Apache Camel and web services

前端 未结 2 1987
一向
一向 2021-01-19 18:22

I am trying to understand how to integrate Apache Camel with any web service that provides a WSDL to generate its classes to afterward call his methods to return some reques

相关标签:
2条回答
  • 2021-01-19 18:30

    You are referring to contract first or top-down development of Web-services. In this approach you generate stub code from the WSDL definitions and use these classes etc in your development. I have done this a lot and I have used WSDL's from service created in .Net, Java, PHP and even Delphi(though Delphi breaks WSI compliance don't even go there).

    CXF will generate classes from just about any WSDL you can point the library at. First thing is that you need to add an entry to your Maven POM file which tell Maven to generate classes from the WSDL for you.

    Add the following to your POM file:

    <plugin>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-codegen-plugin</artifactId>
        <version>get the latest version or the version you want</version>
        <executions>
            <execution>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
            <configuration>
    
                <sourceRoot>
                ${basedir}/target/generated/src/main/java
                </sourceRoot>
                <wsdlOptions>
                    <wsdlOption>
                    <wsdl>
                    URI/FILE PATH OF WSDL HERE
                    </wsdl>
                    <extraargs>
                    <extraarg>-impl</extraarg> <-- use this if you want to implement the service i.e. create it
                    <extraarg>-client</extraarg> <-- us this if you want to generate a client for the service.
                    </extraargs>
                    </wsdlOption>
                </wsdlOptions>
            </configuration>
            <goals>
            <goal>wsdl2java</goal>
            </goals>
            </execution>
        </executions>
    </plugin>
    

    You can now runt he maven goal mvn generate-source to generate the needed stub classes to use this file.

    I normally drop into a processor/bean to do the actual implementation as most of the web-services I produce and or consume have rather complex data structures. However this really depends on the service.

    So in short you can use CXF to generate the stub classes for almost(Delphi guys are you listening?) web-service then use these generated classes in a processor to implement the client and or server.

    UPDATE:

    Based on your example above you are on the right track. First I want to just discuss something about CXF in camel which is an important concept. The CXF beans are a little different than the other beans for example when you see the following code:

    <from uri="file://....."/>
    <to uri="mock"/>
    

    The file component is a producer it produces files after all and the mock component is a consumer as it takes data produced by the file component and consumes it to do its task.

    Web-services twists this concept slightly. When you have a route such as:

    The cxf bean is called a producer as it calls a web service. It gets interesting when you use a cxf bean as a consumer or in the <from> part of your route.

    Here is an example of a web-service consumer:

    <from uri="cxf:bean:someService" />
    

    The CXF bean is consuming the web-service call and then sending the message on to various other parts. This allows you to expose something very complex such as downloading a file from an FTP server, enriching the contents to with a JDBC call and then processing the enriched data against a SAP system as web-service. Your route exposes the cxf bean in the <from> as the service the rest of the route can do all the integration but it is exposed as a web-service. VERY powerful concept.

    In your case your web-service bean is a producer or a client. I typically don't use cxf beans for clients as te services I consume can be rather complex and i need the full power of Java to handle these cases. So I will show you how to do it this way.

    So in my world I would do the following camel route:

    <routeContext id="osvWebServiceInvoke" xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="quartz2://test?cron=0/10+*+*+*+*+?"/>
            <process ref="osvWebServiceProcessor" />
            <to uri="log:live?level=INFO" />
        </route>
    </routeContext>
    

    And my processor bean will change to this:

    public class OsvWebServiceProcessor implements Processor
    {
        @Override
        public void process(Exchange exchange) throws Exception
        {
            Message inMessage = exchange.getIn();
    
    
    
           /*
                  SInce i dont have access to the WSDL and XSD I cant say how the following code will look but essentially you would need to call the web-service here in Java code and get the result back.
    
           */
          outSOAPMsg=  siemens_hiq8000.SiemensHiq8000PortType.OperationName(inSOAPMsg)
          //set the reply into the inbody and send onto other components for processing.
          inMessage.setBody(outSOAPMsg);
    
      }
    }
    

    Looking at your code I realised that it appears that your stub classes are not generated correctly. I strongly urge you to add the items described in my post to your POM file. If you could post some of the WSDL and XSD files I could give you more descriptive answer.

    0 讨论(0)
  • 2021-01-19 18:43

    One of my main responsibilities is to consume different web services using camel as a client. This is the approach I generally use, never ran into any problems it works like a charm everytime.

    1) Define the endpoint in your camel-config.xml file:

    < bean id="service_name_CXFEndpoint" class="org.apache.camel.component.cxf.CxfEndpoint" />

    2) Use the Endpoint Defined in the config file in the route for web service consumption:

    private String CXF_SERVICE_ENDPOINT = "cxf:bean:service_name_CXFEndpoint?address=wsdl_uri_location&serviceClass=service_name_from_the_stubs&loggingFeatureEnabled=true";

    For the service name, you need to copy the contents of the wsdl, paste it in a .wsdl file and generate webservice client. To do this, you need to right click on the wsdl file>webservices>Generate Client. Then you need to select JbossWS for the runtime( You have to set it up first in the preferences). Once the stubs, have been generated, look for the main service class. Then copy its entire location.(for example, for a class called WebServiceClass located in com.test would be serviceClass=com.test.WebService.class)

    3) Define the routing for consumption:

    from("direct:web_service")
    .routeId("service_name")
    .bean(ServiceWSProcessor,"processRequest")
    .to(CXF_SERVICE_ENDPOINT)
    .bean(ServiceWSProcessor,"processResponse")
    .end();
    

    Now, you send a request to this processor, which will go to the web service endpoint and give you a response.

    4) Write a processor for the request response(in this case serviceWS processor).

    @Component(value="serviceWSProcessor")
    public class ServiceWSProcessor {
    
      private static final Logger LOGGER = LoggerFactory.getLogger(ServiceWSProcessor.class);
    
      public void processRequest(Exchange exchange) throws Exception {
    
        Message in = exchange.getIn();
        Message out = exchange.getOut();
    
        try {
    
          LOGGER.info("Service - START");
    
          Request Request = in.getBody(Request.class);
    
          //This depends on your WSDL File. Test the process in SOAP UI and see how the request looks like and code
          //accordingly.
    
          List<Object> list = new ArrayList<Object>();
          list.add(header);
          list.add(body);
          //for this, you need to check the service for what are the parameters for that method and what response its expecting.
    
          out.setHeader(CxfConstants.OPERATION_NAME, "method_name");
          out.setBody(list);
    
        } 
        catch (Exception e) {
          e.printStackTrace();
        }
    
      }
    
      public void processResponse(Exchange exchange) throws Exception {
    
        Message in = exchange.getIn();
        Message out = exchange.getOut();
    
        try {
          Response response = null; //Code this based on what response you should set to the final body. check the message
          //contents list in debug mode to see what response you are getting.
    
          try {
            MessageContentsList result = (MessageContentsList) in.getBody();
            if (result != null) {
              response = (Response)result.get(0);
    
              out.setHeader(Constants.HEADER_SERVICE_RESPONSE_SUCCESS, Constants.SERVICE_RESPONSE_SUCCESS_Y);
            } else {
              out.setHeader(Constants.HEADER_SERVICE_RESPONSE_SUCCESS, Constants.SERVICE_RESPONSE_SUCCESS_N);
            }
    
          } catch (Exception e) {
            e.printStackTrace();
            out.setHeader(Constants.HEADER_SERVICE_RESPONSE_SUCCESS, Constants.SERVICE_RESPONSE_SUCCESS_N);
          }
          LOGGER.info("Service - END");
          out.setBody(response));
        } 
        catch (Exception e) {
          LOGGER.error("Service - ERROR");
          out.setBody(e.getMessage());
        } 
    
      }
    
    }
    

    For the list of dependencies required for camel and spring-ws, check out this page.

    https://github.com/gauthamhs/Java/blob/master/JavaEE/Dependencies-Important-Camel-Spring.xml

    Let me know if you need additional help or if you have any concerns.

    Regards, Gautham

    0 讨论(0)
提交回复
热议问题