RSS

Monthly Archives: July 2012

Configuring Jetty with exploded web archives

Abstract : Having a great number of useful features, Jetty is one of the most popular servlet containers around. In this post we are going to prepare our test-bed with Jetty using exploded web archives (WAR) without any integrated development environment (IDE) plugins (such as IntelliJ Jetty integration plug-in or Eclipse Jetty Plugin).

Goal : Prepare a Jetty-enabled test-bed using exploded WAR content

Acknowledgement : My gratitude goes to the open source community and to the following people:

Arthur Kahn for presenting me with this challenge and for his help

Step 1 : Download Jetty and extract the Jetty archive in a convenient for you directory. I’m going to use Jetty version 8.1.4 but hopefully this post will be still valid for other versions.

Step 2 : Let’s say you’ve extracted Jetty in a directory called jetty_home. Make a copy of jetty.xml, called jetty-exploded-web.xml. You can find jetty.xml in jetty_home/etc and you should place jetty-exploded-web.xml there as well.

Step 3 : Make a directory under jetty_home called exploaded-context-deploy. We will put the web application context files of our web projects in this directory.

Step 4 : Add the following few lines to jetty-exploded-web.xml just before the closing tag:

    <!-- =========================================================== -->
    <!-- exloded web archives options                                -->
    <!-- =========================================================== -->
    <Call name="addLifeCycle">
        <Arg>
            <New class="org.eclipse.jetty.deploy.ContextDeployer">
                <Set name="contexts">
                    <Ref id="Contexts"/>
                </Set>
                <Set name="configurationDir">exploaded-context-deploy</Set>
                <Set name="scanInterval">1</Set>
            </New>
        </Arg>
    </Call>

Step 5 : Say we have two web apps: web-app-1 and web-app-2. We are going to put the web context files of these web applications in the jetty_home/exploaded-context-deploy directory. Both context files are quite similar except for the web app names, thus I’ll post the content of web-app-1.xml only:

<?xml version="1.0"  encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
    <Set name="contextPath">/web-app-1</Set>
    <Set name="resourceBase">/absolute/path/to/web-app-1</Set>
</Configure>

Step 6 : Comment the line etc/jetty.xml in the jetty_home/start.ini file and add the line etc/jetty-exploded-web.xml. Here is an example of start.ini file:

#===========================================================
# Start classpath OPTIONS.
# These control what classes are on the classpath
# for a full listing do
#   java -jar start.jar --list-options
#-----------------------------------------------------------
OPTIONS=Server,jsp,jmx,resources,websocket,ext,plus,annotations,overlay
#-----------------------------------------------------------

#===========================================================
# Configuration files.
# For a full list of available configuration files do
#   java -jar start.jar --help
#-----------------------------------------------------------
etc/jetty-jmx.xml
#etc/jetty.xml
etc/jetty-exploded-web.xml
etc/jetty-annotations.xml
# etc/jetty-ssl.xml
# etc/jetty-requestlog.xml
etc/jetty-deploy.xml
#etc/jetty-overlay.xml
etc/jetty-webapps.xml
etc/jetty-contexts.xml
etc/jetty-testrealm.xml

Step 7 : In order to run Jetty on port 8090 you have to execute the following from jetty_home:

java -Djetty.port=8090 -jar start.jar

Note that if you don’t provide the -Djetty.port=8090, Jetty will run on port 8080 by default.

Hot deploy : Note that Jetty is not going to automatically detect re-compiled Java classes, so one way to tell Jetty to reload a web app is to add a small change to the web app’s context file. For example if you have re-compiled web-app-1 adding a new line to web-app-1.xml web context file and saving it will be enough for telling Jetty to reload the project.

Remote debugging : If you want to attach a debugger (i.e. when using Eclipse, IntelliJ, etc.) to Jetty on port 8008 you have to run Jetty as follows:

java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8008 -jar start.jar

Extra classpaths : You can specify extra class paths for your web application by indicating this in the web context file, as follows:

<Configure class="org.eclipse.jetty.webapp.WebAppContext">
 ...
 <Set name="extraClasspath">/extra/classes,/extra/extra.jar</Set>
 ...
</Configure>
 
Leave a comment

Posted by on July 22, 2012 in Jetty

 

Tags: ,

Testing AKKA actors with Mockito and FEST-Reflect

Abstract : One of the few frameworks implementing the actor model is AKKA. In fact AKKA is a lot more than just an implementation of the actor model, but within this post we are going to concentrate on combining Mockito, JUnit and FEST-Reflect in order to facilitate actor testing and thus we won’t need all the fancy features of AKKA.
Goal : Mocking an instance field within an AKKA actor.
Acknowledgement: My gratitude goes to the open source community and to the following people:
Munish K Gupta – Using AKKA testkit with Java

In order to reach our goal will need the following maven configuration. Note that you need to add the AKKA repository:

<!-- other maven configuration -->
    <dependencies>
        <dependency>
            <groupId>com.typesafe.akka</groupId>
            <artifactId>akka-actor</artifactId>
            <version>2.0.2</version>
        </dependency>

        <dependency>
            <groupId>org.easytesting</groupId>
            <artifactId>fest-reflect</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>3.1.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
        </dependency>

        <dependency>
            <groupId>com.typesafe.akka</groupId>
            <artifactId>akka-testkit</artifactId>
            <version>2.0.2</version>
        </dependency>

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.9.0</version>
        </dependency>

    </dependencies>

    <repositories>
        <repository>
            <id>akka.repository</id>
            <name>Akka Maven Repository</name>
            <url>http://repo.akka.io/releases/</url>
        </repository>
        <!-- other repositories ... -->
    </repositories>

The actor which we are going to test looks like this:

import akka.actor.UntypedActor;
import com.honeysoft.business.service.IBusinessService;
import org.springframework.beans.factory.annotation.Autowired;

public class BusinessActor extends UntypedActor {

    @Autowired
    private IBusinessService businessService;

    @Override
    public void onReceive(Object message) {
        businessService.doBusiness(message);
    }
}

As you can see, I’m using Spring framework for dependency injection within the actor, but you are free to choose whatever approach you want to instantiate and assign the business service.

Our goal is quite simple, we have to mock the businessService within our BusinessActor. The difficulty comes from the fact that in a test case we are going to have an ActorRef reference variable to our actor and not a plain Actor reference. This means that our actor is actually nested within an ActorRef reference. As you might already guessed this brings further complications for mocking our businessService reference within the actor instance itself. Or in other words, our businessService is deeply nested and the exact path is actorRef.actorCell.actor.businessService. Luckily for us, since version 1.4 of FEST-Reflect we can play with (deeply) nested fields with a single line of code (not counting the static import). Here is how:

import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import com.honeysoft.business.service.IBusinessService;
import com.typesafe.config.ConfigFactory;
import org.fest.reflect.core.Reflection;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

import static org.fest.reflect.core.Reflection.*;
import static org.mockito.Matchers.eq;

@RunWith(MockitoJUnitRunner.class)
public class TestBusinessActor {

    static ActorSystem akkaSystem = ActorSystem.create("honeysoft-test-system", ConfigFactory.load().getConfig("honeysoft-test-system"));

    @Mock
    private IBusinessService businessServiceMock;

    private ActorRef businessActor;

    @Before
    public void setup() {
        businessActor = akkaSystem.actorOf(new Props(BusinessActor.class));
    }

    @After
    public void clean() {
        akkaSystem.stop(businessActor);
    }

    @Test
    public void shouldExecuteBusinessMethod() {
        //GIVEN
        String businessMessage = "Some business message";

        field("actorCell.actor.businessService").ofType(IBusinessService.class)//
            .in(businessActor).set(businessServiceMock);

        //WHEN
        businessActor.tell(businessMessage);

        //THEN
        Mockito.verify(businessServiceMock, Mockito.times(1))//
            .doBusiness(eq(businessMessage));
    }
}

As you can see from the highlighted line 43 setting a deeply nested variable is as simple as specifying the path to it. Note that the exact path is businessActor.actorCell.actor.businessService, but the businessActor is already passed to the .in() method and thus as an argument to field() we have only “actorCell.actor.businessService”.

To run the test you are also going to need a configuration file named application.conf which I have placed in my src/test/resources directory. The content of application.conf is:

honeysoft-test-system {
	akka {
	    mode = test
	  	event-handlers = ["akka.testkit.TestEventListener"]
		loglevel = DEBUG
		actor {
			debug {
			 receive = on
			 autoreceive = on
			 lifecycle = on
			}
		}
  	}
}

Well that was all for this post. Don’t hesitate to leave a comment!

 
2 Comments

Posted by on July 1, 2012 in AKKA, FEST-Reflect, Java, JUnit, Maven, Mockito

 

Tags: , , , ,