1 2 3 Previous Next 34 Replies Latest reply on Sep 14, 2009 3:59 PM by muellerc

    How to use camel-jaxb in fuse esb (4.1.0.0)

    muellerc

      Hi folks!

       

      In a simple project, I would consume a xml file with camel-file from the file system, marshal the body with camel-jaxb to a domain object and then call a osgi service with this domain object.

      But if I unmarshal the body, I receive always an exception, depending on wath I try:

       

      My starting point was a simple "file move route". This route works great.

       

      from("/tmp/events/incoming/")

      .to("/tmp/events/outgoing");

       

      Now, I create my schema (with namespaces) an generate the java code with the maven-jaxb2-plugin. After that, I create the jaxb.index file, added my domain model name and put it into the correct subdirectory under my src/main/resources directory. At the end, I installed the camel-jaxb feature in FUSE ESB.

       

      case 1:

      I read the doc http://fusesource.com/docs/router/1.6/defining_routes/FMRS.TMC.html and try it.

       

      from("/tmp/events/incoming/")

      .unmarshal(new org.apache.camel.model.dataformat.JaxbDataFormat())

      .to("/tmp/events/outgoing");

       

      But this class has no constructor which takes a string (typo?), so I use the default constructor. But I receive the following exception:

       

      22:54:18,631 | WARN  | Component@64b7e3 | ResolverUtil                     | g.apache.camel.util.ResolverUtil  517 | Could not find class 'org/apache/servicemix/nmr/core/converter/StringSourceConverter.class' in any classloaders:

      ...

      22:54:18,645 | ERROR | Component@64b7e3 | DeadLetterChannel                | rg.apache.camel.processor.Logger  203 | Failed delivery for exchangeId: ID-chris/50428-1241953976871/0-19. On delivery attempt: 0 caught: java.io.IOException: unexpected element (uri:"http://ps4b.de/rfid/model/Matrics", local:"Matrics"). Expected elements are (none)

      java.io.IOException: unexpected element (uri:"http://ps4b.de/rfid/model/Matrics", local:"Matrics"). Expected elements are (none)

              at org.apache.camel.util.IOHelper.createIOException(IOHelper.java:85)

       

       

      case 2:

      Because I think in case 1 was a type, I use the org.apache.camel.converter.jaxb.JaxbDataFormat instead

       

      from("/tmp/events/incoming/")

      .unmarshal(new org.apache.camel.converter.jaxb.JaxbDataFormat("de.ps4b.rfid.model.matrics"))

      .to("/tmp/events/outgoing");

       

      But again, I receive an exception:

       

      23:02:42,912 | WARN  | Component@db7208 | ResolverUtil                     | g.apache.camel.util.ResolverUtil  517 | Could not find class 'org/apache/servicemix/nmr/core/converter/StringSourceConverter.class'

      ...

      23:02:42,943 | ERROR | Component@db7208 | DeadLetterChannel                | rg.apache.camel.processor.Logger  203 | Failed delivery for exchangeId: ID-chris/50428-1241953976871/0-20. On delivery attempt: 0 caught: org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: class org.apache.camel.component.file.FileMessage to the required type: java.io.InputStream with value FileMessage: /Applications/apache-servicemix-4.1.0.0-fuse/incomingEvents/sample_event.xml

      org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: class org.apache.camel.component.file.FileMessage to the required type: java.io.InputStream with value FileMessage: /Applications/apache-servicemix-4.1.0.0-fuse/incomingEvents/sample_event.xml

              at org.apache.camel.impl.converter.DefaultTypeConverter.doConvertTo(DefaultTypeConverter.java:147)

       

       

      case 3:

      I searched the web and found an article at DZone: http://architects.dzone.com/articles/apache-camel-integration?page=0,0.

      So, my route now looks like:

       

      from("/tmp/events/incoming/")

      .convertBodyTo(String.class)

      .unmarshal(new org.apache.camel.converter.jaxb.JaxbDataFormat("de.ps4b.rfid.model.matrics"))

      .to("/tmp/events/outgoing");

       

      But I receive the same exception like case 2.

       

       

      case 4:

       

      I read, that camel use a JAXB fallback Type Converter (I think if the class has a @XmlRootElement annotation) http://camel.apache.org/etl-example.html. So, I try the following route:

       

      from("/tmp/events/incoming/")

      .convertBodyTo(Matrics.class)

      .to("/tmp/events/outgoing");

       

      And I got a warning, but the file was moved:

       

      23:24:45,717 | WARN  | Component@f0fef9 | ConvertBodyProcessor             | l.processor.ConvertBodyProcessor   46 | Could not convert body of IN message: FileMessage: /Applications/apache-servicemix-4.1.0.0-fuse/incomingEvents/sample_event2.xml to type: de.ps4b.rfid.model.matrics.Matrics

       

       

      case 5:

       

      Ok, let me see what is the body class:

       

      from("/tmp/events/incoming/")

      .convertBodyTo(Matrics.class)

      .process(new Processor() {

           public void process(Exchange exchange) throws Exception {

                logger.info("the body class is: " + exchange.getIn().getBody().getClass());

           }

      })

      .to("/tmp/events/outgoing");

       

      And I got:

       

      23:30:42,327 | INFO  | Component@61c570 | FileEventReader                  | ps4b.rfid.file.FileEventReader$1   38 | the body class is: class java.io.File

       

       

      What can I do to receive my Matrics object? Any idea what is wrong or has anyone a running sample for me which can adopt?

       

      Thank you for your help,

      Christian

        • 1. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
          janstey

          Hi Christian,

           

          I hacked up the example in my article a bit to demonstrate loading a file into a domain object (see attached). To try it out run mvn clean camel:run on the command line and in a separate window copy a file message like

           

          janstey@mojo:/x1/fuse/rider-auto-example$ cp src/data/message1.xml target/placeorder/
          

           

           

          The XML message will be loaded into an Order domain object as shown by the output

           

          the body class is: class org.fusesource.camel.Order
          

           

          So the example route looks like

           

          JaxbDataFormat jaxb = new JaxbDataFormat("org.fusesource.camel");
          
          from("file:target/placeorder")
            .convertBodyTo(String.class)
            .unmarshal(jaxb)
            .process(new Processor() {
              public void process(Exchange exchange) throws Exception {
                  System.out.println("the body class is: " + exchange.getIn().getBody().getClass());
              }
            });
          

           

          Hope this helps.

           

          Cheers,

          Jon

          • 2. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
            muellerc

            Hi Jonathan,

             

            thank you for your help.

            I found your article and the sample project at DZone (http://architects.dzone.com/articles/apache-camel-integration?page=0,0). It is good and work great (also on my machine).

            It works also with small modifications, I made (like yours in your post).

            Now, I will replace your order JAXB model with my more complex JAXB domain object. If it work, I will deploy this route to FUSE ESB.

             

            I will keep you informed...

             

            Cheers,

            Christian

            • 3. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
              muellerc

              Hi all,

               

              I don't know, what is wrong...

               

              In my camel project, my route works great, but in my fuse esb project, the route did not work.

               

              23:19:41,680 | WARN  | Component@47712b | ResolverUtil                     | g.apache.camel.util.ResolverUtil  517 | Could not find class 'org/apache/servicemix/nmr/core/converter/StringSourceConverter.class' in any classloaders:

              ...

              23:19:41,702 | WARN  | Component@47712b | ConvertBodyProcessor             | l.processor.ConvertBodyProcessor   46 | Could not convert body of IN message: FileMessage: /Applications/apache-servicemix-4.1.0.0-fuse/incomingEvents/sample_event.xml to type: de.ps4b.rfid.model.matrics.Matrics

               

               

              My camel route in my pure camel project looks like (see my sample project in my-camel-sandbox.zip):

               

              from("file:target/events/in")

              .convertBodyTo(Matrics.class)

              .process(new Processor() {

                   public void process(Exchange exchange) throws Exception {

                        System.out.println("the body class is " + exchange.getIn().getBody().getClass());

                   }

              })

              .to("file:target/events/out");

               

              and it works great. And in my fuse esb project (see my sample project in file-event-reader.zip), my camel route looks like:

               

              from("file:/Applications/apache-servicemix-4.1.0.0-fuse/incomingEvents/")

              .convertBodyTo(Matrics.class)

              .process(new Processor() {

                   public void process(Exchange exchange) throws Exception {

                        logger.info("the body class is: " + exchange.getIn().getBody().getClass());

                   }

              })

              .to("file:/Applications/apache-servicemix-4.1.0.0-fuse/outgoingEvents/");

               

              and it does't work.

               

              Any idea what's wrong or missing (some additional osgi bundles in fuse esb what I have to install)?

               

              Thank you for your help,

              Christian

              • 4. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
                janstey

                Took a quick look at your project and got it working to the point of loading the XML message into a Matrics object. I first had to load the camel-jaxb bundle

                osgi install -s mvn:org.apache.camel/camel-jaxb/1.6.0.0-fuse
                

                and then your file-event-reader bundle. I changed your route to

                JaxbDataFormat jaxb = new JaxbDataFormat("de.ps4b.rfid.model.matrics");
                from("file:/Applications/apache-servicemix-4.1.0.0-fuse/incomingEvents/")
                  .convertBodyTo(String.class)
                  .unmarshal(jaxb)
                  .process(new Processor() {
                        public void process(Exchange exchange) throws Exception {
                            logger.info("the body class is: " + exchange.getIn().getBody().getClass());
                        }
                  });
                

                This outputs

                the body class is: class de.ps4b.rfid.model.matrics.Matrics
                

                I couldn't actually get the Matrics object marshaled back into XML for saving to a file though. Unfortunately I don't have any more time to debug this today... hope that this gets you a bit further. Keep me posted.

                 

                Cheers,

                Jon

                • 5. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
                  muellerc

                  Hi Jonathan,

                   

                  Thank you for taking time to look for my problem. I installed the camel-jaxb osgi bundle with

                   

                  smx@root:features> install camel-jaxb

                   

                  I think the result is the same...

                  I modified my route with your hints to:

                   

                  package de.ps4b.rfid.file;

                   

                  import org.apache.camel.Exchange;

                  import org.apache.camel.Processor;

                  import org.apache.camel.builder.RouteBuilder;

                  import org.apache.camel.converter.jaxb.JaxbDataFormat;

                  import org.slf4j.Logger;

                  import org.slf4j.LoggerFactory;

                   

                  public class FileEventReader extends RouteBuilder {

                   

                       private static final Logger logger = LoggerFactory.getLogger(FileEventReader.class);

                        

                       private JaxbDataFormat jaxb = new JaxbDataFormat("de.ps4b.rfid.model.matrics");

                   

                       public void configure() throws Exception {

                            from("file:/Applications/apache-servicemix-4.1.0.0-fuse/incomingEvents/")

                                 .unmarshal(jaxb)

                                 .process(new Processor() {

                                      public void process(Exchange exchange) throws Exception {

                                           logger.info("the body class is: " + exchange.getIn().getBody().getClass());

                                      }

                                 })

                                 .marshal(jaxb)

                                 .to("file:/Applications/apache-servicemix-4.1.0.0-fuse/outgoingEvents/");

                       }

                  }

                   

                  And it work! Also the marshaling! I only see the warning:

                   

                  23:28:32,843 | WARN  | Component@2a4da2 | ResolverUtil                     | g.apache.camel.util.ResolverUtil  517 | Could not find class 'org/apache/servicemix/nmr/core/converter/StringSourceConverter.class' in any classloaders:

                  ...

                   

                  But why, the default JAXB type converter don't work like in a pure camel project (for marshaling and unmarshaling)? Maybe because the class org.apache.servicemix.nmr.core.converter.StringSourceConverter could not be found? Which osgi bundle or jar file normally should contain this class?

                   

                  Thank you a lot!

                   

                  Cheers,

                  Christian

                  • 6. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
                    njiang

                    Hi , 

                     

                    Even you deployed a pure camel route in ESB 4.1.0.0, camel-core will search the whole bundles for the component, langauge and type converter registering.

                     

                    I think the warning message may be caused by the bundle doesn't export the package of the converter.

                     

                    I will dig the code for it now.

                     

                    Willem

                    • 7. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
                      njiang

                      Hi,

                       

                      I just dig the lasted ServiceMix nmr code, the issue is fixed in it trunk code. You can find the JIRA[1] of it here.

                       

                      https://issues.apache.org/activemq/browse/SMX4NMR-135

                      • 8. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
                        muellerc

                        Hi Willem,

                         

                        thank you for your help!

                        Do you know, how I can test the fix with fuse esb 4.1.0.0? I ask, because fuse esb is delivered with Apache ServiceMix NMR Core (1.1.0.fuse). Can I replace this version with Apache ServiceMix NMR Core (1.1.0) from servicemix trunk?

                         

                        Cheers,

                        Christian

                        • 9. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
                          njiang

                          Replacing the jar is not enough, since the jars are OSGi bundle, you need also update the META-INF.

                          So I suggest you try the snapshot of fuse esb.

                           

                          http://repo.open.iona.com/maven2-snapshot/com/iona/fuse/fuse-esb/4.1.0-SNAPSHOT/

                          • 10. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
                            muellerc

                            Hi Willem,

                             

                            I downloaded the SNAPSHOT from 15.05.2009. I added the package 'org.apache.servicemix.nmr.core.converter' in my maven-bundle-plugin Import-Package declaration and modify my route builder to looks like my route builder in my pure camel project (which works like expected):

                             

                            from("file:/Applications/apache-servicemix-4.1.0.0-fuse-SNAPSHOT/incomingEvents/")

                               .convertBodyTo(Matrics.class)

                               .process(

                                  new Processor() {

                                     public void process(Exchange exchange) throws Exception {

                                        logger.info("the body class is " + exchange.getIn().getBody().getClass());

                                     }

                                  })

                               .to("file:/Applications/apache-servicemix-4.1.0.0-fuse-SNAPSHOT/outgoingEvents/");

                             

                            Now, the WARN log message is gone. But the message is not converted properly. I receive the following log message:

                             

                             

                            19:16:30,414 | WARN  | Component@856c07 | ConvertBodyProcessor             | l.processor.ConvertBodyProcessor   46 | Could not convert body of IN message: FileMessage: /Applications/apache-servicemix-4.1.0.0-fuse-SNAPSHOT/incomingEvents/sample_event.xml to type: de.ps4b.rfid.model.matrics.Matrics

                            19:16:30,416 | INFO  | Component@856c07 | FileEventReader                  | ps4b.rfid.file.FileEventReader$1   33 | the body class is class java.io.File

                             

                            Any idea?

                             

                            Cheers,

                            Christian

                            • 11. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
                              davsclaus

                              Hi

                               

                              Why are you not using the JAXB data format unmarshal anymore to convert from file -> your domain object?

                              • 12. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
                                njiang

                                Hi Christian

                                 

                                Did you install the  camel-jaxb feature from the fuse ESB ?

                                Camel supports the .convertBodyTo(Matrics.class) DSL, as the camel-jaxb provides a fallback Converter to do this work.

                                 

                                But I don't know if this feature is broken in OSGi plateform. I will try to write a test to verify it and will keep you posted.

                                 

                                BTW, can you try to run your route as a normal Camel application ? I think it should work.

                                 

                                Willem

                                • 13. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
                                  njiang

                                  Hi Christian,

                                   

                                  This is a camel bug, I just fill a JIRA[1] for tracing it.

                                   

                                  http://fusesource.com/issues/browse/MR-174

                                   

                                  Willem

                                  • 14. Re: How to use camel-jaxb in fuse esb (4.1.0.0)
                                    muellerc

                                    Hi Claus,

                                     

                                    I find the configuration with the default converter smarter, than the configuration with the jaxb type converter...

                                     

                                    This bug is not critical (for me), but I think camel should work the same way in servicemix/fuse like without servicemix/fuse...

                                     

                                    Cheers,

                                    Christian

                                    1 2 3 Previous Next