Kohei Nozaki's blog 

Entries tagged [maven]

Building latest WildFly against latest Undertow


Posted on Wednesday Feb 25, 2015 at 09:34PM in WildFly


Today I had to make some modification to WildFly and Undertow. I’ve got stucked at build most, and had to make many try and error so I leave about it as note. I’m bad at using Maven so I spent most of time at making WildFly to reference latest Undertow package. I tried something like mvn clean install -Dversion.io.undertow=1.2.0.Beta9-SNAPSHOT in wildfly package but it didn’t work. eventually, I installed following packages into my Maven repository.

wildfly-core

Obtain same version as specified in version.org.wildfly.core property in pom.xml of wildfly package (it can be obtained using git tag).

The pom.xml file in this package keeps version.io.undertow property. wildfly package references this property so you need to modify it to desired version of Undertow. I modified it to 1.2.0.Beta9-SNAPSHOT before install it to local Maven repository. note that -Dmaven.test.skip=true makes build fail but -DskipTests=true might work.

undertow

This package doesn’t have annoying dependencies so you just need to make modification you desired and install to your local repository. keep version element in pom.xml and ensure that it is same to version.io.undertow property in wildfly-core.

wildfly

This package has dependency to wildfly-core. ensure that version.io.undertow in wildfly-core is desired one. the build will be made in wildfly/build/target/wildfly-9.0.0.Alpha2-SNAPSHOT.zip.

My final recipe is following:

  1. Run mvn clean install for undertow (1.2.0.Beta9-SNAPSHOT). changes to java code here but no changes to pom here.

  2. Run mvn clean install for wildfly-core (1.0.0.Alpha19). before install, I updated <version.io.undertow> to 1.2.0.Beta9-SNAPSHOT.

  3. Run mvn clean install for wildfly (9.0.0.Alpha2-SNAPSHOT). changes to java code here but no changes to pom here.


Lean example of integration test Maven project for WildFly


Posted on Monday Feb 23, 2015 at 11:20PM in Technology


I created similar example before, but it was redundant. I created more lean version so leave here with some notes. check my GitHub repository for details.

The project contains AppServer class, which extends ExternalResource so it can be used with @Rule annotation of JUnit as follows. note that mavenit is the name of WAR file to be tested.

public class HelloImplIT {

    @ClassRule
    public static AppServer appServer = new AppServer();
    private static Hello sut;

    @BeforeClass
    public static void beforeClass() {
        sut = appServer.lookup("mavenit", HelloImpl.class, Hello.class);
    }

    @Test
    public void test() {
        Assert.assertEquals("Hello world!", sut.hello());
    }
}

The project is easy to use with both of IDE and standalone. to run IT classes with IDE, you need to launch the application server, deploy the project as WAR package, then run a IT class from IDE. if you launched the server at not 8080 port, specify the port in app-server.port system property.

To run IT classes in standalone Maven, use following command. it automatically launches WildFly instance with port offset of 30000, deploy the WAR file, running IT classes, undeploy the WAR and stops WildFly. the command is intended to use from a Jenkins job.

mvn verify -Pintegration-test-with-wildfly \
 -Djava.home=/Library/Java/JavaVirtualMachines/jdk8/Contents/Home/jre \
 -Djboss-as.home=/Users/kyle/servers/wildfly-8.2.0.Final \
 -Dwildfly.port=39990 \
 -Dapp-server.port=38080 \
 -Dwildfly.jvmArgs="-Djboss.server.base.dir=/Users/kyle/servers/wildfly-8.2.0.Final/standalone-mavenit -Djboss.socket.binding.port-offset=30000 -ea"

You can configure following parameters through command line argument:

  • JAVA_HOME-Djava.home

  • WildFly distribution ⇒ -Djboss-as.home

  • jboss.server.base.dir ⇒ inside -Dwildfly.jvmArgs

  • Port offset ⇒ -Djboss.socket.binding.port-offset inside -Dwildfly.jvmArgs. you need to set -Dwildfly.port and -Dapp-server.port accordingly.


Switching EJB remote interface to local interface accordingly to environment


Posted on Monday Feb 23, 2015 at 01:33PM in Technology


Sometimes I need to create both of remote and local interface for EJBs. most of cases that were for integration testing. usually I used this way but that way still has some disadvantages as follows:

  • Annoying creation of both of interface (local and remote) is needed for all of each EJBs

  • Remote interface is redundant for most cases in production environment

To overcome these issues, I moved declarations of EJB from annotation to ejb-jar.xml. XML files are easy to be filtered with build tools such as Maven plugins. consider following case:

Business interface

public interface MyBean {
    String hello();
}

Implementation

public class MyBeanImpl implements MyBean {
    @Override
    public String hello() {
        return "Hello";
    }
}

Injection point

@WebServlet(name = "MyServlet", urlPatterns = "/")
public class MyServlet extends HttpServlet {
    @EJB
    MyBean myBean;
...
}

Test class

public class MyBeanIT {
    static Context ctx;
    static MyBean myBean;

    @BeforeClass
    public static void before() throws Exception {
        Properties props = new Properties();
        // ... put application server specific configuration here ...
        ctx = new InitialContext(props);
        myBean = (MyBean) ctx.lookup("ejb:/ejbxmltest//MyBeanImpl!org.nailedtothex.ejbxmltest.MyBean");
    }

    @AfterClass
    public static void after() throws Exception {
        ctx.close();
    }

    @Test
    public void test() throws Exception {
        org.junit.Assert.assertEquals("Hello", myBean.hello());
    }
}

ejb-jar.xml

<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
         version="3.1">
    <enterprise-beans>
        <session>
            <ejb-name>MyBeanImpl</ejb-name>

            <!-- Will be replaced by business-local with replacer-plugin for production -->
            <business-remote>org.nailedtothex.ejbxmltest.MyBean</business-remote>

            <ejb-class>org.nailedtothex.ejbxmltest.MyBeanImpl</ejb-class>
            <session-type>Stateless</session-type>
        </session>
    </enterprise-beans>
</ejb-jar>

Remote interface and bean definition are presented in ejb-jar.xml instead of annotations. that definition will be used by IDE as default. EJBs will be deployed with a remote interface to the application server in development environment so we can test the bean through remote interface. a trick is in a profile named business-local in pom.xml which intended to use for production environment:

<profile>
	<id>business-local</id>
	<build>
		<!-- Following plugin definitions will be ignored by IDEA -->
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<configuration>
					<warSourceExcludes>WEB-INF/ejb-jar.xml</warSourceExcludes>
				</configuration>
			</plugin>
			<plugin>
				<groupId>com.google.code.maven-replacer-plugin</groupId>
				<artifactId>replacer</artifactId>
				<version>1.5.3</version>
				<executions>
					<execution>
						<phase>prepare-package</phase>
						<goals>
							<goal>replace</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<file>src/main/webapp/WEB-INF/ejb-jar.xml</file>
					<outputFile>target/${project.artifactId}/WEB-INF/ejb-jar.xml</outputFile>
					<token><![CDATA[(?<=</?)business-remote(?=>)]]></token>
					<value>business-local</value>
				</configuration>
			</plugin>
		</plugins>
	</build>
</profile>

maven-replacer-plugin replaces all of business-remote elements by business-local and put it into WEB-INF directory in the target directory, and tell maven-war-plugin to stop copying original WEB-INF/ejb-jar.xml so all of remote interfaces will be local interfaces in production environment. it is disabled by default and you have to enable it with invoke Maven with -P business-local argument. as to injection point (MyServlet) we don’t need to make any modification. @EJB or @Inject will work nevertheless whether the interface is local or remote.

Actually I really want to use Arquillian instead of remote EJB but unfortunately it doesn’t have some flexibility on my use case such as control of deployment timing at the present time.

The project used in test is available in my GitHub repository. the test was done with WildFly 8.2.0.Final.

CAUTION: invoking EJBs via local interface will call by reference but invoking via remote interface will call by value. you will get serious problems that different behavior between invoking local and remote interfaces. consider keep using remote interface on production (with accepting some performance degradation) or using modern testing framework such as Arquillian if necessary.


Running AntUnit in Maven


Posted on Tuesday Jan 27, 2015 at 11:11PM in Technology


These days I’m writing a build.xml and some custom tasks which manipulates OS X’s tmutil (Time Machine utility) and vmrun (VMware utility). testing of custom tasks are bit annoying to me, so I’ve had some googling around and I found AntUnit which is unit test framework for custom Ant tasks. it enables us to test custom tasks in more realistic way than plain JUnit testing. it actually runs the custom tasks in test case which wrote as build.xml. it looks little similar to JUnit test case as follows:

<project xmlns:au="antlib:org.apache.ant.antunit" xmlns="antlib:org.apache.tools.ant">
    <taskdef name="mytask" classname="org.nailedtothex.antunitpractice.MyTask">
        <classpath>
            <pathelement location="${project.build.outputDirectory}"/>
        </classpath>
    </taskdef>

    <target name="setUp">
        <echo>setup</echo>
    </target>

    <target name="test1">
        <mytask property="prop"/>
        <au:assertTrue>
            <equals arg1="Hello from MyTask" arg2="${prop}"/>
        </au:assertTrue>
    </target>

    <target name="tearDown">
        <echo>tearDown</echo>
    </target>
</project>

Targets that beginning their name with test will be automatically executed. we can do assertion with some elements (e.g. au:assertTrue) that provided by AntUnit. target named setUp will be executed before executing every test cases. tearDown also the same as JUnit.

The function of a custom task which I wrote is very simple. it simply set the constant string Hello from MyTask to specified property (prop).

package org.nailedtothex.antunitpractice;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

public class MyTask extends Task {

    private String property;

    public String getProperty() {
        return property;
    }

    public void setProperty(String property) {
        this.property = property;
    }

    @Override
    public void execute() throws BuildException {
        getProject().setNewProperty(property, "Hello from MyTask");
    }
}

So, how to run the test? I used Maven’s maven-antrun-plugin. it doesn’t need annoying preparation such as standalone installation of Ant and AntUnit because it collects annoying dependencies automatically. we only need to run mvn clean test as follows:

kyle-no-MacBook:antunitpractice kyle$ mvn clean test
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building antunitpractice 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ antunitpractice ---
[INFO] Deleting /Users/kyle/src/antunitpractice/target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ antunitpractice ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ antunitpractice ---
[INFO] Compiling 1 source file to /Users/kyle/src/antunitpractice/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ antunitpractice ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ antunitpractice ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ antunitpractice ---
[INFO]
[INFO] --- maven-antrun-plugin:1.8:run (default-cli) @ antunitpractice ---
[INFO] Executing tasks

main:
[au:antunit] Build File: /Users/kyle/src/antunitpractice/target/test-classes/myTaskTest.xml
[au:antunit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.018 sec
[au:antunit] Target: test1 took 0.016 sec
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.413s
[INFO] Finished at: Wed Jan 28 09:38:19 JST 2015
[INFO] Final Memory: 16M/212M
[INFO] ------------------------------------------------------------------------

I haven’t apply this method to actual projects yet but looks useful for some occasions.

More information can be found via the official site of AntUnit. the entire project using in this entry can be found in my GitHub repository.


Progress of reading 2 #packt5dollar - thoughts about build tool


Posted on Friday Jan 23, 2015 at 09:51PM in Technology


I haven’t read IntelliJ IDEA Essentials yet except some parts of Run configuration but it gives me that better view of the mechanism to run an application on the application server or standalone. I read that with Mastering Apache Maven 3 at same time. I didn’t understand particulary how my application will be built and run, but these books improved my understanding drastically.

I guess that every beginner Java programmer would better to learn that how build tool and Java program works through development with simple text editor and cli of build tool before start using a modern IDE. also launching an application server and deploying their application with build tool is good for server-side programmer. it’s important to know what each tool done. I don’t know how much waste my time for stucking in various problem of automated build and deploy mechanism. this can be avoided with correct understanding of the mechanism.

I realized how Maven has many function and flexibility. the book gave me basic knowledge about it but still I have to learn more advanced topics such as real-world use case which used multi module scheme. there are more Maven books published that mentioned about more specific topic so I would read these books later.

Also I should look back that book sometimes because I might misunderstood or simply couldn’t understand at some part of the book. also there are many plugins that the book didn’t mentioned comprehensively (I know it’s impossible for only one book) so I need to learn about it on the web or another books.