How to test a custom processor - Apache Camel Spring Test - spring

I have the following route:
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="activemq:topic:inbox" />
<log message="To: ${in.header.recipients}" />
<to uri="bean:myLogger" />
</route>
</camelContext>
bean:myLogger is my custom processor for formatting the log messages I am getting. The process method in my custom processor simply calls a private method that appends the type of message (e.g. CC) and the recipients' email. I am struggling to see how to test the actual resulting logs. I am using CamelSpringTestSupportand I am OK when it comes to testing the myLogger endpoint:
#Produce(uri = "activemq:topic:inbox")
protected ProducerTemplate template;
#Override
protected AbstractApplicationContext createApplicationContext() {
return new ClassPathXmlApplicationContext("file:src/main/resources/my-camel-context.xml");
}
#Test
public void testLogEndpoint() throws Exception {
String body = "Hello World";
template.sendBody("activemq:topic:inbox", body);
LOG.info("This is the message body we sent {} ", body);
}
However, I am not really sure how to test the format of the returned logs. Do I send the email of the recipients in a similar fashion as the example above? But then how do I check whether the format is the correct one? I am really looking more for the approach than the actual solution.
Thank you so much for your help,
I.

Make the log formatting in the bean independent on the logger such as another public/package method and then write a plain unit test that tests this method. Then you don't need to use Camel in that test at all.
If you can't do that, then maybe configure the logger to log to a file, and then read that file afterwards and test its logged as you want.

Related

Spring AsyncUncaughtExceptionHandler : Show error on JSF page

My email-sending code (a Spring managed bean) is executed asychronous (using Springs #Async Annotation) because our email-server seems rather slow (takes 3-4 seconds until the mail is sent). The email method throws an checked excpetion if the email cannot be sent.
Now I'm sending emails from my JSF-managed bean (i.e. my controller), e.g. to send credentials to newly created users and want to show a growl Message to inform the (admin-)user that the email sending code threw an excpetion (I know that there will be a delay, but thats seems ok as it does not block the gui thread).
What I've done so far:
I implemented my custom AsyncUncaughtExceptionHandler, i.e. the method:
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
#Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
// inform user that something went wrong (growl message)
}
}
This handler is then specified in Spring's XML config:
<bean id="exceptionHandler" class="org.myproject.util.CustomAsyncExceptionHandler" />
<task:annotation-driven executor="asyncExecutor" scheduler="asyncScheduler" exception-handler="exceptionHandler" />
<task:executor id="asyncExecutor" pool-size="5" />
<task:scheduler id="asyncScheduler" pool-size="10" /
The problem is that I cannot access the FacesContext in this exceptionHandler (which is a spring-managed bean).
How can I do this and if not, is there another way to let the user know that the async method threw an excpetion?

Camel & CXF & REST: ERROR No message body writer has been found for class java.util.ArrayList, ContentType: application/json

In my Spring configuration file:
<bean id="jacksonJsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />
<bean id="restJacksonProviderList" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="jacksonJsonProvider"/>
</list>
</constructor-arg>
</bean>
//......
<route id="RestMyRoute">
<from id="RestRequest" uri="cxfrs:/rest/MyService?resourceClasses=com.myself.services.MyService&bindingStyle=SimpleConsumer&providers=#restJacksonProviderList" />
<to uri="direct:doRoute" />
</route>
The Service interface:
#GET
#Path("/my/something/{id}")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#WebMethod
#WebResult(name = "getSomethingResponse")
public List<MySomething> getSomething(
#PathParam("id") #WebParam(name = "id") String id);
The code above works! I can send the get request to the URl and I get a JSON response.
Now, I do a small change: Instead of defining the web service's URL (and the route) by XML configuration, I define them by Java code:
public class MyRoute extends RouteBuilder {
private String uriRest = "cxfrs:/rest/MyService?resourceClasses=com.myself.services.MyService&bindingStyle=SimpleConsumer&providers=#restJacksonProviderList";
#Override
public void configure() throws Exception {
from(uriRest).
to("log:input").
to("direct:doRoute").
to("log:output");
}
}
When I hit the web service URL, I am getting 500 Internal Server Error and in the logs (Tomcat) I see JAXRSUtils ERROR No message body writer has been found for class java.util.ArrayList, ContentType: application/json
Actually the debugger tells me that defining the URI by Java code is recognized, since I do hit the code inside the route.
I saw this error in many answers here, basically they say to add a Json provider and assign it to the CXF endpoint.
Seems to me like it is what I have done. But it does not work.
Any idea what I am doing wrong here?
As peeskillet said, it's because there isn't a list of providers registered under the name restJacksonProviderList. You can get the JndiContext like this and bind a list to it in the configure method of your routebuilder:
JndiContext registry = (JndiRegistry) context.getRegistry();
registry.bind("restJacksonProviderList", Arrays.asList(new JacksonJsonProvider()));
Edit after comments:
Change & for & in your cxfrs uri definition, & is only needed in xml.

Camel: forward message to dynamic destinations (from database)

I am using camel 2.8.4 in my app. my app will receive request from a queue, then the request will be validated by a Validator. Base on the content of the message, the Validator will forward the request to different destinations. Validator will be a POJO bean. Destinations will be get from database (this is a MUST). I prefer to use spring dsl for camelContext.
1. I dont know how to write the validator to forward req to destinations.
2. Can we use something similar like this
<to uri='method=getURI() bean='Validator''> in camelContext
<camelContext>
<route id="route-1">
<from uri="mq:queue:QUEUE"/>
<bean ref="Validator" method="validate"/>
<!--i would be great if we can use <to uri="dynamicURI-from-database"> here -->
</route>
</camelContext>
Class Validator{
public void validate(String req){
if (...)
//get uri1 from database
String uri1=getURI(..);
//forward req to uri1
...........
else
//get uri2 from database
String uri2=getURI(...);
//forward req to uri2
...........
}
public String getURI(..){
......
return uri;
}
}
Use the dynamic URI feature to generate a URI at runtime. You can invoke a processor which sets the URI in exchange and then use that in the to clause.
Something like :
process(new Procesor()
public void process(Exchange exchange){
exchange.setHeader("myURI",someURI);
});
and in the to clause
<to uri="${header.myURI}"/>
Did you have a look at the dynamic recipient list pattern: http://camel.apache.org/recipient-list.html ?
You can use toD provided the destination endpoints are Http APIs. Please refer the link : https://camel.apache.org/components/latest/eips/toD-eip.html

GWT does not work with Spring REST service

I wrote a Spring REST application. I tested it with curl command and it worked truly.
In another GWT Ajax application I have an RequestBuilder object that it does not work with my Spring Rest: after calling sendRequest method, the event onResponseReceived is fired but the getText method returns an empty string.
this is a part of my spring servlet.xml configuration file
<bean id="jsonmembertemplate"
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" >
<property name="contentType" value="text/javascript;charset=UTF-8"/>
<property name="disableCaching" value="false"/>
</bean>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
and a part of my controller class
#RequestMapping(method = RequestMethod.GET, value="/member/get/{memberid}")
public String getMember(Model model, #PathVariable("memberid") int id, HttpServletResponse response) {
model.addAttribute("member", memberDao.get(id));
return "jsonmembertemplate";
}
and gwt code
private RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, "http://localhost:8080/depna-nat-server/member/get/1?");
try {
rb.setHeader("Content-Type", "text/javascript;charset=UTF-8");
rb.sendRequest(null, new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
Window.alert(Integer.toString(response.getStatusCode()));
Window.alert(response.getStatusText());
Window.alert(Integer.toString(response.getText().length()));
area.setText(response.getText());
}
#Override
public void onError(Request request, Throwable exception) {
Window.alert("fail");
}
});
} catch (RequestException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I have a couple of gwt applications working with json and xml rest services offered by spring, we use spring instead of gwt (rpc or rf) because these services are offered to 3party apps as well.
I started my first project with RequestBuilder and we dind't have any problem, so maybe you have some issue in your code, could you inspect the traffic and post the errors you have?
If you are running a cross-domain issue (statusCode=0 normally means it) , add a filter to your servlet container, take a look to this document.
I finally opted to use gwtquery-ajax and gquery-data-binding because it made really easy to consume these services and to map them to java objects.

Exception handler for REST controller in spring

I want to handle exceptions so the URL information is automatically shown to the client. Is there an easy way to do this?
<bean id="outboundExceptionAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver">
<!-- what property to set here? -->
</bean>
You have two choices:
Spring Reference 15.9.1 HandlerExceptionResolver
Spring HandlerExceptionResolvers ease the pain of unexpected
exceptions that occur while your request is handled by a controller
that matched the request. HandlerExceptionResolvers somewhat resemble
the exception mappings you can define in the web application
descriptor web.xml. However, they provide a more flexible way to
handle exceptions. They provide information about which handler was
executing when the exception was thrown. Furthermore, a programmatic
way of handling exceptions gives you more options for responding
appropriately before the request is forwarded to another URL (the same
end result as when you use the servlet specific exception mappings).
The HandlerExceptionResolver has one method, containing everything you need:
HandlerExceptionResolver.resolveException(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex)
Or if you need different handlers for different controllers: Spring Reference Chapter 15.9.2 #ExceptionHandler
#ExceptionHandler(IOException.class)
public String handleIOException(IOException ex, HttpServletRequest request) {
return "every thing you asked for: " + request;
}
Short question short answer
I'm doing the following trick:
#ExceptionHandler(Exception.class)
public ModelAndView handleMyException(Exception exception) {
ModelAndView mv = new ModelAndView("redirect:errorMessage?error="+exception.getMessage());
return mv;
}
#RequestMapping(value="/errorMessage", method=RequestMethod.GET)
#Responsebody
public String handleMyExceptionOnRedirect(#RequestParamter("error") String error) {
return error;
}
Works flawless.

Resources