Property set at one endpoint in the Camel Exchange is not available in another endpoint in the Camunda Workflow - apache-camel

I am calling a camel endpoint from the service task in a Camunda BPM workflow, and then an external HTTP request is sent to an endpoint and the response is saved as a property in the camel exchange, but the property is not propagated ?
#Override
public void configure() throws Exception {
from("direct:preferredPaymentMethod")
.log("PreferredPaymentMethodRoute")
.bean(PreferredPaymentMethodTransformation.class, "transform")
.setHeader(Exchange.HTTP_QUERY, simple("related.id=${in.headers.relatedId}"))
.marshal().json(JsonLibrary.Jackson)
.to("http4://localhost:9090/paymentMethods/v1/paymentMethod")
.id("PreferredPaymentMethod-http")
.unmarshal(jsonDataFormat)
.convertBodyTo(PaymentMethodResponseBean.class)
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
Map<String, Object> preferredPaymentMethodResponse = new HashMap<>();
preferredPaymentMethodResponse.put("responseCode", exchange.getIn().getHeaders().get(Exchange.HTTP_RESPONSE_CODE));
preferredPaymentMethodResponse.put("response", exchange.getIn().getBody(PaymentMethodResponseBean.class));
exchange.setProperty("preferredPaymentMethodResponse", preferredPaymentMethodResponse);
}
})
.bean(PreferredPaymentMethodTransformation.class, "processResponse")
.id("PreferredPaymentMethod-processResponse")
.routeId("PreferredPaymentMethodRoute");
}
I even tried setting the property in the bean method processResponse.

Related

Apache Camel: pollEnrich does not call dynamic URI

I have a route to poll the email from the server. In the FunctionRoute I am trying to pass the subject of the email I want to fetch by the IMAP protocol using pollEnrich method in the EmailPollingRoute. Currently I am facing problem to make a dynamic URI endpoint. I noticed the headers are being cleared before calling the pollEnrich method. Therefore I tried to use the ${exchangeProperty.subject} but there is no email is fetched. When I set the subject directly in the endpoint as String then the email is being fetched.
How can I set the subject dynamically in the pollEnrich method? The subject is being passed from the FunctionRoute to EmailPollingRoute route.
I appreciate any help
#Component
public class FunctionRoute extends EmailPollingRoute {
static final Logger LOGGER = LoggerFactory.getLogger(FunctionRoute.class);
#Override
public void configure() throws Exception {
from("direct:process_polling_email_function")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
subject = "ABCD - Test1";
exchange.setProperty("ABCD - Test1");
LOGGER.info("1. subject - " + subject);
}})
//.setProperty("subject", constant("ABCD - Test1"))
//.setHeader("subject", simple("ABCD - Test1"))
.to("direct:process_polling_email");
}
}
#Component
public class EmailPollingRoute extends BaseRouteBuilder {
static final Logger LOGGER = LoggerFactory.getLogger(EmailPollingRoute.class);
public String subject;
#Override
public void configure() throws Exception {
//super.configure();
//2362
//#formatter:off
from("direct:process_polling_email")
.routeId("routeId_EmailPollingRoute")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
subject = exchange.getProperty("subject", String.class);
LOGGER.info("0001 - subjectB: (" + subject + ")");
}})
.pollEnrich("imaps://XXXXXXX.info"
+ "?username=XXXXX&"
+ "password=XXXXXXX&"
+"folderName=Inbox/Test&"
+"searchTerm.fromSentDate=now-72h&"
+"searchTerm.subject=${exchangeProperty.subject}&"
+"fetchSize=1");
.to("log:newmail");
//#formatter:on
}
}
You can set pollEnrich URI dynamically using simple method, you can also specify timeout in similar way.
.pollEnrich()
.simple("imaps://XXXXXXX.info"
+ "?username=XXXXX&"
+ "password=XXXXXXX&"
+"folderName=Inbox/Test&"
+"searchTerm.fromSentDate=now-72h&"
+"searchTerm.subject=${exchangeProperty.subject}&"
+"fetchSize=1")
.timeout(1000);

camel calling to rest service, body is empty

My camel project receives an url, it acts as a proxy and sends a GET petition to a rest service with a route definition like this:
rest("/car")
.get("/{id}")
.param().name("id").type(RestParamType.path)
.dataType("int").endParam()
.to("http://0.0.0.0:8081?bridgeEndpoint=true")
.consumes("application/json")
.to("direct:jsoncar");
from("direct:jsoncar")
.streamCaching()
.log("log:${body}")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
String data = exchange.getIn().getBody(String.class);
...
...
}
});
The rest service sends back a json in a stream. The problem is that body is always empty. I have tried it in many ways:
from("direct:jsoncar")
.streamCaching()
.setHeader(Exchange.CONTENT_TYPE,constant("text/json"))
.marshal().json(JsonLibrary.Jackson, true)
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
String dto = exchange.getIn().getBody(String.class);
...
});
But it is always empty.
Please, any body has any idea of the nature of the problem?

Spring Security with REST architecture

I have been looking into a problem with Spring Security for a REST API. And before jumping into implementation I would like to get an expert advice or some sample project on github, if available.
My application will be based on REST API. And will be accessed by two clients:
Mobile Phone
Web
If I create a REST API with custom login page, then it will always be redirected to Web (as per my understanding). What when I will start consuming it with Mobile Phone?
.formLogin()
.defaultSuccessUrl("/ui/index.html#/app/dashboard")
.loginProcessingUrl("/api/upuser/verifyUser")
.usernameParameter("username")
.passwordParameter("password")
.successHandler(new AjaxAuthenticationSuccessHandler(new SavedRequestAwareAuthenticationSuccessHandler()))
.loginPage("/ui/index.html#/access/signin")
I think from the above code it seems quite obvious that this application will be accessed from two different locations:
localhost:8080/api/ for API
localhost:8383/ui/ for WEB (Angular JS)
But, I will move both to localhost/api/ & localhost/ui/ by using nginx. So, above two will be accessed by
localhost/api/
localhost/ui/
So, my second question is what will be the best way to implement spring security:
Token Based Authentication
Session Based Authentication
Problem is as it's a stateless service so how we are going to implement session based Authentication?
Try something like this :
You should try this, may be it will help you:
#Configuration
#EnableWebSecurity
#Profile("container")
public class SOAPSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationProvider authenticationProvider;
#Autowired
private AuthenticationProvider authenticationProviderDB;
#Override
#Order(1)
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
#Order(2)
protected void ConfigureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProviderDB);
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/scripts/**","/styles/**","/images/**","/error/**");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/rest/**").authenticated()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.successHandler(new AuthenticationSuccessHandler() {
#Override
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication a) throws IOException, ServletException {
//To change body of generated methods,
response.setStatus(HttpServletResponse.SC_OK);
}
})
.failureHandler(new AuthenticationFailureHandler() {
#Override
public void onAuthenticationFailure(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException ae) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
})
.loginProcessingUrl("/access/login")
.and()
.logout()
.logoutUrl("/access/logout")
.logoutSuccessHandler(new LogoutSuccessHandler() {
#Override
public void onLogoutSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication a) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
})
.invalidateHttpSession(true)
.and()
.exceptionHandling()
.authenticationEntryPoint(new Http403ForbiddenEntryPoint())
.and()
.csrf()//Disabled CSRF protection
.disable();
}
}

How to mock cxfbean call in Apache Camel?

I've got route that calls cxfbean:
.to("cxfbean:reservationService")
Tried mock this in my test with
#EndpointInject(uri = "mock:reservationService")
MockEndpoint reservationSystemMock;
#BeforeMethod
private void setUpContext() throws Exception
{
context.getRouteDefinition( "send.to.res.svc.endpoint" ).adviceWith(
context, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception
{
interceptSendToEndpoint("cxfbean:reservationService")
.skipSendToOriginalEndpoint()
.to("mock:reservationService");
}
});
}
Also tried mock with weaveByToString( "**reservationService" ).replace().to( "mock:reservationService" );. In both cases I get:
Caused by: org.apache.camel.NoSuchBeanException: No bean could be found in the registry for: reservationService
I'd like to test my route without cxf bean instantiation. I'm using CamelTestSupport class as parent.
Managed to mock cxfbean endpoint with weaveByToString( "To[cxfbean:reservationService]" ):
#EndpointInject(uri = "mock:reservationService")
protected MockEndpoint reservationSystemMock;
#BeforeMethod
private void setUpContext() throws Exception
{
context.getRouteDefinition( "send.to.res.svc.endpoint" ).adviceWith(
context, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
weaveByToString( "To[cxfbean:reservationService]" )
.replace().to( "mock:reservationService" );
}
});
}
Also seems that we can peek necessary expression for weaveByToString using context.getRouteDefinitions().get(0).toString() in debug watcher
Remember to turn on advice-with on your test class. If you use those annotations, then add #UseAdviceWith to the class.
And then start the camel context after you have advised, which
http://camel.apache.org/spring-testing.html
http://camel.apache.org/advicewith.html

How to do load balancing using apache camel

I tried to achieve load balancing using camel and using the below code to get the response from server.But, the rest service is not called.
CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder() {
public void configure() {
System.out.println("inside configure....");
from(
"http://localhost:9876/LunaHSMLoadBalancer/csr/getSignature")
.loadBalance()
.roundRobin()
.to("http://localhost:8080/test/services/token/signature",
"http://10.65.49.216:8080/test/services/token/signature");
}
});
context.start();
Thread.sleep(900000);
context.stop();

Resources