Project Lombock Awesomeness

I could try to put together my own unique thoughts on project Lombock, but instead its awesomeness can easily be found at this guy’s article.

I agree with Bozho’s hesitation to use Lombock because of its “black magic”, and the implications of using something that generates so much code behind the scenes. However, for basic implementations of equals(), hashcode(), and toString() Lombock is a great starting point.

My new favorite test tool: Unitils

I was working on some RESTful integration tests, and kept being annoyed at the repetetive nature in which I was verifying my user object. I knew I could override the equals() and hash() methods and simply call user.equal(newUser) to confirm whether users were equal, but I wanted a more universal solution that would not be limited to just my User objects. I knew someone had to have fixed this problem using reflection.

A few google searches later revealed the incredibly useful and powerful Unitils.org.

Old, ugly, repetitive assertions

...
import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;
import org.junit.Test;
import org.unitils.reflectionassert.ReflectionAssert;
import org.unitils.reflectionassert.ReflectionComparatorMode;
...

public class TestUserRestService {
...
    @Test
    public void test_createUser() throws Exception {
        String xml = this.getResponseAsString(response.getEntityInputStream());

        User uFromXml = (User) WSUtils.getObjectFromXml(xml); 

        Assert.assertNotNull(uFromXml); 
        Assert.assertEquals(u.getUserId(), uFromXml.getUserId()); 
        Assert.assertEquals(u.getPassword(), uFromXml.getPassword()); 
        Assert.assertEquals(u.getFirstName(), uFromXml.getFirstName()); 
        Assert.assertEquals(u.getLastName(), uFromXml.getLastName()); 
        Assert.assertEquals(u.getPhone(), uFromXml.getPhone()); 
        Assert.assertEquals(u.getZip(), uFromXml.getZip()); 
        Assert.assertEquals(u.getEmail(), uFromXml.getEmail()); 
        Assert.assertEquals(u.getAddress(), uFromXml.getAddress()); 
        Assert.assertEquals(u.getCity(), uFromXml.getCity()); 
        Assert.assertEquals(u.getState(), uFromXml.getState()); 
        Assert.assertEquals(u.getZip(), uFromXml.getZip()); 
    }
...
}

Simple, elegant one-line to verify code

        String xml = this.getResponseAsString(response.getEntityInputStream());

        User uFromXml = (User) WSUtils.getObjectFromXml(xml); 

        ReflectionAssert.assertReflectionEquals(u, uFromXml); 

That one line of code just replaced 12, and those 12 were not all attributes on the class, so that one line is much more useful than just replacing the initial 12 assertions mentioned above.

There were some issues with default values, but they have already thought of that and provide a parameter to ignore defaults.

        ReflectionAssert.assertReflectionEquals(u, uFromXml, ReflectionComparatorMode.IGNORE_DEFAULTS); 

I was kind of curious how it would handle certain Collection classes, and so far, for my simple Lists it appears to work as advertised.

    public static void main(String[] args) {
        List<String> g1 = new ArrayList<String>(); 
        g1.add("red"); 
        g1.add("blue"); 
        g1.add("yellow"); 

        List<String> g2 = new ArrayList<String>(); 
        g2.add("red"); 
        g2.add("blue"); 
        g2.add("green"); 

        User u1 = TestData.getTestUser_1("bob"); 
        u1.setUserGroups(g1);

        User u2 = TestData.getTestUser_1("bob");
        u2.setUserGroups(g2);

        ReflectionAssert.assertReflectionEquals(u1, u2); 
    }

This utility has significantly improved my test classes by making them much more thorough, and concise. I may even look to enhance (I want to pass a list of attributes to ignore). I just wish it was on GitHub instead of Sourceforge.

Jersey RESTful Framework with Forms

I needed a RESTful service from which a variety of disparate apps and systems can submit to in order to create a new user. The basic flow will be for a user to fill out an HTML Form, and have the data sent to my service.

I have used the Jersey RESTful Framework for quite some time now, I and like its simple, intuitive API. I had not used Jersey as an endpoint for Form submissions, but I know other frameworks have this features, and some simple searching showed that Jersey supports Forms as well.

@Path("/user")
public class UserRestService extends AbstractSpringRestAware {

    UserService userService;

    public UserRestService(){
        userService = (UserService) context.getBean("userService");
    }

    @POST
    @Path("create")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response createUser(@FormParam("userId") String userId,
            @FormParam("password") String password, @FormParam("firstName") String firstName,
            @FormParam("lastName") String lastName, @FormParam("email") String email, 
            @FormParam("phone") String phone, @FormParam("fax") String fax,
            @FormParam("address") String address, @FormParam("city") String city, 
            @FormParam("state") String state, @FormParam("zip") String zip){ 

        if(StringUtils.isBlank(userId) || StringUtils.isBlank(password) 
                || StringUtils.isBlank(password) || StringUtils.isBlank(firstName)
                || StringUtils.isBlank(lastName) || StringUtils.isBlank(phone)
                || StringUtils.isBlank(address) || StringUtils.isBlank(city)
                || StringUtils.isBlank(state) || StringUtils.isBlank(zip)
                || StringUtils.isBlank(email)){

            if(logger.isDebugEnabled()){
                logger.debug("One of the required params was not provided.  userId=" + userId); 
            }

            // 412 - The server does not meet one of the preconditions that the requester put on the request.[2]
            return Response.status(412).entity("One of the required params was not provided.  userId=" + userId).build();
        }

        User existingUser = userService.getUser(userId); 

        if(existingUser != null){

            // 412 - The server does not meet one of the preconditions that the requester put on the request.[2]
            return Response.status(412).entity("userId already exists: " + userId).build();

        } else {

            User u = new User(); 
            u.setUserId(userId);
            u.setPassword(password);

            //set all User attributes

            User u2 = userService.createUser(u);

            if(u2 == null){
                return Response.status(412).entity("User was not created due to unforeseen issues. userId=" + userId).build();
            }

            String userXml = WSUtils.getXmlForObject(u2);

            return Response.status(200).entity(userXml).build();
        }
    }

}

My custom AbstractSpringRestAware class loads my ApplicationContext.xml to inject my services. I need to update this codebase to let Jersey know about spring in the web.xml (com.sun.jersey.spi.spring.container.servlet.SpringServlet) , but I have not completed that task just yet.

public abstract class AbstractSpringRestAware {
    ApplicationContext context = null; 

    public AbstractSpringRestAware(){
        String env = System.getProperty(StaticVars.ENV_VAR); 

        if(env != null && env.equals(StaticVars.TRUE)){
            context = new FileSystemXmlApplicationContext("applicationContext.xml");
        } else {

            //Try-Catch is needed b/c in UAT, the appContext.xml is used, but when testing locally, we want the test-appContext.xml
            try{
                context = new FileSystemXmlApplicationContext("classpath:test-applicationContext.xml");
            } catch(Exception e){
                context = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");
            }
        }
    }
}

My hope was to use Grizzly integrated with Maven to test this feature locally, but I ran into SSL issues on my local machine when trying to save the user, which I have not yet fixed. (Post on local SSL config coming soon, hopefully) That left me with having to deploy the WAR out to our WebSphere environment, and testing the form submission manually. Not a good long-term solution, but it was able to get the other developers something to test against in a timely fashion while I figure out the SSL issues.

I used a few different client frameworks to try and mock the form submission (mainly straight-up URLConnection and Apache HTTPClient), but ran into a multiple issues, and once they were working, it was somewhat messy. My guess is I was doing something wrong with those frameworks, but once I found the JerseyClient API, it was a much easier and cleaner solution in my opinion.

public class TestUserRestService {
    private static final String userCreateUrl = "http://dev.corporation.com/app/rest/user/create"; 
    private static String userId = "testUser_";

    @BeforeTest
    public static void beforeTests(){
            userId = userId + WSUtils.getCurrentDateAndTimeAsString();
    }

    @Test
    public void test_createUser() throws Exception {

        User u = TestData.getTestUser_1(userId); 

        ClientConfig config = new DefaultClientConfig();
        Client client = Client.create(config);
        WebResource webResource = client.resource(userCreateUrl);

        MultivaluedMap<String, String> formData = new MultivaluedMapImpl();
        formData.add("userId", u.getUserId());
        formData.add("password", u.getPassword());

        //set all User data

        ClientResponse response = webResource.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, formData);

        String xml = this.getResponseAsString(response.getEntityInputStream());

        User uFromXml = (User) WSUtils.getObjectFromXml(xml); 

        Assert.assertNotNull(uFromXml); 
        Assert.assertEquals(u.getUserId(), uFromXml.getUserId()); 

        //assert all User values were saved

    }
}

Cloned Cluster on WebSphere does not start

We had a need to create a new cluster of WebSphere 7 JVMs (Cluster_B) that are identical to an existing cluster (Cluster_A).  No problem, an easy task that I’ve done many times before. I proceeded to venture through the WAS console to create a new cluster using the existing Cluster_A_was01 member as a template. The new config was told to create new ports, I clicked through the save buttons, and gave the cluster members a few minutes to ensure they were synced up properly with the new configuration.

Everything worked as expected right up to the point that the server did not start after issuing the start command from the CLI (Command Line Interface).

websphere_01:~> /was/AppServer/profiles/AppServer/bin/startServer.sh Cluster_B
ADMU0116I: Tool information is being logged in file
/was/AppServer/profiles/AppServer/logs/Cluster_B/startServer.log
ADMU0128I: Starting tool with the AppServer profile
ADMU3100I: Reading configuration for server: Cluster_B
ADMU3200I: Server launched. Waiting for initialization status.
ADMU3011E: Server launched but failed initialization. startServer.log,
SystemOut.log(or job log in zOS) and other log files under
/was/AppServer/profiles/AppServer/logs/Cluster_B
should contain failure information.
websphere_01:~>

This is a new server, that was cloned from an existing one, so there could be a conflict of a param that I missed (ports, cookie names, etc.).  I look inside the Cluster_B log directory, and there is no SystemOut.log to be found.

websphere_01:~> cd /was/AppServer/profiles/AppServer/logs/Cluster_B
websphere_01:/was/AppServer/profiles/AppServer/logs/Cluster_B> ls -latr
total 16
-rw-r–r–  1 websphereUser websphereGroup    0 2014-02-26 15:19 native_stdout.log
-rw-r–r–  1 websphereUser websphereGroup    5 2014-02-26 15:35 Cluster_B.pid
-rw-r–r–  1 websphereUser websphereGroup 1935 2014-02-28 13:26 startServer.log
-rw-r–r–  1 websphereUser websphereGroup 2259 2014-02-28 13:26 native_stderr.log

Note that I tried to start the server, it failed, and told me to look in the SystemOut.log.  There is no SystemOut.log listed.  I’m now in uncharted waters.  I’ve never seen an instance of starting up a new JVM where no SystemOut.log or SystemErr.log is created.  Thanks for mutton WebSphere.

After verifying the ports are different from the cloned JVM from Cluster_A, kicking kittens, and other config comparisons, I thought to look at the JVM args, which would be identical to Cluster_A, since it is a clone.  I see that AppDynamics is there, and right next them are the bane of the past couple of hours: a check mark next to Debug with the port set to 7777, just like Cluster_A’s debug configuration.

To be sure that the identical debug ports are the issue (and not AppD), I first remove the AppDynamics JVM params and try again.  Failure.  Next the debug config is removed altogether, and the server boots right up.  I changed the debug port on Cluster_B to 7778, reboot, and it again starts right up.

It would have been nice for the WAS server to let me know that there was a debug port conflict, instead of me fumbling around in the dark with no idea of where to start.  It would have saved me a couple of hours, and several kicks to kittens.

 

JDK not found on Linux Path

I’m researching Atlassian’s Stash to help us manage our Git repository, and in the process, I started with a completely new Suse Linux machine. I exploded the JDK, and added it to the path:


export PATH=$PATH:/jdk/jdk1.7.0_25/bin

However, this gave the dreaded “command not found”. I also tried to use “which java” command, but as expected, that revealed “command not found” as well. After verifying that the path did indeed exist (../bin/java -version), I knew that it had to be something higher in the Path that was being hit before my JDK was reached.

Digging a little higher into the path, I found a /usr/lib/java that existed, but it was corrupt. Since I do not own this machine, I simply put my JDK first in the path to fix the issue.


export JAVA_HOME=/jdk/java/jdk1.7.0_25
export PATH=$JAVA_HOME/bin:$PATH

Bad idea: Mixing JUnit Annotations and extends TestCase

I Wasted a good deal of time trying to find out why my simple JUnit tests were not working properly. It boiled down to my stupidity in mixing “public class TestSomeService extends TestCase” and trying to use “@BeforeClass” to initialize some test data.

When combining the JUnit annotations with “extends TestCase”, the annotations are rendered useless. There are no errors of any kind at the console, which makes the problem tough to nail down.

Do not do…

public class TestSomeService extends TestCase {
    @BeforeClass
    public static void beforeAllTestsConfig() throws Exception {
        //config before All tests are run
    }

<pre><code>@AfterClass
public static void afterAllTestsConfig() throws Exception {
    //config after all tests are run
}
</code></pre>

}

Instead…

public class TestSomeService {

<pre><code>@BeforeClass
public static void beforeAllTestsConfig() throws Exception {
    //config before All tests are run
}

@AfterClass
public static void afterAllTestsConfig() throws Exception {
    //config after all tests are run
}

@Before
public void beforeEachTest(){
    //config before each test is run
}

@After
public void afterEachTest() throws IOException{
    //config after each @Test is run
}

@Test
public void test_SimpleEmail() throws Exception {
    assertEquals(x, y);  //static import            
    Assert.assertTrue(true);
}
</code></pre>

}

how to copy jaxb.index properly without ignoring other config files in maven

I was utilizing some simple JAXB for a project that has a jaxb.index full of the java objects that are utilizing the JAXB annotations. I first tried the code below within my pom.xml:

&lt;build&gt;
              &lt;resources&gt; &lt;!-- include jaxb index files --&gt;
                     &lt;resource&gt;
                           &lt;directory&gt;src/main/java&lt;/directory&gt;
                           &lt;includes&gt;
                                  &lt;include&gt;**/*.index&lt;/include&gt;
                           &lt;/includes&gt;
                     &lt;/resource&gt;
              &lt;/resources&gt;
&lt;/build&gt;

However, this appears to override the data within the /src/main/resources/ directory (appConfig.xml, *.properties, etc.). This is what caused the .

I was able to find a maven plugin vi that helped to fix the issue.

&lt;plugin&gt;
    &lt;artifactId&gt;maven-resources-plugin&lt;/artifactId&gt;
    &lt;version&gt;2.5&lt;/version&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;id&gt;copy-resources&lt;/id&gt;
            &lt;phase&gt;validate&lt;/phase&gt;
            &lt;goals&gt;
                &lt;goal&gt;copy-resources&lt;/goal&gt;
            &lt;/goals&gt;
            &lt;configuration&gt;
                &lt;outputDirectory&gt;${basedir}/target/classes/path/to/model/&lt;/outputDirectory&gt;
                &lt;resources&gt;
                    &lt;resource&gt;
                        &lt;directory&gt;${basedir}/src/main/resources/&lt;/directory&gt;
                        &lt;includes&gt;
                            &lt;include&gt;jaxb.properties&lt;/include&gt;
                        &lt;/includes&gt;
                    &lt;/resource&gt;
                &lt;/resources&gt;
            &lt;/configuration&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
&lt;/plugin&gt; 

Maven: install jar into repository

install a jar into repository

	
		mvn install:install-file -Dfile={ORACLE_HOME}/jdbc/lib/ojdbc6.jar -Dpackaging=jar\ -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.1.0

Then in your pom.xml file just include the newly added jar:

	
		<dependency>
		 <groupId>com.oracle</groupId>
		 <artifactId>ojdbc6</artifactId>
		 <version>11.1.0</version>
		</dependency>