Monthly Archives: March 2015

Watch Maven in Color

Color TV!

Color TV!

Maven is not TV, but if I’m going to watch it, I want to see it in color.

Luckily, it’s straightforward, here’s how:

  1. Delete or backup Maven’s lib/slf4j-simple-1.7.5.jar file.
  2. Copy the following files to Maven’s lib folder:
    1. jansi-1.11.jar (if you are on Windows)
    2. The following Log4j 2 jars (where x is a version number):
      1. log4j-api-2.x.jar
      2. log4j-core-2.x.jar
      3. log4j-slf4j-impl-2.x.jar
    3. slf4j-ext-1.7.5.jar
  3. Create a log4j2.xml configuration file in Maven’s conf/logging folder.

<?xml version="1.0" encoding="UTF-8" ?>
<Configuration>
  <Properties>
    <Property name="maven.logging.root.level">INFO</Property>
  </Properties>
  <Appenders>
    <Console name="console" target="SYSTEM_OUT">
      <PatternLayout pattern="%highlight{[%p] %msg%n%throwable}" />
    </Console>
  </Appenders>
  <Loggers>
    <Root level="${sys:maven.logging.root.level}">
      <Appender-ref ref="console"/>
    </Root>
  </Loggers>
</Configuration>

This will give you output that looks like this:

MavenInColor

The coloring is enabled in the PatternLayout with the highlight option, which gives you decent default colors for each level. You can produce a fancier layout with:

%highlight{%d [%t] %-5level: %msg%n%throwable}

In the above example. the text between %highlight{ and } is the log event template. For an explanation of the templates option, please see the Log4j manual.

You can override the default colors in the optional {style} option. For example:

%highlight{%d [%t] %-5level: %msg%n%throwable}{FATAL=white, ERROR=red, WARN=blue, INFO=black, DEBUG=green, TRACE=blue}

You can highlight only the a portion of the log event:

%d [%t] %highlight{%-5level: %msg%n%throwable}

You can style one part of the message and highlight the rest the log event:

%style{%d [%t]}{black} %highlight{%-5level: %msg%n%throwable}

Enjoy life in color!

Java: Write once, run everywhere? Not quite.

Java: Write once, run everywhere? Not quite. At least not with older versions of Apache CXF, an otherwise fantastic SOAP framework I use in a server side Java 7 app server.

My trouble with the Java Tribbles started when a customer tried to run our proprietary server on an IBM iSeries a.k.a AS/400. IBM has its own JVM called J9 on the 400.No, it’s not a Java 9 preview JVM, it’s just a confusing name, so thanks for that 😉

The first furry incident revealed itself as:

java.lang.NoClassDefFoundError: com/sun/xml/messaging/saaj/soap/SOAPDocumentImpl
	at com.sun.xml.messaging.saaj.soap.SOAPPartImpl.<init>(SOAPPartImpl.java:106)
	at com.sun.xml.messaging.saaj.soap.ver1_1.Message1_1Impl.getSOAPPart(Message1_1Impl.java:90)
	at org.apache.cxf.binding.soap.saaj.SAAJInInterceptor$SAAJPreInInterceptor.handleMessage(SAAJInInterceptor.java:131)
	at org.apache.cxf.binding.soap.saaj.SAAJInInterceptor$SAAJPreInInterceptor.handleMessage(SAAJInInterceptor.java:101)
	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
	at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:122)
	at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:211)
	at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:213)
	at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:154)
	at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:129)
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:187)
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:110)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:166)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:669)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:457)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1075)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:384)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1009)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
	at org.eclipse.jetty.server.Server.handle(Server.java:368)
	at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)
	at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:953)
	at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1014)
	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:861)
	at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
	at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:628)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
	at java.lang.Thread.run(Thread.java:761)

Here we see Jetty running a custom servlet which extends the Apache CXF 2.6.0 AbstractHTTPServlet. I do most of my development on Windows with some Linux testing, all using Oracle JVMs. Oracle bundles all sorts of extra code under the com.sun package which are not part of the Java standard. It’s no surprise then to see an error when the IBM java runtime tries to load com/sun/xml/messaging/saaj/soap/SOAPDocumentImpl.

It turns our there is a workaround for this known problem. You need to set the following system properties:

javax.xml.soap.MessageFactory = com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl 
javax.xml.soap.SOAPFactory = com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPFactory1_1Impl 
javax.xml.soap.SOAPConnectionFactory = com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnectionFactory 
javax.xml.soap.MetaFactory = com.sun.xml.internal.messaging.saaj.soap.SAAJMetaFactoryImpl

See also OpenEJB-1126AXIS-4228 and Customizing your IBM i server for Java usage.

Done? Nope. What happens next is painful:

java.lang.NoClassDefFoundError: com.sun.org.apache.xerces.internal.dom.DocumentImpl
	at java.lang.ClassLoader.defineClassImpl(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:287)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:74)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:540)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:451)
	at java.net.URLClassLoader.access$300(URLClassLoader.java:79)
	at java.net.URLClassLoader$ClassFinder.run(URLClassLoader.java:1038)
	at java.security.AccessController.doPrivileged(AccessController.java:365)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:429)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:677)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:358)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:643)
	at com.sun.xml.messaging.saaj.soap.SOAPPartImpl.<init>(SOAPPartImpl.java:106)
	at com.sun.xml.messaging.saaj.soap.ver1_1.Message1_1Impl.getSOAPPart(Message1_1Impl.java:90)
	at org.apache.cxf.binding.soap.saaj.SAAJInInterceptor$SAAJPreInInterceptor.handleMessage(SAAJInInterceptor.java:131)
	at org.apache.cxf.binding.soap.saaj.SAAJInInterceptor$SAAJPreInInterceptor.handleMessage(SAAJInInterceptor.java:101)
	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
	at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:122)
	at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:211)
	at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:213)
	at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:154)
	at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:129)
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:187)
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:110)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:166)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:669)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:457)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1075)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:384)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1009)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
	at org.eclipse.jetty.server.Server.handle(Server.java:364)
	at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)
	at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:953)
	at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1014)
	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:861)
	at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
	at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:628)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
	at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.ClassNotFoundException: com.sun.org.apache.xerces.internal.dom.DocumentImpl
	at java.net.URLClassLoader.findClass(URLClassLoader.java:434)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:677)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:358)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:643)
	... 46 more

Helmet on? Check. Light on? Check. The class com.sun.xml.messaging.saaj.soap.SOAPPartImpl lives in saaj-impl-1.3.18.jar which is delivered with CXF 2.6.0. What happens at line 106? Nothing dramatic (the listing starts at line 105):

    protected SOAPPartImpl(MessageImpl message) {
        document = new SOAPDocumentImpl(this);
        headers = new MimeHeaders();
        this.message = message;
        headers.setHeader("Content-Type", getContentType());
    }

Let’s take a look at SOAPDocumentImpl then:

package com.sun.xml.messaging.saaj.soap;

import java.util.logging.Logger;

import com.sun.org.apache.xerces.internal.dom.DocumentImpl;
import org.w3c.dom.*;

import com.sun.xml.messaging.saaj.soap.impl.*;
import com.sun.xml.messaging.saaj.soap.name.NameImpl;
import com.sun.xml.messaging.saaj.util.LogDomainConstants;

public class SOAPDocumentImpl extends DocumentImpl implements SOAPDocument {
...

And there you have it, in a nutshell: SOAPDocumentImpl extends com.sun.org.apache.xerces.internal.dom.DocumentImpl. SAAJ 1.3.18 is hard-wired to Sun’s internal copy of Apache Xerces. Blearch!

Luckily for us and our customer, the solution was fairly painless: We can easily drop in a later version of our server which uses Apache CXF 2.7.5 instead of 2.6.0, a version which no longer relies on the SAAJ jar file. This also eliminates the need for the system properties hack mentioned above.

ApacheCon 2015 in Austin, Texas

Dear Apache enthusiasts,

In just a few weeks, we’ll be holding ApacheCon in Austin, Texas, and we’d love to have you in attendance. You can save $300 on admission by registering NOW, since the early bird price ends on the 21st.

Register at http://s.apache.org/acna2015-reg

ApacheCon this year celebrates the 20th birthday of the Apache HTTP Server, and we’ll have Brian Behlendorf, who started this whole thing, keynoting for us, and you’ll have a chance to meet some of the original Apache Group, who will be there to celebrate with us.

We’ve got 7 tracks of great talks, as well as BOFs, the Apache BarCamp, project-specific hack events, and evening events where you can deepen your connection with the larger Apache community. See the full schedule athttp://apacheconna2015.sched.org/

And if you have any questions, comments, or just want to hang out with us before and during the event, follow us on Twitter – @apachecon – or drop by #apachecon on the Freenode IRC network.

Hope to see you in Austin!