Tuesday, 30 July 2013

Soap UI

SoapUI is a brilliant tool for testing web services.  It can be downloaded from http://www.soapui.org/.

Property Transfers

SoapUI allows testing individual calls to a service but also allows multiple requests to be put together to form test cases.  For example, a test case creating and deleting would require the id generated by the first request to be passed to the delete request.  Soap UI's mechanism for doing this is with a Property Transfer.

    Right Click on the Test Steps -> Add Step -> Property Transfer

The transfer is done using XPath by default.  An example of a property transfer is below using the xml

CreateRequest
    <CreateRequest>
        <name>Andy</name>
        <data>123456</data>
    </CreateRequest>

CreateResponse
    <CreateResponse>
        <id>159</id>
        <name>Andy</name>
        <data>123456</data>
    </CreateResponse>

DeleteRequest
    <DeleteResponse>
        <id>159</id>
    </DeleteResponse>

Here the property transfer is between the CreateResponse and the DeleteRequest.  In SoapUI this will look like,

    Source: Create      Property: Response
    declare namespace myns='http://www.me.com/example';
    //myns:CreateResponse/id

    Target: Delete      Property: Request
    declare namespace myns='http://www.me.com/example';
    //myns:DeleteRequest/id

It is possible to include the whole <id>159</id> or to just transfer the value you can check the

    Transfer text content

Transfering a whole block of xml can be really powerful but the 'Transfer text content' does keep things simple and allows the transfer of the 'value' only.



Friday, 26 July 2013

SOAP WebService

SOAP is a common type of webservice.  Spring has a lot of support for creating SOAP webservices.  Below is an example configuration.

Maven Dependencies

There are a number of dependencies required for wiring up spring webservices.  The two spring ones here are obvious.  The org.apache.ws.xmlschema allows multiple schemas to be used and spring wraps some of the functionality of this dependency.  You may not need it as a compile dependency but certainly as a runtime.  The wsdl4j dependency allows a dynamic wsdl to be created.


        <dependency>
            <groupId>org.springframework.ws</groupId>
            <artifactId>spring-ws</artifactId>
            <version>${org.springframework.ws.version}</version>
            <scope>compile</scope>
            <classifier>all</classifier>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${org.springframework.version}</version>
            <scope>compile</scope>
        </dependency>
        
        <dependency>
            <groupId>org.apache.ws.xmlschema</groupId>
            <artifactId>xmlschema-core</artifactId>
            <version>2.0.1</version>
            <scope>runtime</scope>
        </dependency>
        
        <dependency>
            <groupId>wsdl4j</groupId>
            <artifactId>wsdl4j</artifactId>
            <version>1.6.3</version>
            <scope>compile</scope>
        </dependency>

server.xml Configuration

The server.xml configuration is very straightforward.  Firstly though a webservice in spring is usually wired with the org.springframework.ws.transport.http.MessageDispatcherServlet rather than the more common org.springframework.web.servlet.DispatcherServlet.  It means that the server.xml in WEB-INF is as follows,

    <display-name>My web service</display-name>

    <!-- This servlet is the actual web service -->
    <servlet>
<servlet-name>my-ws</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
    <param-name>transformWsdlLocations</param-name>
            <param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
<servlet-name>my-ws</servlet-name>
<url-pattern>/ws/*</url-pattern>
    </servlet-mapping>


The transformWsdlLocations parameter means that spring will automatically adjust the location of the service, published in the wsdl.

Spring xml configuration

The spring configuration has a number of options.

Standard Spring 
There are a few standard tags for spring ws.  These are below

    <context:component-scan base-package="com.me.web.ws" />
    
    <!-- Enable @Required -->
    <context:annotation-config />
    
    <!-- Enable @Endpoint, @PayloadRoot, etc -->
    <sws:annotation-driven />


Defining the Schemas
The schemas can be defined using a schema collection.  The advantages are that multiple schemas can be used and the spring bean that holds them all can be reused.  The schemaCollection is the reason for the apache pom entry above.  The schemas can be defined using,

    <bean id="schemas" class="org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection">
        <property name="xsds">
            <list>
                <value>classpath:/schema_1.xsd</value>
                <value>classpath:/schema_2.xsd</value>
            </list>
        </property>
        <property name="inline" value="true" />
    </bean>


Defining the WSDL
The WSDL can be defined automatically by spring from the schemas.  If you want to create a static wsdl yourself then spring has plenty of support for publishing this too.  However, in most cases it is easier this way,

    <bean id="webservice" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
        <property name="schemaCollection" ref="schemas"/>
        <property name="portTypeName" value="MyWsPortType"/>
        <property name="locationUri" value="/ws/mywebservice"/>
    </bean>

Here the location defines the link to the wsdl.  In this case it would be

  http://<server>:<port>/<context><locationUri><id>.wsdl

  http://<server>:<port>/<context>/ws/mywebservice/webservice.wsdl

Defining the wsdl this way also allows us to reuse the schemaCollection that was defined above.  There is an optional property for 'requestSuffix' and 'responseSuffix'.  These are the suffixes to define the entry points for the webservice.  By default they are 'Request' and 'Response'.  If you have not objects in your schema which end with 'Request' or 'Response' then there will be no obvious entry points for your webservice.

There is a shorthand way of defining the wsdl with springs sws tags. However, the schemaCollection cannot be used for this.

     <sws:dynamic-wsdl  id="possession" portTypeName="PossessionPortType" locationUri="/ws/possession">
         <sws:xsd location="classpath:/schema_1.xsd"/>
         <sws:xsd location="classpath:/schema_2.xsd"/>
     </sws:dynamic-wsdl>
    

Interceptors
An interceptor is something which happens before the request is passed to the webservice or after the webservice has finished with the request.  There are two particular interceptors which are really useful.  The logging interceptor will log all the requests which are made of the service.  The validating interceptor will validate that the request and response payloads are legitimate against the defined schemas.   

    <bean id="validatingInterceptor" class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
        <property name="xsdSchemaCollection" ref="schemas" />
        <property name="validateRequest" value="true"/>
        <property name="validateResponse" value="true"/>
    </bean>

    <!-- Logging interceptor -->
    <bean id="loggingInterceptor" class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor">
        <description>
            This interceptor logs the message payload.
        </description>
    </bean>

    <sws:interceptors>
        <ref bean="validatingInterceptor" />
        <ref bean="loggingInterceptor" />
    </sws:interceptors>

Endpoint

The Endpoint is the class which actually receives the request.  It should be annotated with @Endpoint.  The actual method which is called is defined using the @PayloadRoot annotation.  The localPart is the name of the xml root element in the request.  The namespace is defined in the schema for that element. Note that if a reference to the namespace is used like this then the namespace value isn't quoted!


    public static final String WEBSERVICE_NAMESPACE = "http://www.me.com/my/webservice";

    @PayloadRoot(localPart = "ReadRequest", namespace = WEBSERVICE_NAMESPACE)                 
    @ResponsePayload
    public ReadResponse getPossessions(@RequestPayload final ReadRequest readRequest, final SoapHeader header) 
    {  
        ...
    }

If you don't want to use the @PayloadRoot annotation then an xml configuration is available

    <bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
        <property name="mappings">
            <props>
                <prop key="{http://www.me.com/my/webservice}ReadRequest">readEndpoint</prop>
            </props>
        </property>
        <property name="interceptors">
            <bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor" />
        </property>
    </bean>

where 'readEndpoint' is a bean defined in the context.



Wednesday, 24 July 2013

JPA Entity Manager

Setting up an EntityManager for JPA can be done in a number of ways.  Below is a simple example to get something going.  It uses spring 3 and the packagesToScan option so that a persistence.xml file is not required.

persistence.xml

The persistence.xml file normally lives in the META-INF directory of src/main/java but if the packagesToScan option is going to be used in the EntityManagerFactory then this file should not be present at all.

DataSource

The DataSource defines the database that is used.  For simple development this can just be included as shown below however, two useful changes can be done.  Firstly, externalise the properties to a property file that can be changed without a recompile.  Secondly the datasource can be obtained by looking up a JNDI resource from the application server.

<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> 
<property name="url" value="jdbc:oracle:thin:@localhost:1521:XE" />
<property name="username" value="awhite" />
<property name="password" value="passw0rd" />
</bean>

Whichever driver is used needs to be on the classpath of the application.  In this case oracle.jdbc.driver.OracleDriver.

EntityManagerFactory

Creating an EntityManagerFactory is shown below.  The 'databasePlatform' will change depending on the database that is being connected to.  The 'hibernate.show_sql' and 'format_sql' are useful for debugging purposes but could be configured in a property file to allow them to be changed later.

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="packagesToScan" value="com.my.packages" />
        <property name="dataSource" ref="myDataSource" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
                <property name="generateDdl" value="false" />
            </bean>
        </property>
        <property name="jpaProperties">
            <props>
                <!-- General settings -->
                <prop key="hibernate.archive.autodetection">class, hbm</prop>
                <prop key="hibernate.current_session_context_class">jta</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
            </props>
        </property>
    </bean>
 

PersistenceAnnotationPostProcessor

The PersistenceAnnotationPostProcessor is included so that the EntityManager created by the JPA implementation (eg Hibernate) can still be wired into classes with spring even though it isn't spring that creates and manages that class.

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
 
This bean allows the @PersistenceContext annotation to be included in classes and the developer can assume that the EntityManager will be there at runtime. Here is an example of the annotation.

    /** JPA entity manager. */
    @PersistenceContext
    private EntityManager entityManager;