Monday, 10 February 2014

Command Line Application Start

Java has the 'main' method to start its apps and this is very easy to invoke.  However, there are times when optional arguments need to be passed into the app and for this the apache commons cli (Command Line Interface) is really useful.

Creating a Parser

Creating a parser is really simple and involves just one line

    CommandLineParser parser = new BasicParser();

Creating Options

The options for the command line are built using a builder pattern.  Here is an example

    OptionBuilder
        // the name of the argument
        .withArgName("timeout") 
        // this has two arguments -timeout <value>
        .hasArgs(2)
        // the separator '-' is used
        .withValueSeparator()
        // the description used for the help text
        .withDescription("Millisecond timeout for this test (default: 20000)")
        // create this option refered to as 'timeout'      
        .create("timeout")

This option is then added to the list of options

    final Options options = new Options();
    options.addOption(OptionBuilder.withArgName(.......));

which are added to the parser

    CommandLine line = parser.parse(options, args);

Getting the values

This CommandLine object can then be used to get the values that have been provided.

    final String timeoutStr = line.getOptionValue("timeout", "20000");

or query that an option has been provided,

    if (line.hasOption("timeout")) {
    
    }

Help Text
The descriptions created in the Options can be used to generate help text

    final HelpFormatter formatter = new HelpFormatter();
    formatter.printHelp("sample", options);

which is useful if a value fails validation or particular options are not provided.

Example

Here is a full example

import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

public class SampleMain
{


    /**
     * Main.
     * 
     * @param args The command line args
     */
    public static void main(final String[] args)
    {

        final CommandLineParser parser = new BasicParser();
        final Options options = new Options();
        options.addOption(OptionBuilder.withArgName("timeout").hasArgs(2).withValueSeparator()
                .withDescription("Millisecond timeout for this app (default: 20000)").create("timeout"));
        options.addOption(OptionBuilder.withArgName("filepath").hasArgs(2).withValueSeparator()
                .withDescription("Configuration file").create("filepath"));
        options.addOption(OptionBuilder.withArgName("logdirectory").hasArgs(2).withValueSeparator()
                .withDescription("log directory (default: ./logs)").create("logdirectory"));
        
        CommandLine line = parser.parse(options, args);
        
        // Get the timeout
        final String timeoutStr = line.getOptionValue("timeout", "20000");
        final long timeout = Long.valueOf(timeoutStr);

        // Log directory for the app
        final String logDirectory = line.getOptionValue("logdirectory", "./logs");
        
        if (line.hasOption("filepath"))
        {
            // Do something with this file
        }
        else
        {
            final HelpFormatter formatter = new HelpFormatter();
            formatter.printHelp("sample", options);
        }
    }
}

Use

This code would then be used,

    java -jar sample.jar -logdirectory ./mylog -timeout 5000 -filepath mydir/myfile

or to use the defaults

    java -jar sample.jar -filepath mydir/myfile


Monday, 20 January 2014

Dynamic Spring Message Driven Beans

Creating MDBs from spring is really easy particularly if all the information is known up front.  As usual it is just some configuration in the spring context and is shown here.

For dynamic beans things can still be put into the spring configuration but need the destination setting at runtime.  This can be done using some spring context as prototype beans so that a new instance of them is created each time and a small bit of wiring in the code.

Spring Context


<!-- MQ / JMS Connection factory -->
<bean id="jmsConnectionFactory" class="com.ibm.mq.jms.MQTopicConnectionFactory">
<property name="hostName" value="${jms.mq.ip}" />
<property name="port" value="${jms.mq.port}" />
<property name="queueManager" value="${jms.mq.queueManager}" />
<property name="transportType" value="1" />
</bean>


<!-- Spring Connection Factory -->
<bean id="springConnectionFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="jmsConnectionFactory" />
<property name="username" value="${jms.mq.username}" />
<property name="password" value="${jms.mq.password}" />
</bean>

<!-- This bean is a prototype bean which is loaded dynamically-->
<!-- it is loaded using a getBean("jmsDestination", requiredTopic") and as such the HOLDING_VALUE is -->
<!-- replaced with whatever is required by the class in question                                    -->
<bean id="jmsDestination" class="com.ibm.mq.jms.MQTopic" scope="prototype">
<constructor-arg value="HOLDING_VALUE" />
</bean>

<!-- Generic MDB Container -->
<bean id="springMdbContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer" scope="prototype">
<property name="connectionFactory" ref="springConnectionFactory" />
<!-- The destination is dynamically set in the factory method but a default is provided here-->
<property name="destination" ref="jmsDestination" />
<!-- The normal MessageListener which is put here is added dynamically in the factory -->
</bean>

Java

In the java code a new destination can be obtained using the bean above and the code,

    /**
     * Create a Destination object.
     *
     * @param topic The topic to construct the destination with
     * @return the Destination created.
     */
    public Destination createDestination(final String topic)
    {
        // Create the destination with the topic string.
        return (Destination) applicationContext.getBean("jmsDestination", topic);
    }

This creates a new Destination object based on the spring bean.  This allows the MQ provided to be changed in the spring configuration without having to change code.

To create a new MDB create a destination as above and then use the code,
   
    /**
     * Create a MDB wired by spring.
     *
     * @param destination The destination topic to listen to.
     * @param messageListener The message listener (MDB) to wire
     */
    private void wireMdb(final Destination destination, final MessageListener messageListener)
    {
        // Use spring to wire up the MDB with this destination and a ConnectionFactory 
        // which is already provided in the spring context. 
        // The MDB and Destination are set here and then the container is manually started.
        final DefaultMessageListenerContainer container = 
                (DefaultMessageListenerContainer) applicationContext.getBean("springMdbContainer");
        container.setDestination(destination);
        container.setMessageListener(messageListener);
        container.start();
    }

It is also possible to change the destination that a container is listening to once it has started.  Using the setDestination(...) method does this according to the spring documentation.


Tuesday, 19 November 2013

Java Keytool

I constantly forget how to use the keytool so here are some memory joggers!  The keytool app is part of the the standard Java distribution.

These will be added to over time.

List

List the contents of a jks file

    keytool -list -keystore <keystore.jks> -storepass <password>

Remote Keys

Print a certificate for a remote server


   keytool -printcert -rfc -sslserver my.company.com

Copy the output into a file .pem

Import Key

Import a key to a key store.  In this case it is imported into the java default Certificate Authority file (cacerts).  This will prompt for a password for the cacerts file which is 'changeit' by default.

    keytool -importcert -file ./certificate.pem -keystore $JRE_LIB/lib/security/cacerts

Thursday, 14 November 2013

Spring WS Interceptor

Using the spring interceptor methods a SOAP message can be manipulated by adding or removing elements.

Create an interceptor and add it to the spring config
   
    <bean id="myInterceptor" class="com.me.MyInterceptor">
    </bean>
    
    <sws:interceptors>
    <ref bean="myInterceptor" />
    </sws:interceptors>

The interceptor class implements the EndpointInterceptor

    public class MyInterceptor implements EndpointInterceptor

This interface defines four methods,

    // Used to read and / or manipulate the request coming in the endpoint
    boolean handleRequest(MessageContext paramMessageContext, Object paramObject)

    // Used to read and / or manipulate the response coming out of the endpoint
    boolean handleResponse(MessageContext paramMessageContext, Object paramObject)

    // Used to read and / or manipulate any faults that have occurred
    boolean handleFault(MessageContext paramMessageContext, Object paramObject)

    // Called after the interceptor has finished.
    void afterCompletion(MessageContext paramMessageContext, Object paramObject, Exception paramException)

Java Soap Objects

The default java soap objects are from the java.xml.soap package,

    SOAPBody
    SOAPHeader
    SOAPMessage

These objects use the standard org.w3c.dom objects to manipulate the contents.  These objects can be obtained using the following,

    SaajSoapMessage message = (SaajSoapMessage) messageContext.getRequest();
    SOAPMessage soapMessage = message.getSaajMessage();
    SOAPHeader soapHeader = soapMessage.getSOAPHeader();
    SOAPBody soapBody = soapMessage.getSOAPBody();

Spring Soap Objects

The spring objects are in the package org.springframework.ws.soap,

    SoapBody
    SoapHeader
    SoapEnvelope
    SoapElement

and have only a few methods.  The Body and Header can be used to get a standard javax.xml.transform.Source or Result object.  These objects can be obtained using,

    SaajSoapMessage message = (SaajSoapMessage) messageContext.getRequest();
    SoapBody soapHeader = message.getSoapHeader();
    SoapBody soapBody = message.getSoapBody();

Reading using the Java Objects

Reading using the java objects is pretty easy. Using the java SOAPBody a node list can be obtained,

    SOAPBody soapBody = soapMessage.getSOAPBody();
    NodeList soapBodyNodeList = soapBody.getChildNodes();
    String soapBodyStr = null;
    for (int i = 0; i < soapBodyNodeList.getLength(); i++)
    {
        String localName = soapBodyNodeList.item(i).getLocalName();
    }

or other standard dom manipulation eg getElementByTagName("myTag").

Reading using the Spring Objects

Using the Spring soap header or body can really simply be read using a Transformer,

    SoapBody springSoapBody = message.getSoapBody();
    TransformerFactory factory = TransformerFactory.newInstance();
    Transformer transformer = factory.newTransformer();
    StringWriter stringWriter = new StringWriter();
    transformer.transform(springSoapBody.getPayloadSource(), new StreamResult(stringWriter));

The contents can then be obtained from the stringWriter using the toString().  Alternatively a DOMResult can be used,

    DOMResult result = new DOMResult();
    transformer.transform(springSoapBody.getPayloadSource(), result);

Adding using the Spring Objects

Added an object in easy using the transformer defined above,

    SoapHeader soapHeader = message.getSoapHeader();
    StringSource stringSource = new StringSource("<xmlToAdd>Hello</xmlToAdd>");
    transformer.transform(stringSource , soapHeader.getResult());

The header will now include the xml.  At the point above the xml is just a string so could be generated using JAXB to create complicated additional nested xml tags if necessary.






Friday, 27 September 2013

JD Eclipse Decompile

JD Eclipse is a brilliant java decompile which very usefully provides line numbers in the decompiled class file.  Unfortunately it is no longer supported or in the Eclipse MarketPlace. To get it running on eclipse copy the two jars

jd.ide.eclipse.win32.x86_64_0.1.3.jar
jd.ide.eclipse_0.1.3.jar

into the eclipse/plugins directory and restart Eclipse.

Once eclipse has restarted go to,

    Window - Preferences - General - Editors - File Associations

Click on 'Class' and then 'Add'.  There is a new option now available called 'Class File Editor'.  Add this and make it the default.  Do the same to the 'Class without Source'.

Once completed the JD-Eclipse class viewer will be used to open class files.

I'd be interested to know if there is anything else around that decompiles like JD Eclipse?  The ByteCode Visualiser in the MarketPlace is good but I want the actual code not the byte code.



Update
After posting this I have found this site with instructions and updates.

http://jd.benow.ca/

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.