Wednesday, 30 April 2014

Spring Context Unit Testing

It is always a good idea to unit test the spring contexts that define an application.  This can be as simple as a unit test

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "classpath:com/me/my_context.xml" })
    public class SpringContextTest implements ApplicationContextAware
    {
        /**
         * The spring context.
         */
        private ApplicationContext applicationContext;

        /**
         * Test the spring wiring.
         */
        @Test
        public void testSpringWiring()
        {
            final Object obj = applicationContext.getBean("myBean");
            assertTrue(obj instanceof MyBean);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void setApplicationContext(final ApplicationContext applicationContext)
        {
            this.applicationContext = applicationContext;
        }
    }


However, where there is interaction with a JNDI resource as part of the spring start up this needs to be modified to make the JNDI resource available.  Adding this @Before method will set up a JNDI resource for a MySql database.

    /**
     * Set up the jndi data source so that the wiring tests still work.
     */
    @BeforeClass
    public static void setUpClass()
    {
        // Setup the jndi context and the datasource
        try
        {
            // Create a database connection to satisfy the data loading requirements.
            final DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql://server:port");
            dataSource.setUsername("username");
            dataSource.setPassword("password");

            final SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
            builder.bind("jdbc/MY_JNDI_NAME", dataSource);
            builder.activate();
        }
        catch (final NamingException ex)
        {
            LOG.error("Error creating JNDI resource", ex);
        }
    }



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.