Archive

Author Archive

Mock liferay services in unit tests for 6.1.1

Using mock Liferay 6.1.1 services in a unit test.

When you are developing components, which interact with Liferay services, you will want / need to use mocks for those services.
In previous versions of Liferay the best strategy for this was to use the LocalServiceUtils in your production code and provide the mocks by setting that mockLocalService on an instance of the LocalServiceUtil.

For instance: To use a mocked GroupLocalService you needed to do the following in your test setup:

GroupLocalServiceUtil groupLocalServiceUtil = new GroupLocalServiceUtil();
groupLocalServiceUtil.setService(mockGroupLocalService);

Read more…

Categories: iPROFS, Liferay Tags: , ,

Bye bye XMLGregorianCalendar (part 2)

Change generated java classes with an XJC plugin.

In the previous post on ‘Bye bye XMLGregorianCalendar‘ I wrote about how you can influence the (un)marshalling of xml to java objects by adding an XmlAdapter to the classpath and an XmlJavaTypeAdapter annotation to a field in the java class. This technique works fine when you are actually writing the java classes your self, but: We don’t do that very often.  One of the main features of XML is that it can be validated against a schema, a contact which defines the valid options and structures with the XML. Most of the times, when we work with XML, there is a schema availabe, either as an standard defined for an industry / product or as part of the contract of a webservice. We can leverage the XSD (XML Schema Definition) to generate Java objects, which represent the elements in XML.

Read more…

Categories: Java Tags: , , , , ,

Patching open-source java software with Maven

16/04/2012 1 comment

As soon as you start using third party libraries in your project, you also introduce all the bugs in those libraries into your project.

There are various ways to handle these kinds of situations:

  • Sometimes you won’t even notice the bugs being present, when you don’t use that section of the library.
  • When you do notice a bug, you can upgrade to newer version of the library in which the bug was already fixed.
  • You might create a work-around in your code.
  • Or you could patch the third-party library.

Sometimes the patch already is present in the trunk of the project, but no newer release is made yet. Encouraging a release-early, release-ofter strategy sometimes work to get a stable release without the bug being present, but it’s good to have alternatives. Most likely you aren’t a committer on the project of the library, so you become dependend on other developers, which could create problems for your deadlines.

This procedure in this post will describe a way to create a stable patched released version of the third party library in your own software repository.

In this post I will use the recaptcha4j library as the example of the software to patch. The only available released version of that library is net.tanesha.recaptcha4j:recaptcha4j:0.0.7. The code in this library still references the server URL’s on https://api-secure.recaptcha.net instead of the newer https://www.google.com/recaptcha/api. Since the names in the SSL certificates won’t match various browsers will show warnings or won’t work at all on the old URL’s. So the task at hand is to create a patched version of the library, which will use the new URL’s.

One way of doing this is copying the entire project into your own source code management tool, make the changes and release software. I prefer to keep the original software as seperate as possible from my own changes. So my way of doing this is:

  1. Create a maven project for the patched version.
  2. Extracting the original classes out of the third party library during a maven build cycle.
  3. Replace the classes, which need to be patched by custom versions.
  4. Create a new jar-file containing the combination of original and patched classes.

Note: Of course I use some naming convention to prevent version conflict between the original software and the patched version.

Create a maven project for the patched version.

Of course you need a project location in your own source code management tool and create the default maven project structure with a pom.xml.

To identify the patched version of the library I use the groupId and artifactId of the original library, so everybody will still recognize dependency on the third party library. Within the version of I add an extra version-digit plus a describtion of the patched.
In our example it would become:

  <groupId>net.tanesha.recaptcha4j</groupId>
  <artifactId>recaptcha4j</artifactId>
  <version>0.0.7.1-iprofs-https-patched-SNAPSHOT</version>

Within this pom I add a dependency to the original ‘broken’ version of the third party library. This will add all classes and dependencies to the classpath of my project enabling my IDE to use those classes during the build.

  <dependency>
    <groupId>net.tanesha.recaptcha4j</groupId>
    <artifactId>recaptcha4j</artifactId>
    <version>${original.recaptcha4j.version}</version>
    <type>jar</type>
  </dependency>

Extracting the original classes

During the build I use the maven-dependency-plugin to extract the classes from the original version to the target build location. This will ensure all classes will become part of the new patched jar-file. You need to exclude all broken classes from extraction, because your patched versions will not become part of the jar-file if the originals are already present in the target location.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <executions>
    <execution>
      <id>unpack</id>
      <phase>generate-sources</phase>
	<goals>
	  <goal>unpack</goal>
	</goals>
	<configuration>
	  <artifactItems>
	    <artifactItem>
		<groupId>net.tanesha.recaptcha4j</groupId>
		<artifactId>recaptcha4j</artifactId>
		<version>${original.recaptcha4j.version}</version>
		<type>jar</type>
		<overWrite>true</overWrite>
		<outputDirectory>${project.build.directory}/classes</outputDirectory>
		<excludes>
		  **/ReCaptchaImpl.class,**/ReCaptchaFactory.class
		</excludes>
	    </artifactItem>
	  </artifactItems>
	</configuration>
     </execution>
   </executions>
 </plugin>

Replace the classes, which need to be patched by custom versions.

Within my project I create the same package structure and classes for all classes, which need to be patched.
Extracting them from a source jar is a very good way to get started or copy them from the libraries version control system.
In my example it would be net.tanesha.recaptcha.ReCaptchaImpl.

Create the patched jar-file.

For this step you don’t need to do anything special. If you properly excluded the patched classes the maven build process will extract and compile all classes to the proper locations and the maven-jar-plugin will build your patched jar-file. Using your normal maven release process you are now able to create a patched stable release version and deploy it into your own software repository.

Tricky situations.

After using this procedure to create a patched version of the recaptha library and redeploying the software I still noticed that references to the old server URL’s were being used. The cause of this weird behaviour was a compiler optimalization called ‘Constant folding‘. ’Constant folding’ is the proces of replacing all references to or calculations of constants values by the final constant value in the byte code of the compiled classes.

Within the recaptcha library the ReCaptchaFactory references the constants defined in the ReCaptchaImpl. In the original class file for the ReCapthcaFactory the values still were the server URL’s which we needed to patch in the first place. Therefor the exclusions in the dependency extraction does contain that Factory as well.

Recommendations.

Contribute back to the original project.

If you went through all this trouble to fix a bug in an open source library, it is recommended that you create a patch of your changes and submit those to the open source project. Many project welcome such contributions and you get to make the world a better place for everybody.

Monitor releases for the original project.

Subscribe to the release mailing list of the original project and monitor their future releases. As soon as the provided a release, which incorporated your patch, switch to using the normal orginal library again.

Categories: iPROFS

Preventing mixed content warnings in your webapplication

Probably we have all run into to problem while browsing the web or using a webapplication: A warning of your browser, which tell you that a secure pages uses non-secure content, script or elements. Sometimes these kind of problems only show up in production, simply because the development and test-environments are running on plain HTTP. It does required some additional setup and configuration to enable HTTPS, but I think you should take the effort to have your local and test server mirror the general configuration of the production environment.

This article describes how can setup your local environment to serve the webapp unsing HTTPS and provides tips to prevent your application having the same problem. Read more…

Categories: Frontend, Infrastructure

Bye bye XMLGregorianCalendar (part 1)

13/02/2012 1 comment

Introduction.

We all know that working with dates in the Java language isn’t perfect, at least when you just look at the standard JDK. Not only is more then half of them methods in java.util.Date deprecated, but in order to get the Date of a java.util.Calendar you have to use the getTime() method. So when the base object aren’t that well to start with, things can only get worse when you start to mix in more technologies like XML.

When you are getting started with marshalling and unmarshalling java objects to XML you’re bound to run into the javax.xml.datatype.XMLGregorianCalendar. Did you ever try to get the Date value for a field unmarshalled from XML and wrote the following code:

Date date = xmlGregorianCalendar.toGregorianCalendar.getTime();

Why isn’t an XMLGregorianCalendar a GregorianCalendar just like a ArrayList is a List or a HashMap is a Map?

Oke, some smart people discovered these problems as well and started to specify a new Date and Time API (JSR 310).
Their idea are great although an anwser in the original JSR does give me some worries:

2.11 Are there any internationalization or localization issues?
No issues are expected.

In my opinion internationalization and localization are the major issues when working with dates and times, but hey, that’s propably just me.

So the expert group started on 13 februari 2007 and finished the early review on 28 march 2010.
I’m really wondering in which version of the JDK this well be included.
And of course once this has been introducted into the JDK: How long will it take to get it supported as the default datatype for  XML dates?

Solution.

Fortunately there is already a solution available: Joda-Time.
With it’s DateTime, Period, Interval and Duration objects it provided a mature, easy to use and comprehensive feature set.

There is only one slight problem: JAXB doesn’t know anything about Joda-Time and it’s DateTime object.
By default fields in an XML-file with a xsd:datetime type will be unmarshalled to an XMLGregorianCalendar.

In various projects I have seen DateConverter utility classes for conversion from and to the Joda-Time DateTime object.
Wouldn’t it be nice if you just could use the DateTime field and have the conversion be done as some form of ‘custom marshalling‘?
But wait: you can! The JAXB API specifies an XMLAdapter, which “Adapts a Java type for custom marshaling

What we need is an XMLAdapter, which allows us marshal and unmashal between a ValueType and the BoundType.
The ValueType is some class, which JAXB knows how to handle out of the box (Strings, Lists or an Calendar and the BoundType is some type that JAXB doesn’t know how to handle. The Adapter will specify how transform from one type to the other.

So I’ve written a DateTimeAdapter, which unmashals from a Calender to DateTime and marshals a DateTime to a Calendar.

public class DateTimeAdapter extends XmlAdapter {

	@Override
	public DateTime unmarshal(Calendar calendar) throws Exception {
		return new DateTime(
			calendar.get(Calendar.YEAR),
			// Correct for the difference between Joda DateTime
			// and JDK Calendar.
			calendar.get(Calendar.MONTH) + 1,
			calendar.get(Calendar.DATE),
			calendar.get(Calendar.HOUR_OF_DAY),
			calendar.get(Calendar.MINUTE),
			calendar.get(Calendar.SECOND),
			calendar.get(Calendar.MILLISECOND),
			DateTimeZone.forTimeZone(calendar.getTimeZone()));
	}

	@Override
	public Calendar marshal(DateTime v) throws Exception {
		Calendar calendar = Calendar.getInstance(v.getZone().toTimeZone());
		calendar.setTime(v.toDate());
		return calendar;
	}

}

Now the tricky part: You have to tell the XML (un)marshaller that it should use the custom adapter for mashalling certain fields in your objects.
But as you propably could have guessed: the JAXB-API provides a solution for that as well:
Just add an XmlJavaTypeAdapter annotation to the field in your object and the Marshaller and Unmarshaller will invoke the Adapter during the process.

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "book", propOrder = {
    "author",
    "title",
    "publicationDate"
})
public class Book {

    @XmlElement(required = true)
    protected String author;
    @XmlElement(required = true)
    protected String title;
    @XmlElement(required = true)
    @XmlSchemaType(name = "date")
    @XmlJavaTypeAdapter(nl.iprofs.util.jaxb.adapter.DateTimeAdapter.class)
    private DateTime publicationDate;

    // Getters and Setters
    .....

}

Part 2: WsImport, Maven and XJC.

In the next blog about this topic I’ll dig into the topic of WsImport with Maven and XJC (XML to Java Compiler) which is being using in generating classes for webservices based upon a WSDL and Schema. If some generator is going to generate the java classes for the SOAP service, I want it to generate fields as DateTime objects and annotate them with my XMLAdapter.
Sound easy, but of course it isn’t just that.

Update on how we do testing

Introduction.

Just like everything in the software industry: You need to make sure that your knowledge and your tools stay up to date.
New developments and new additional framework could make your life easier.

I previously wrote about ‘How we do unit testing with junit and mockito‘.
Recently I started using the Matchers from Hamcrest for writing my test expressions.
That library allows us to specify the requirements in a syntax which almost read like normal english. I just really like things like this:

String message = messageBuilder.getMessage();
assertThat(message, is(equalTo("This message will self destruct in T-10")));

Or this:

List allLetters = AlphabetGenerator.getAllLowerCaseLetters();
assertThat(allLetters, hasItems('a', 'e', 'i', 'o', 'u'));

Tool configuration.

Maven.

In order to use all the libraries in your maven project, you need to have the following dependencies with scope test:

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.8.2</version>
	<scope>test</scope>
</dependency>

<dependency>
	<groupId>org.hamcrest</groupId>
	<artifactId>hamcrest-library</artifactId>
	<version>1.2.1</version>
	<scope>test</scope>
</dependency>

<dependency>
	<groupId>org.mockito</groupId>
	<artifactId>mockito-all</artifactId>
	<version>1.8.5</version>
	<scope>test</scope>
</dependency>

Eclipse.

Since the syntax of the test expression changes, so should the favorites in your IDE.
My list of favorites has been changed to:

  • org.hamcrest.MatcherAssert
  • org.hamcrest.Matchers
  • org.mockito.Mockito
Categories: Java Tags: , , ,

How we do unit testing with JUnit and Mockito

Introduction

Recently iPROFS hired some new guys and I have had the pleasure of working closely with them in their first period with us.
It is always nice to get a lot of guestions like ‘How do you things like ……’ and ‘Is there a standard for ……..’
Some of the things we take for granted, required some explanation. One of the areas of our craftsmanship, where we have some de facto standards is Unit testing. Our company always had a focus on quality, so Unit testing is a required basic skill.

We use JUnit and Mockito for Unit testing in all our projects.

This post describes how we do unit testing based upon a basic and simple scenario in a web environment.

Scenario

A user selects a product in order to add them to the shopping cart.

A Unit test should specify a given scenario, invoke the class under test and verify if the class did what it had to do.
I start writing my tests with three lines of comment:

  1. //describe scenario
  2. //perform action
  3. //verify outcome

Similar to the Given, When, Then sentence from behaviour driven development, but changed due to a naming conflict on the word when with Mockito. The exacts words don’t matter as long as it helps set your mind in the right mood.

Writing the unit test

I’ll start by creating the Test-class with some basic components: An instance of the class to test and a test-method to invoke a single method of that instance.


public class ProductSelectorServletTest() {

// Instantiate the class under test.
private ProductSelectorServlet servlet = new ProductSelectorServlet();

private HttpServletRequest request;
private HttpServletResponse response;

public void testAddSelectedProductToShoppingCard() {

/* describe scenario */
// User selected a product and submitted it.

/* perform action */
servlet.doPost(request, response);

 

/* verify outcome */
// The selected product should have been added to the shopping cart.
}

From this point on it’s just some small steps to implement that in the test code.

Describe the scenario in code

We specify the behaviour of the HttpServletRequest in a set of rules how object should behave when they are invoked by the class under test. In order to specify those rules dynamically, those object should be a Mockito mock, so we need to add the @Mock-annotation to the fields, eg: @Mock private HttpServletRequest request
This alone will not get it working, because by default JUnit doesn’t know how to handle @Mock-annotations. In order to have Mockito initialize the annotated fields we need to the JUnit to run this Test-class with Mockito:


@RunWith(MockitoJUnitRunner.class)
public class ProductSelectorServletTest() {
.....
}

Now start translating the scenario in to actual java statements:


/* describe scenario */
when(request.getParameter("productId")).thenReturn("someId");

Oke, that looks oke, but probably the servlet uses some backend service to get the Product based upon it’s id. So we need to add another line:

when(backendService.getProduct("someId")).thenReturn(someProduct);

This adds two new object to be added as Mock’s

@Mock private BackendService backendService;
@Mock private Product someProduct;

This code assumes that the servlet has access to the backendService, so this requires some initialization of our test:

@Before
public void setUp() {
servlet.setBackendService(backendService);
when(request.getSession()).thenReturn(session);
when(session.getAttribute("shoppingCart")).thenReturn(shoppingCart);
}

Those last two line may have been a surprise, but we need to specify that behavior in order for the servlet to use the proper instances, so we can validate that changes made to it. And so we need two additional mocked fields.


@Mock private HttpSession session;
@Mock private ShoppingCart shoppingCart;

Verification in code

Again: Just translate the requirements into java statements:


// The selected product should have been added to the shopping cart.
verify(shoppingCart).addProduct(someProduct);

Adding this verify statement will instruct the mock shoppingCart to fail the test if the specified method is not invoked with the proper arguments. In those case we know exactly what the argument should be, so we can specify it.
In other cases that might not be true and we need to implement a different way to match the argument of the invoked method to something we expect. Mockito provided various Matchers for that purpose, with the ability to write your own.

Practical tips for Eclipse Users

For those of you, whom use Eclipse as their IDE, just like me, some practical tips:

  1. Add the following types to your favorites for code completion: (Java > Editor > Content Assist > Favorites in preferences)
    • org.junit.Assert
    • org.mockito.Matchers
    • org.mockito.Mockito
  2. Install EclEmma as a Java Code Coverage Plugin to determine if you need additional test scenarios for full test coverate.

Entire test class

Combining all code from this article should result in the following Test:

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class ProductSelectorServletTest {

private ProductSelectorServlet servlet = new ProductSelectorServlet();

@Mock private HttpServletRequest request;
@Mock private HttpServletResponse response;
@Mock private HttpSession session;
@Mock private BackendService backendService;
@Mock private Product someProduct;
@Mock private ShoppingCart shoppingCart;

@Before
public void setUp() {
servlet.setBackendService(backendService);
when(request.getSession()).thenReturn(session);
when(session.getAttribute("shoppingCart")).thenReturn(shoppingCart);
}

@Test
public void testAddSelectedProductToShoppingCard() throws ServletException, IOException {
/* describe scenario */
// User selected a product and submitted it.
when(request.getParameter("productId")).thenReturn("someId");
when(backendService.getProduct("someId")).thenReturn(someProduct);

/* perform action */
servlet.service(request, response);

/* verify outcome */
// The selected product should have been added to the shopping cart.
verify(shoppingCart).addProduct(someProduct);

}

 

}

Categories: Java Tags: , ,
Follow

Get every new post delivered to your Inbox.

Join 169 other followers