Monday 22 April 2013

Webservice with cxf using embedded Jetty

Jetty is a pure Java-based HTTP server and Java Servlet container. Jetty provides support for SPDY, Web Sockets, OSGi, JMX, JNDI, JASPI, AJP and many other integrations. More details about jetty please click following links.
This blog instruction will help us to create a sample webservice using cxf using embedded jetty (jetty://).

  • HTTP jaxws setup with CXF using embedded Jetty
    1. Create a dynamic web project.
    2. Create a folder wsdl under WEB-INF.
    3. Create a file Sample.wsdl under WEB-INF\wsdl.
    4. Add following wsdl snippet in WEB-INF\wsdl\Sample.wsdl and save the file.

    5. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
      <wsdl:definitions name="Sample" 
          xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
       xmlns:tns="http://poc.kaustuv.com/ws/service/greetings" 
       xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       targetNamespace="http://poc.kaustuv.com/ws/service/greetings">
       <!-- The WSDL types element is a container for XML Schema type definitions.
       The type definitions you place here are referenced from higher-level message 
       definitions in order to define the structural details of the message -->
       <wsdl:types>
        <xsd:schema targetNamespace="http://poc.kaustuv.com/ws/service/greetings">
         <xsd:element name="GreetingsRequest">
          <xsd:complexType>
           <xsd:sequence>
            <xsd:element name="name" type="xsd:string" />
           </xsd:sequence>
          </xsd:complexType>
         </xsd:element>
         <xsd:element name="GreetingsResponse">
          <xsd:complexType>
           <xsd:sequence>
            <xsd:element name="message" type="xsd:string" />
           </xsd:sequence>
          </xsd:complexType>
         </xsd:element>
        </xsd:schema>
       </wsdl:types>
       <!--The WSDL message element defines an abstract message that can 
       serve as the input or output of an operation. Messages consist of
       one or more part elements, where each part is associated with either
       an element (when using document style) or a type (when using RPC style) -->
       <wsdl:message name="GreetingsReq">
        <wsdl:part element="tns:GreetingsRequest" name="parameterIn" />
       </wsdl:message>
       <wsdl:message name="GreetingsRes">
        <wsdl:part element="tns:GreetingsResponse" name="parameterOut" />
       </wsdl:message>
       <!--The WSDL portType element defines a group of operations, also known as an interface in most environments .-->
       <wsdl:portType name="Greetings">
        <wsdl:operation name="Greetings">
         <wsdl:input message="tns:GreetingsReq" />
         <wsdl:output message="tns:GreetingsRes" />
        </wsdl:operation>
       </wsdl:portType>
       <!-- The WSDL binding element describes the concrete details 
       of using a particular portType with a given protocol. 
       The binding element contains several extensibility elements 
       as well as a WSDL operation element for each operation in 
       the portType it's describing . Here bnding is document literal -->
       <wsdl:binding name="GreetingsSOAPBinding" type="tns:Greetings">
        <!-- Style of binding canbe document or rpc -->
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="Greetings">
         <soap:operation soapAction="Greetings" />
         <wsdl:input>
          <soap:body use="literal" />
         </wsdl:input>
         <wsdl:output>
          <soap:body use="literal" />
         </wsdl:output>
        </wsdl:operation>
       </wsdl:binding>
       <!-- The WSDL service element defines a collection of ports, 
       or endpoints, that expose a particular binding -->
       <wsdl:service name="GreetingsService">
        <wsdl:port name="GreetingsPort" binding="tns:GreetingsSOAPBinding">
        <!-- address of service -->
         <soap:address location="http://www.kaustuv.com/ws/service/" />
        </wsdl:port>
       </wsdl:service>
      </wsdl:definitions>
      

    6. Generate java classes and service interfrace using eclipse wsdl2java.































    7. Modify GreetingsImpl.java add following code snippet.
    8. /**
      *
      * Copyright (c) Kaustuv Maji , 2013
      * Repos - https://github.com/kaustuvmaji
      * Blog -  http://kaustuvmaji.blogspot.in 
      *
      */
      package com.kaustuv.poc.ws.service.greetings;
      
      import java.util.logging.Logger;
      import javax.jws.WebMethod;
      import javax.jws.WebParam;
      import javax.jws.WebResult;
      import javax.jws.WebService;
      import javax.jws.soap.SOAPBinding;
      import javax.xml.bind.annotation.XmlSeeAlso;
      
      @javax.jws.WebService(
                            serviceName = "GreetingsService",
                            portName = "GreetingsPort",
                            targetNamespace = "http://poc.kaustuv.com/ws/service/greetings",
                            wsdlLocation = "WEB-INF/wsdl/Sample.wsdl",
                            endpointInterface = "com.kaustuv.poc.ws.service.greetings.Greetings")
                            
      public class GreetingsImpl implements Greetings {
      
          private static final Logger LOG = Logger.getLogger(GreetingsImpl.class.getName());
      
          /* (non-Javadoc)
           * @see com.kaustuv.poc.ws.service.greetings.Greetings#greetings(com.kaustuv.poc.ws.service.greetings.GreetingsRequest  parameterIn )*
           */
          public com.kaustuv.poc.ws.service.greetings.GreetingsResponse greetings(GreetingsRequest parameterIn) { 
              LOG.info("Executing operation greetings");
              System.out.println(parameterIn);
              try {
                  com.kaustuv.poc.ws.service.greetings.GreetingsResponse _return = new GreetingsResponse();
                  _return.setMessage(parameterIn.getName());
                  return _return;
              } catch (java.lang.Exception ex) {
                  ex.printStackTrace();
                  throw new RuntimeException(ex);
              }
          }
      }
      
    9. Modify generated web.xml WEB-INF/web.xml add following xml snippet.
    10. <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
        <display-name>SimpleJettyExample</display-name>
        <servlet>
          <description>Apache CXF Endpoint</description>
          <display-name>cxf</display-name>
          <servlet-name>cxf</servlet-name>
          <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
          <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
          <servlet-name>cxf</servlet-name>
          <url-pattern>/*</url-pattern>
        </servlet-mapping>
        <session-config>
          <session-timeout>60</session-timeout>
        </session-config>
        <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>WEB-INF/conf/*-beans.xml</param-value>
        </context-param>
        <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
      </web-app>
      
    11. Create a xml file name cxf-jetty-beans.xml under WEB-INF/conf
    12. <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
             xmlns:cxf="http://cxf.apache.org/core"
             xmlns:jaxws="http://cxf.apache.org/jaxws"
          xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration" 
          xsi:schemaLocation="
                              http://cxf.apache.org/core 
                              http://cxf.apache.org/schemas/core.xsd
                              http://www.springframework.org/schema/beans 
                              http://www.springframework.org/schema/beans/spring-beans.xsd
                              http://cxf.apache.org/transports/http-jetty/configuration 
                              http://cxf.apache.org/schemas/configuration/http-jetty.xsd
                              http://cxf.apache.org/jaxws 
                              http://cxf.apache.org/schemas/jaxws.xsd">
          <!-- import resource -->
          <import resource="classpath:META-INF/cxf/cxf*.xml" />
          <bean id="biosocket" class="org.eclipse.jetty.server.bio.SocketConnector">
              <property name="host" value="localhost" />
              <property name="port" value="9001" />
          </bean>
          <bean id="defaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler" />
          <!-- Cxf Bus implementation -->
          <cxf:bus>
              <!-- Cxf features implementation global -->
              <cxf:features>
                  <!-- cxf logging implementation -->
                  <cxf:logging />
              </cxf:features>
          </cxf:bus>
          <!-- Jetty server configuration and implementation -->
          <httpj:engine-factory bus="cxf">
              <!-- jetty server port we can add host too -->
              <httpj:engine host="localhost" port="9001">
                  <!-- jetty thread pooling -->
                  <httpj:threadingParameters minThreads="5" maxThreads="15" />
                  <httpj:connector>
                      <ref bean="biosocket" />
                  </httpj:connector>
                  <httpj:handlers>
                      <ref bean="defaultHandler" />
                  </httpj:handlers>
                  <httpj:sessionSupport>true</httpj:sessionSupport>
              </httpj:engine>
          </httpj:engine-factory>
      </beans>
      
    13. Modify generated cxf-beans.xml WEB-INF/conf/cxf-beans.xml add following xml snippet.
    14. <?xml version="1.0" encoding="UTF-8"?>
      <beans 
      xmlns="http://www.springframework.org/schema/beans" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:jaxws="http://cxf.apache.org/jaxws"
      xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
           http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
          <import resource="classpath:META-INF/cxf/cxf.xml" />
          <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
          <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
       
          <jaxws:endpoint 
              xmlns:tns="http://poc.kaustuv.com/ws/service/greetings" 
              id="greetings"
              implementor="com.kaustuv.poc.ws.service.greetings.GreetingsImpl"
              wsdlLocation="WEB-INF/wsdl/Sample.wsdl" 
              endpointName="tns:GreetingsPort"
              serviceName="tns:GreetingsService" 
              address="http://localhost:9001/Greetings">
        <!-- xml:tns , enpointname ans servicename will be same as in wsdl -->
        <!-- /Greetings means our webservice url will be 
        http://<host>:<port>/<webapplicationname>/Greeting?wsdl 
        -->
              <jaxws:features>
        <!-- Used for cxf log to see soap packet structure -->
                  <bean class="org.apache.cxf.feature.LoggingFeature" />
              </jaxws:features>
          </jaxws:endpoint>
      </beans>
      
    15. Export and package this as war.Destination path %JBOSS_HOME%\server\default
    16. Open command prompt and go to directory %JBOSS_HOME\bin
    17. Execute run.bat -c default -b 0.0.0.0
    18. Deployement will be sucessfull according to above instructions. following log message will apear in jboss console log.
      INFO: Creating Service {http://poc.kaustuv.com/ws/service/greetings}GreetingsService from WSDL: WEB-INF/wsdl/Sample.wsdl
      INFO: Setting the server's publish address to be http://localhost:9001/Greetings
      INFO: jetty-7.5.4.v20111024
      INFO: Started SelectChannelConnector@localhost:9003 STARTING
      INFO: started o.e.j.s.h.ContextHandler{,null}
      13:22:16,863 INFO  [ContextLoader] Root WebApplicationContext: initialization completed in 9333 ms
      13:22:16,965 INFO  [Http11Protocol] Starting Coyote HTTP/1.1 on http-0.0.0.0-8080
      13:22:16,990 INFO  [AjpProtocol] Starting Coyote AJP/1.3 on ajp-0.0.0.0-8009
      13:22:17,032 INFO  [Server] JBoss (MX MicroKernel) [4.2.3.GA (build: SVNTag=JBoss_4_2_3_GA date=200807181417)] Started in 33s:865ms
      
      WSDL url : http://localhost:9003/Greetings?wsdl

      Please check the above snapshot wsdl tab. Icon (j:) it means that 9003 is cxf embeded jetty web server port. 9003 jetty port configuration is done in cxf-jetty-beans.xml .

  • HTTP jaxrs setup with CXF using embedded Jetty

  • Developing sample restful webservice please go through following link. The link will help you to create sample restful webservice in details. In this section we will only configure jaxrs server to use cxf embabed jetty.
    1. Create a xml file name cxf-jetty-beans.xml under WEB-INF/conf
    2. <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
             xmlns:cxf="http://cxf.apache.org/core"
             xmlns:jaxws="http://cxf.apache.org/jaxws"
          xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration" 
          xsi:schemaLocation="
                              http://cxf.apache.org/core 
                              http://cxf.apache.org/schemas/core.xsd
                              http://www.springframework.org/schema/beans 
                              http://www.springframework.org/schema/beans/spring-beans.xsd
                              http://cxf.apache.org/transports/http-jetty/configuration 
                              http://cxf.apache.org/schemas/configuration/http-jetty.xsd
                              http://cxf.apache.org/jaxws 
                              http://cxf.apache.org/schemas/jaxws.xsd">
          <!-- import resource -->
          <import resource="classpath:META-INF/cxf/cxf*.xml" />
          <bean id="biosocket" class="org.eclipse.jetty.server.bio.SocketConnector">
              <property name="host" value="localhost" />
              <property name="port" value="9001" />
          </bean>
          <bean id="defaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler" />
          <!-- Cxf Bus implementation -->
          <cxf:bus>
              <!-- Cxf features implementation global -->
              <cxf:features>
                  <!-- cxf logging implementation -->
                  <cxf:logging />
              </cxf:features>
          </cxf:bus>
          <!-- Jetty server configuration and implementation -->
          <httpj:engine-factory bus="cxf">
              <!-- jetty server port we can add host too -->
              <httpj:engine host="localhost" port="9001">
                  <!-- jetty thread pooling -->
                  <httpj:threadingParameters minThreads="5" maxThreads="15" />
                  <httpj:connector>
                      <ref bean="biosocket" />
                  </httpj:connector>
                  <httpj:handlers>
                      <ref bean="defaultHandler" />
                  </httpj:handlers>
                  <httpj:sessionSupport>true</httpj:sessionSupport>
              </httpj:engine>
          </httpj:engine-factory>
      </beans>
      

    3. Modify jaxrs-beans.xml under WEB-INF/conf and mention the jetty host port in jaxrs server section

    4. <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:jaxrs="http://cxf.apache.org/jaxrs"
      xmlns:cxf="http://cxf.apache.org/core" 
          xsi:schemaLocation="
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://cxf.apache.org/core 
      http://cxf.apache.org/schemas/core.xsd
      http://cxf.apache.org/jaxrs
      http://cxf.apache.org/schemas/jaxrs.xsd"
          default-lazy-init="false">
          <!-- Service -->
          <bean id="customerService" class="com.kaustuv.jaxrs.example.service.DemoCustomerServiceImpl" 
          init-method="init" 
          destroy-method="destroy" />
          <!-- Jaxrs Server -->
          <jaxrs:server id="restserver" address="http://localhost:9001/customerService">
              <!-- adding service bean -->
              <jaxrs:serviceBeans>
                  <ref bean="customerService" />
              </jaxrs:serviceBeans>
              <!-- adding media type provider -->
              <jaxrs:providers>
                  <ref bean="jsonProvider" />
                  <ref bean="jaxbXmlProvider" />
                  <ref bean="cors-filter" />
              </jaxrs:providers>
              <jaxrs:features>
                  <cxf:logging/>
              </jaxrs:features>
              <!-- Keeping extention type -->
              <jaxrs:extensionMappings>
                  <entry key="json" value="application/json" />
                  <entry key="xml" value="application/xml" />
              </jaxrs:extensionMappings>
          </jaxrs:server>
      </beans>
      
      Above instructions will be enable our jaxrs project to use cxf embedded jetty.

  • Testing
  • Post production testing procedure will be as same as discussed is previous blog. Please click on jaxws or jaxrs browse testing section for more details procedures.
    • References:
    Jetty wiki
    Embedded Jetty
    CXF documents

    European Union laws require you to give European Union visitors information about cookies used on your blog. In many cases, these laws also require you to obtain consent.

    As a courtesy, we have added a notice on your blog to explain Google's use of certain Blogger and Google cookies, including use of Google Analytics and AdSense cookies.

    You are responsible for confirming that this notice actually works for your blog and that it is displayed. If you employ other cookies, for example by adding third-party features, this notice may not work for you. Learn more about this notice and your responsibilities.

    European Union laws require you to give European Union visitors information about cookies used on your blog. In many cases, these laws also require you to obtain consent.

    As a courtesy, we have added a notice on your blog to explain Google's use of certain Blogger and Google cookies, including use of Google Analytics and AdSense cookies.

    No comments:

    Post a Comment