You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by traviskds <tr...@gmail.com> on 2013/07/21 18:16:30 UTC

Camel Consumer in JAX-RS Web Service

I find Camel easy for difficult use cases but hard to simple use cases. Or
maybe I haven't still mastered it.

I have a JAX-RS web service that when executed, will dynamically create a
route that reads mail from an IMAP server and then gets processed via a
bean.

My problem is that I need to add Thread.sleep(10000); so that the web
service waits until the route completes. 

My issue is I want a better way to know if the route has completed instead
of setting some arbitrary timer that has the potential for side effects.
(e.g. waiting unnecessarily when the route might have already finished or
even worse existing before the route has time to complete it's work.

I am wondering how others might have done something similar to this
requirement? Any ideas/suggestions are welcome as I have done everything
possible including reading other posts in this forum, looking at the camel
source code and test code without much success.

My main code is below (note I have a JEE6 bootstrap class that starts
CamelContext and which in turn is injected into the below jax-rs service)

@Path("/Mail")
public class ReadMail {

	private static final Logger logger = LoggerFactory
			.getLogger(ReadMail.class);
	
    @Inject
    CdiCamelContext camelContext;

	@Path("/read")
	@GET
	@Produces(MediaType.TEXT_HTML)
	public Response getUser(@Context UriInfo uriInfo) {

		try {

			logger.debug(">>> Reading mail from mail server ..");
			MultivaluedMap<String, String> queryParameters = uriInfo
					.getQueryParameters();
			String mailProtocol = 
queryParameters.getFirst("mailProtocol").toLowerCase();
			String mailHost = queryParameters.getFirst("host").toLowerCase();
			String userName = queryParameters.getFirst("username");
			String password = queryParameters.getFirst("password");
			
			final String MAIL_ENDPOINT_URI = mailProtocol + "://" + mailHost
					+ "?username="+ userName + "&password=" + password + "&delete=false"
					+ "&debugMode=true&unseen=true&consumer.delay=5000";

			final MailBean mailBean = new MailBean();
			
			camelContext.addRoutes(new RouteBuilder() {
				public void configure() throws Exception {
					from(MAIL_ENDPOINT_URI).routeId("myRoute")
					.bean(mailBean, "processMail");
				}
			});
			
			Thread.sleep(10000);

			return
Response.status(Response.Status.OK).entity(mailBean.getMessageBody().toString())
					.build();

		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			try {
				camelContext.stopRoute("myRoute");
				camelContext.removeRoute("myRoute");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return Response.status(Response.Status.NOT_FOUND)
				.entity("Requested search did not return any results").build();

	}

}

My Bean class is

public class MailBean {
	
	private StringBuilder messageBody = new StringBuilder();
	
	public void processMail(Exchange exchange) throws MessagingException,
IOException {
		
                System.out.println(">>>> Inside MailBean exchangeTest >>>>
");
                System.out.println("<<<< Message Id:"+
exchange.getIn().getMessageId());

        this.setMessageBody(this.getMessageBody().append("Message Id:"+
exchange.getIn().getMessageId()+ "<br/><br/>"));

        if (exchange.getIn().getBody() instanceof String) {

        	this.setMessageBody(this.getMessageBody().append(((String)
exchange.getIn().getBody()).replaceAll("(\r\n|\n)", "")+ "<br/><br/>"));

        } else if (exchange.getIn().getBody() instanceof Multipart) {

        
this.setMessageBody(this.getMessageBody().append((Utility.getMultipartText((Multipart)
exchange.getIn().getBody())).replaceAll("(\r\n|\n)","")+ "<br/><br/>"));

        }		
	}
	
	public StringBuilder getMessageBody() {
		return messageBody;
	}
	public void setMessageBody(StringBuilder messageBody) {
		this.messageBody = messageBody;
	}

}





--
View this message in context: http://camel.465427.n5.nabble.com/Camel-Consumer-in-JAX-RS-Web-Service-tp5735968.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Camel Consumer in JAX-RS Web Service

Posted by Sergey Beryozkin <sb...@gmail.com>.
I've been thinking more along these lines:

class ReadMail {

     public Response read(...) {

        MailBean bean = new MailBean();
        new Thread().run(new MyRouteWrapper(bean));
        // block on the current thread
        bean.waitTillDone();



     }

     private MyRouteWrapper implements Runnable {
         // here goes your mail route
         // the last part of this route will call a MailBean method 
which will unblock a waiting readMail thread

     }
}

Something like that...

Cheers, Sergey

On 22/07/13 13:00, traviskds wrote:
> Thanks for responding Sergey.
>
> I assume you mean adding the "to" part of the route.
>
> I did this
>
> 			camelContext.addRoutes(new RouteBuilder() {
> 				public void configure() throws Exception {
> 					from(MAIL_ENDPOINT_URI).routeId("myRoute")
> 					.bean(mailBean, "processMail")
> 					.to("log:mail");
> 				}
> 			});
>
> and no impact. Then I did this
>
> 			camelContext.addRoutes(new RouteBuilder() {
> 				public void configure() throws Exception {
> 					from(MAIL_ENDPOINT_URI).routeId("myRoute")
> 					.to("bean:mailBean?method=processMail");
> 				}
> 			});
>
> and no impact. Note I registered the bean using SimpleRegistry before adding
> it to the route in the 2nd set of code.
>
> But in both instances, and even in my original code when I have
> Thread.sleep(10000); it works.
>
> I am really stuck at this point as what I plan to do is provide JAX-RS
> services as an API Gateway and use Camel for various backend integration and
> if I cannot have Synchronous calls in JAX-RS, it is a show stopper for my
> use cases.
>
> In the Camel In Action book, in page 97-98, Service Activator Pattern, I was
> under the impression when the BeanProcessor is used, then it will make a
> Synchronous call.
>
> I think maybe I am not understanding this correctly.
>
> Any help is appreciated.
>
>
>
>
>
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/Camel-Consumer-in-JAX-RS-Web-Service-tp5735968p5736023.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Re: Camel Consumer in JAX-RS Web Service

Posted by traviskds <tr...@gmail.com>.
Thanks for responding Sergey.

I assume you mean adding the "to" part of the route.

I did this

			camelContext.addRoutes(new RouteBuilder() {
				public void configure() throws Exception {
					from(MAIL_ENDPOINT_URI).routeId("myRoute")
					.bean(mailBean, "processMail")
					.to("log:mail");
				}
			});

and no impact. Then I did this

			camelContext.addRoutes(new RouteBuilder() {
				public void configure() throws Exception {
					from(MAIL_ENDPOINT_URI).routeId("myRoute")
					.to("bean:mailBean?method=processMail");
				}
			});

and no impact. Note I registered the bean using SimpleRegistry before adding
it to the route in the 2nd set of code.

But in both instances, and even in my original code when I have
Thread.sleep(10000); it works.

I am really stuck at this point as what I plan to do is provide JAX-RS
services as an API Gateway and use Camel for various backend integration and
if I cannot have Synchronous calls in JAX-RS, it is a show stopper for my
use cases.

In the Camel In Action book, in page 97-98, Service Activator Pattern, I was
under the impression when the BeanProcessor is used, then it will make a
Synchronous call.

I think maybe I am not understanding this correctly.

Any help is appreciated.

 




--
View this message in context: http://camel.465427.n5.nabble.com/Camel-Consumer-in-JAX-RS-Web-Service-tp5735968p5736023.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Camel Consumer in JAX-RS Web Service

Posted by Sergey Beryozkin <sb...@gmail.com>.
Can you add a final component to that mail route which will simply 
notify this ReadMail resource that the route is done ?

Sergey
On 21/07/13 17:16, traviskds wrote:
> I find Camel easy for difficult use cases but hard to simple use cases. Or
> maybe I haven't still mastered it.
>
> I have a JAX-RS web service that when executed, will dynamically create a
> route that reads mail from an IMAP server and then gets processed via a
> bean.
>
> My problem is that I need to add Thread.sleep(10000); so that the web
> service waits until the route completes.
>
> My issue is I want a better way to know if the route has completed instead
> of setting some arbitrary timer that has the potential for side effects.
> (e.g. waiting unnecessarily when the route might have already finished or
> even worse existing before the route has time to complete it's work.
>
> I am wondering how others might have done something similar to this
> requirement? Any ideas/suggestions are welcome as I have done everything
> possible including reading other posts in this forum, looking at the camel
> source code and test code without much success.
>
> My main code is below (note I have a JEE6 bootstrap class that starts
> CamelContext and which in turn is injected into the below jax-rs service)
>
> @Path("/Mail")
> public class ReadMail {
>
> 	private static final Logger logger = LoggerFactory
> 			.getLogger(ReadMail.class);
> 	
>      @Inject
>      CdiCamelContext camelContext;
>
> 	@Path("/read")
> 	@GET
> 	@Produces(MediaType.TEXT_HTML)
> 	public Response getUser(@Context UriInfo uriInfo) {
>
> 		try {
>
> 			logger.debug(">>> Reading mail from mail server ..");
> 			MultivaluedMap<String, String> queryParameters = uriInfo
> 					.getQueryParameters();
> 			String mailProtocol =
> queryParameters.getFirst("mailProtocol").toLowerCase();
> 			String mailHost = queryParameters.getFirst("host").toLowerCase();
> 			String userName = queryParameters.getFirst("username");
> 			String password = queryParameters.getFirst("password");
> 			
> 			final String MAIL_ENDPOINT_URI = mailProtocol + "://" + mailHost
> 					+ "?username="+ userName + "&password=" + password + "&delete=false"
> 					+ "&debugMode=true&unseen=true&consumer.delay=5000";
>
> 			final MailBean mailBean = new MailBean();
> 			
> 			camelContext.addRoutes(new RouteBuilder() {
> 				public void configure() throws Exception {
> 					from(MAIL_ENDPOINT_URI).routeId("myRoute")
> 					.bean(mailBean, "processMail");
> 				}
> 			});
> 			
> 			Thread.sleep(10000);
>
> 			return
> Response.status(Response.Status.OK).entity(mailBean.getMessageBody().toString())
> 					.build();
>
> 		} catch (Exception e) {
> 			e.printStackTrace();
> 		}
> 		finally {
> 			try {
> 				camelContext.stopRoute("myRoute");
> 				camelContext.removeRoute("myRoute");
> 			} catch (Exception e) {
> 				e.printStackTrace();
> 			}
> 		}
>
> 		return Response.status(Response.Status.NOT_FOUND)
> 				.entity("Requested search did not return any results").build();
>
> 	}
>
> }
>
> My Bean class is
>
> public class MailBean {
> 	
> 	private StringBuilder messageBody = new StringBuilder();
> 	
> 	public void processMail(Exchange exchange) throws MessagingException,
> IOException {
> 		
>                  System.out.println(">>>> Inside MailBean exchangeTest >>>>
> ");
>                  System.out.println("<<<< Message Id:"+
> exchange.getIn().getMessageId());
>
>          this.setMessageBody(this.getMessageBody().append("Message Id:"+
> exchange.getIn().getMessageId()+ "<br/><br/>"));
>
>          if (exchange.getIn().getBody() instanceof String) {
>
>          	this.setMessageBody(this.getMessageBody().append(((String)
> exchange.getIn().getBody()).replaceAll("(\r\n|\n)", "")+ "<br/><br/>"));
>
>          } else if (exchange.getIn().getBody() instanceof Multipart) {
>
>
> this.setMessageBody(this.getMessageBody().append((Utility.getMultipartText((Multipart)
> exchange.getIn().getBody())).replaceAll("(\r\n|\n)","")+ "<br/><br/>"));
>
>          }		
> 	}
> 	
> 	public StringBuilder getMessageBody() {
> 		return messageBody;
> 	}
> 	public void setMessageBody(StringBuilder messageBody) {
> 		this.messageBody = messageBody;
> 	}
>
> }
>
>
>
>
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/Camel-Consumer-in-JAX-RS-Web-Service-tp5735968.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>


Re: Camel Consumer in JAX-RS Web Service

Posted by traviskds <tr...@gmail.com>.
Thanks Sergey and Claus.

Using both of your suggestions (i.e. running the routes in a new thread and
using the onCompletion, I was able to get it to work, sort of :(

What I notice is that the onCompletion does not fire after all the mails are
received, but after 2-3 mails. (it is not consistent)

This made me think a little bit about routes and if it works per email
message. 

If that is the case, then I may need to use an aggregator strategy. I am
going to try that now but do you think I am on the correct path and my
understanding on routes being one message at a time correct?

Sorry if these are dumb questions as I am on this Camel learning curve (or
should I say trying to ride the Camel)



--
View this message in context: http://camel.465427.n5.nabble.com/Camel-Consumer-in-JAX-RS-Web-Service-tp5735968p5736190.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Camel Consumer in JAX-RS Web Service

Posted by Claus Ibsen <cl...@gmail.com>.
You can look at using onCompletion or event notifier. Or even the NotifyBuilder.

You can find details on the Camel site using the search box on the front page.

On Sun, Jul 21, 2013 at 6:16 PM, traviskds <tr...@gmail.com> wrote:
> I find Camel easy for difficult use cases but hard to simple use cases. Or
> maybe I haven't still mastered it.
>
> I have a JAX-RS web service that when executed, will dynamically create a
> route that reads mail from an IMAP server and then gets processed via a
> bean.
>
> My problem is that I need to add Thread.sleep(10000); so that the web
> service waits until the route completes.
>
> My issue is I want a better way to know if the route has completed instead
> of setting some arbitrary timer that has the potential for side effects.
> (e.g. waiting unnecessarily when the route might have already finished or
> even worse existing before the route has time to complete it's work.
>
> I am wondering how others might have done something similar to this
> requirement? Any ideas/suggestions are welcome as I have done everything
> possible including reading other posts in this forum, looking at the camel
> source code and test code without much success.
>
> My main code is below (note I have a JEE6 bootstrap class that starts
> CamelContext and which in turn is injected into the below jax-rs service)
>
> @Path("/Mail")
> public class ReadMail {
>
>         private static final Logger logger = LoggerFactory
>                         .getLogger(ReadMail.class);
>
>     @Inject
>     CdiCamelContext camelContext;
>
>         @Path("/read")
>         @GET
>         @Produces(MediaType.TEXT_HTML)
>         public Response getUser(@Context UriInfo uriInfo) {
>
>                 try {
>
>                         logger.debug(">>> Reading mail from mail server ..");
>                         MultivaluedMap<String, String> queryParameters = uriInfo
>                                         .getQueryParameters();
>                         String mailProtocol =
> queryParameters.getFirst("mailProtocol").toLowerCase();
>                         String mailHost = queryParameters.getFirst("host").toLowerCase();
>                         String userName = queryParameters.getFirst("username");
>                         String password = queryParameters.getFirst("password");
>
>                         final String MAIL_ENDPOINT_URI = mailProtocol + "://" + mailHost
>                                         + "?username="+ userName + "&password=" + password + "&delete=false"
>                                         + "&debugMode=true&unseen=true&consumer.delay=5000";
>
>                         final MailBean mailBean = new MailBean();
>
>                         camelContext.addRoutes(new RouteBuilder() {
>                                 public void configure() throws Exception {
>                                         from(MAIL_ENDPOINT_URI).routeId("myRoute")
>                                         .bean(mailBean, "processMail");
>                                 }
>                         });
>
>                         Thread.sleep(10000);
>
>                         return
> Response.status(Response.Status.OK).entity(mailBean.getMessageBody().toString())
>                                         .build();
>
>                 } catch (Exception e) {
>                         e.printStackTrace();
>                 }
>                 finally {
>                         try {
>                                 camelContext.stopRoute("myRoute");
>                                 camelContext.removeRoute("myRoute");
>                         } catch (Exception e) {
>                                 e.printStackTrace();
>                         }
>                 }
>
>                 return Response.status(Response.Status.NOT_FOUND)
>                                 .entity("Requested search did not return any results").build();
>
>         }
>
> }
>
> My Bean class is
>
> public class MailBean {
>
>         private StringBuilder messageBody = new StringBuilder();
>
>         public void processMail(Exchange exchange) throws MessagingException,
> IOException {
>
>                 System.out.println(">>>> Inside MailBean exchangeTest >>>>
> ");
>                 System.out.println("<<<< Message Id:"+
> exchange.getIn().getMessageId());
>
>         this.setMessageBody(this.getMessageBody().append("Message Id:"+
> exchange.getIn().getMessageId()+ "<br/><br/>"));
>
>         if (exchange.getIn().getBody() instanceof String) {
>
>                 this.setMessageBody(this.getMessageBody().append(((String)
> exchange.getIn().getBody()).replaceAll("(\r\n|\n)", "")+ "<br/><br/>"));
>
>         } else if (exchange.getIn().getBody() instanceof Multipart) {
>
>
> this.setMessageBody(this.getMessageBody().append((Utility.getMultipartText((Multipart)
> exchange.getIn().getBody())).replaceAll("(\r\n|\n)","")+ "<br/><br/>"));
>
>         }
>         }
>
>         public StringBuilder getMessageBody() {
>                 return messageBody;
>         }
>         public void setMessageBody(StringBuilder messageBody) {
>                 this.messageBody = messageBody;
>         }
>
> }
>
>
>
>
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/Camel-Consumer-in-JAX-RS-Web-Service-tp5735968.html
> Sent from the Camel - Users mailing list archive at Nabble.com.



-- 
Claus Ibsen
-----------------
Red Hat, Inc.
Email: cibsen@redhat.com
Twitter: davsclaus
Blog: http://davsclaus.com
Author of Camel in Action: http://www.manning.com/ibsen