wtorek, 26 listopada 2013

Problem with git rebase - 'Your local changes to the following files would be overwritten by merge'. No local changes?

This will be definitely a very short post. However, I spent so much time trying to figure out what the heck is going on and why I cannot rebase, that I just decided to write it down. The help itself came from my brother: The problem occurs when you work on the same git repo with someone using different operating system then you. In my case it was Windows and Linux. When I was trying to rebase my commit on a fetched branch, I would alwasy get an error thet there are local uncommited changes, wheras of course all of my changes were already commited. The problem itself can be fixed with following simple trick:
git config --global core.trustctime false
More info on the issue can be found on stackoverflow

czwartek, 24 października 2013

Instant Apache Camel Messaging System released by Packt Publishing.

I am pleased to announce that a book on Apache Camel "Instant Apache Camel Messaging System" that I had a pleasure to review as one of technical reviewers is out. See more here: Instant Apache Camel Messaging System. It is a must read if you want to get your hands quickly on the framework or at least find out what it can do for you.

sobota, 23 lutego 2013

Various @Aspects of Java (Spring AOP)

Intro

The easiest way of learning and implementing aspects is with Spring-AOP. Regarding configuration, as always, you've got two options: XML and annotations. In this article I'll show a small example using annotations:

First, I'll present very simple xml configuration




    
    
    
    
    
    

Now, very simple class defining our pointcut and its implementation:

package com.mp.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

@Component
@Aspect
public class ProfilingAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(ProfilingAspect.class);

    @Pointcut("execution( * com.mp.intercepted.jvmproxy..*(..) )")
    public void profilingPointcut() {}

    @Around("profilingPointcut()")
    public String logProfileInfo(ProceedingJoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        String result = "";
        try {
            result = (String)joinPoint.proceed();
        } catch (Throwable throwable) {
            LOGGER.error(String.format("Error when executing original method [%s]", methodName), throwable);
            stopWatch.stop();
            LOGGER.debug(String.format("Elapsed time when error occured executing method[%s] : [%s]", methodName, stopWatch));
            if(throwable instanceof Error){
                throw (Error)throwable;
            }
        }
        stopWatch.stop();
        LOGGER.debug(String.format("Elapsed time executing method [%s]: [%s]", methodName, stopWatch));
        return "Intercepted: " + result;
    }

}

Pointcut expression "execution( * com.mp.intercepted.jvmproxy..*(..) )" instructs Spring to intercept any method call from package com.mp.intercepted.jvmproxy.

Weaving cheat - JVM Proxy

In original, non-spring AOP, apart from pointuct definitions and classes to be intercepted, we need a weaver - an agent that will weave our code either at compile time, load time or in runtime. With spring AOP it is a bit simpler:

JVM Proxy

If we define an interface for a bean:

package com.mp.intercepted.jvmproxy;

public interface InterceptedWithSpringAopJvmProxy {
    String methodToBeIntercepted();
}

... and an implementation:

package com.mp.intercepted.jvmproxy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;


@Component
public class InterceptedWithSpringAopImpl implements InterceptedWithSpringAopJvmProxy {
    private static final Logger LOGGER = LoggerFactory.getLogger(InterceptedWithSpringAopImpl.class);

    public String methodToBeIntercepted(){
        LOGGER.debug("Entering method to be intercepted");
        return "Not intercepted";
    }
}

... then Spring itself will generate dynamic proxy when creating our bean. The easiest way to find this out is to put a breakpoint on original method and analyze the stack-trace

   at com.mp.intercepted.jvmproxy.InterceptedWithSpringAopImpl.methodToBeIntercepted(InterceptedWithSpringAopImpl.java:20)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-1)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
   at java.lang.reflect.Method.invoke(Method.java:601)
   at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
   at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80)
   at com.mp.aspect.ProfilingAspect.logProfileInfo(ProfilingAspect.java:34)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-1)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
   at java.lang.reflect.Method.invoke(Method.java:601)
   at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
   at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
   at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
   at $Proxy12.methodToBeIntercepted(Unknown Source:-1)

You can see at lines 21 and 22 in the above snippet that indeed $Proxy... is used.

Instrumentation with CGLIB

Dynamic proxy mechanism is used only when there is an interface that the JDK can use to produce the proxy. If we remove the interface, then we will get following exception:

 ... 
Caused by: java.lang.ClassNotFoundException: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException
 at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
 at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
 ... 52 more

The above exception informs us that we have no aspectj weaver in our depencencies. Adding it still does not solve the problem, as we get following exception:

        ...
Caused by: org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.
 at org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy(DefaultAopProxyFactory.java:67)
 at org.springframework.aop.framework.ProxyCreatorSupport.createAopProxy(ProxyCreatorSupport.java:104)
 at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:112)
 at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:476)
 at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362)
 at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1461)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
 ... 40 more

After putting cglib2 dependency into pom classes not implementing any interface get correctly weaved with cglib and aspects get fired as expected

<!--CGLIB-->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
        </dependency>

Limitations

As shown in previous two examples, implemeting aspects with spring AOP is very easy. In case of dynamic JVM proxies, we don't even need AspectJ weaver to be present, as actually no weaving takes place. However, this approach has some serious limitations:

  1. You cannot intercept static methods
  2. You cannot intercept method calls on objects that are not spring managed beans

In the next post I'll describe how to overcome these limitations with AspectJ

Source code location

You can find the source code related to this post in my github repository

PS: Problem with self-invocation

Let's assume we have following class:
package com.mp.nestedintercepted;

import com.mp.intercepted.jvmproxy.InterceptedWithSpringAopJvmProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class InterceptedWithSpringAopNested  {
    private static final Logger LOGGER = LoggerFactory.getLogger(InterceptedWithSpringAopNested.class);

    public Integer nested(){
        LOGGER.debug("Entering method to be intercepted");
        return nested("") + 1;

    }

    public Integer nested(String arg){
        return 1;
    }
}

and following pointcut

@Pointcut("execution( * com.mp.nestedintercepted..nested(..) )")

"Implementation" of this pointuct is as follows:

    @Around("nestedPointcut()")
    public int addOneToOriginalResult(ProceedingJoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        int result = 0;
        try{
            result = (Integer)joinPoint.proceed();
            result += 1;
        } catch (Throwable t){
            LOGGER.error(String.format("Error when executing original method [%s]", methodName), t);
            if(t instanceof Error){
                throw (Error)t;
            }
        }
        return result;
    }

You could expect, that both method call to nested() and to nested(String arg) will be intercepted, so any method call to nested() should return 4. Nevertheless, because interception (or weaving), in case of Spring AOP, is implemented using proxies, and the original class InterceptedWithSpringAopNested knows nothing of the proxy, the call to nested(String arg) is just a regular method call. If you download source code, you can check this behaviour running test InterceptedWithSpringAopNested.

niedziela, 13 stycznia 2013

Google guava presentation and guide to writing testable code

Below you can find very interesting links. One to google's guide to writing testable code. It can be treated as a nice checklist helping to keep code clean. Another, sent to me by a friend of mine, to a very nice project and presentation helping to learn guava

sobota, 12 stycznia 2013

XSLT Identity Transformation Overriding pattern and xsltproc - easy xml files manipulation (unix only)

Recently I faced the problem where I had to modify bunch of XML files scattered all over the file system. The modification was very small - move value of one XML tag into another, and remove the original tag.

The problem itself seems very simple, so writing a piece of software for that seems to be like killing a sparow with a bazooka.

Here is what I came up with

XSLT Identity Transformation Overriding pattern

Because our modification is very small, and we want to preserve most of our original document structure, we should start with XSLT Identity Transformation which looks like following

 
 
  
   
  
 

Now let's say, that we want to add another fridge to our kitchen in the following xml document, but only if the house is locked (house/isLocked element is set to true)

<house>
 <isLocked>true</isLocked>
 <kitchen>
  <cupboard>
   <capacity>8</capacity>
  </cupboard>
  <fridge>
   <boughtOn>2013-01-10T20:45:45.033+01:00</boughtOn>
   <innerTemperature>-4</innerTemperature>
  </fridge>
  <isLocked>true</isLocked>
 </kitchen>
 <livingRoom>
  <isLocked>true</isLocked>
 </livingRoom>
</house>

We can modify (override) our XLST Identity Transformation in following way:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <!--  Identity transform -->
 <xsl:template match="@*|node()">
  <xsl:copy>
   <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
 </xsl:template>

 <!-- add a node fridge into our kitchen -->
 <xsl:template match="kitchen">
  <xsl:copy>
   <xsl:apply-templates/>
   <!-- only if house is locked -->
   <xsl:if test="/house/isLocked = 'true'">
   <fridge>
    <boughtOn>2013-01-10T20:45:45.033+01:00</boughtOn>
    <innerTemperature>-10</innerTemperature>
   </fridge>
   <!-- add new line -->
   <xsl:text>
   </xsl:text>
   </xsl:if>
  </xsl:copy>
 </xsl:template>    
 <!-- "unlock" the house (remove isLocked element) -->
 <xsl:template match="/house/isLocked">
 </xsl:template>
</xsl:stylesheet>

You can quickly see the result of transformation using xsltproc, which is a little unix commandline program for performing xslt transformations.

xsltproc newFridge.xslt kitchen.xml > kitchen.xml.out

Now, if you want to apply the same tranformation to a bunch of files selected from system with, say, find method, you can perform following

for f in `find -name "house*.xml"` ; do xsltproc xslt/newFridge.xslt "$f" > "$f.out"; done

If you don't care for the *.out files, you can always add mv so it will look like transformation was performed on on the original files:

for f in `find -name "house*.xml"` ; do xsltproc xslt/newFridge.xslt "$f" > "$f.out" ; mv "$f.out" "$f" ; done

These altoghether will give you a very easy, yet powerful, tool for mass xml manipulation. I run all of these commands on cygwin

czwartek, 10 stycznia 2013

JAXB - unmarshalling nested element

To fully benefit from this post I suggest visiting following tutorial on XSD and namespaces, and this one describing what is a globally declared element in XSD and why some of them get @XmlRootElement annotation and others have ObjectFactory with method annotated with @XmlElementDecl. The general rule is that if we have globally declared element (not type, element) which contains:
  1. Inline type declaration (anonymous type, as in case of kitchen element from rooms.xsd), it will be annotated with @XmlRootElement
  2. Reference to named type declaration (like houseObject element in houses.xsd), it will have corresponding ObjectFactory with createXXX method annotaded with @XmlElementDecl
As an intro to this post, let's create some xsd files on which we will work: house.xsd
<xs:schema xmlns:house="http://houses.service.jaxb.mpasinski/"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:rooms="http://rooms.houses.service.jaxb.mpasinski/"
           version="1.0"
           targetNamespace="http://houses.service.jaxb.mpasinski/">
    <xs:import namespace="http://rooms.houses.service.jaxb.mpasinski/" schemaLocation="rooms.xsd"/>

    <!-- globally defined element with named type -->
    <!-- it will result in XmlElementDecl annotation in ObjectFactory -->
    <xs:element name="houseObject" type="house:house"/>

    <!--globally defined elements with anonymous type (inline definition)-->
    <!--it will result in XmlElementRoot annotation to be added to generated class-->
    <xs:element name="houseRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="house:houseObject"/>
                <xs:element name="requestDateTime" type="xs:dateTime"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="houseLockedRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="house:houseObject"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="isHouseLockedResponse" type="xs:boolean"></xs:element>

    <!-- Type definition -->
    <xs:complexType name="house">
        <xs:sequence>
            <xs:element name="isLocked" type="xs:boolean" minOccurs="0"/>
            <xs:element ref="rooms:kitchen" minOccurs="0"/>
            <xs:element name="livingRoom" type="rooms:livingRoom" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>
rooms.xsd
<xs:schema
        xmlns:furniture="http://furniture.service.jaxb.mpasinski/"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        version="1.0"
        targetNamespace="http://rooms.houses.service.jaxb.mpasinski/">
    <xs:import namespace="http://furniture.service.jaxb.mpasinski/" schemaLocation="furniture.xsd"/>

    <!--below is the globally defined element with anonymous type-->
    <!--jaxb will add XmlRoot annotation to the class-->

    <xs:element name="kitchen">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="cupboard" type="furniture:cupboard" minOccurs="0"/>
                <xs:element name="fridge" type="furniture:fridge" minOccurs="0"/>
                <xs:element name="isLocked" type="xs:boolean" minOccurs="0"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <!--type declaration-->
    <xs:complexType name="livingRoom">
        <xs:sequence>
            <xs:element name="isLocked" type="xs:boolean" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>
furniture.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           version="1.0"
           targetNamespace="http://furniture.service.jaxb.mpasinski/"
           elementFormDefault="qualified">

    <!--contains only type declarations, no globally defined elements-->
    <xs:complexType name="cupboard">
        <xs:sequence>
            <xs:element name="capacity" type="xs:int" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="fridge">
        <xs:sequence>
            <xs:element name="boughtOn" type="xs:dateTime" minOccurs="0"/>
            <xs:element name="innerTemperature" type="xs:int" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>
Now, let's say we received an xml request document with following format:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<houses:houseRequest xmlns:furniture="http://furniture.service.jaxb.mpasinski/" xmlns:houses="http://houses.service.jaxb.mpasinski/" xmlns:rooms="http://rooms.houses.service.jaxb.mpasinski/">
    <houses:houseObject>
        <isLocked>true</isLocked>
        <rooms:kitchen>
            <cupboard>
                <furniture:capacity>8</furniture:capacity>
            </cupboard>
            <fridge>
                <furniture:boughtOn>2013-01-10T20:45:45.033+01:00</furniture:boughtOn>
                <furniture:innerTemperature>-4</furniture:innerTemperature>
            </fridge>
            <isLocked>true</isLocked>
        </rooms:kitchen>
        <livingRoom>
            <isLocked>true</isLocked>
        </livingRoom>
    </houses:houseObject>
    <requestDateTime>2013-01-10T20:45:45.037+01:00</requestDateTime>
</houses:houseRequest>

We do not care for the for the whole request, but only for kitchen object. Our first attempt to get to the element might be like that:

        String houseRequest = TestUtils.readClasspathFile("houseRequest.xml");

        JAXBContext jaxbContext = JaxbUtils.getJAXBContext(Kitchen.class);
        JAXBElement<Kitchen> result = jaxbContext.createUnmarshaller().unmarshal(new StreamSource(new ByteArrayInputStream(houseRequest.getBytes())), Kitchen.class);
        Kitchen unmarshalledKitchen =  result.getValue();
But after inspecting the retreived kitchen object we find out that both cupboard and fridge are null:
Kitchen@5749b290[cupboard=<null>,fridge=<null>,isLocked=true]

The reason for that is simple. XML does not convey information about type, so JAXB does not know it should start searching for the kitchen element starting from kitchen tag. For the same reason, isLocked in our unmarshalled kitchen is set properly - JAXB found element isLocked (as it expected for kitchen object) and it does not care it that it belongs to houseObject (so different Java type). The reason why our unmarshalling faild becomes even more obvious when we look at result object (of JAXBElement type)

javax.xml.bind.JAXBElement@276a38b5[name={http://houses.service.jaxb.mpasinski/}houseRequest,
declaredType=class mpasinski.jaxb.service.houses.rooms.Kitchen,
scope=class javax.xml.bind.JAXBElement$GlobalScope,
value=mpasinski.jaxb.service.houses.rooms.Kitchen@6765f738,
nil=false]

Unmarshalling nested element with StAX and XMLReader

First we need to tell JAXB where to start unmarshalling our object:

String houseRequest = TestUtils.readClasspathFile("houseRequest.xml");
String nodeName = "kitchen";
Kitchen unmarshalledKitchen = null;

//create XMLStreamReader (StAX)
XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xmlReader = xif.createXMLStreamReader(new StringReader(houseRequest));

int event = 0;
//here we advance to next tag untill we find node called "kitchen"
for (event = xmlReader.next(); event != XMLStreamReader.END_DOCUMENT; event = xmlReader.next()) {
    if (event == XMLStreamReader.START_ELEMENT) {
        if (xmlReader.getLocalName() == nodeName) {
            break;
        }
    }
}

Now all we need to do is just unmarshalling

        if (event != XMLStreamReader.END_DOCUMENT) {
            JAXBContext jaxbContext = JaxbUtils.getJAXBContext(Kitchen.class);
            JAXBElement<Kitchen> result = jaxbContext.createUnmarshaller().unmarshal(xmlReader, Kitchen.class);
            unmarshalledKitchen = result.getValue();
        }

If we analyze our unmarshalled object now, we get following form:

mpasinski.jaxb.service.houses.rooms.Kitchen@4b00ebec
 [cupboard=mpasinski.jaxb.service.furniture.Cupboard@2980f96c,
  fridge=mpasinski.jaxb.service.furniture.Fridge@527736bd,
  isLocked=true]
//cupboard
mpasinski.jaxb.service.furniture.Cupboard@2980f96c[capacity=8]
//fridge
mpasinski.jaxb.service.furniture.Fridge@527736bd
 [boughtOn=java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="GMT+01:00",offset=3600000,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2013,MONTH=0,WEEK_OF_YEAR=1,WEEK_OF_MONTH=1,DAY_OF_MONTH=10,DAY_OF_YEAR=1,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=20,MINUTE=45,SECOND=45,MILLISECOND=33,ZONE_OFFSET=3600000,DST_OFFSET=0],
  innerTemperature=-4]

On my github repo you can find JaxbUtils class which has method doUnmsarshallNestedElement being refactored version of the code above. You can find there also the complete code used in this post.

Of course the definite flaw of this method is that it will try to unmarshall first element with specified name. A better way to perform unmarshalling nested element may be to use EclipseLink MOXy jaxb implementation and the @XmlPath extension. However, there are times where you cannot change the jaxb implementation or you cannot alter generated classes (therefore you cannot add @XmlPath annotation)

wtorek, 8 stycznia 2013

Using guava cache to avoid expensive JAXBContext recreation

Creating JAXBContext is very expensive, especially when many classes are "known" to this context (just as a side note, a class is known to JAXBContext when it is in the package which name was passed to newInstance method or in the same package as class passed to newInstance method). Using guava's cache can be a very nice way of acheiving JAXBContext caching

private static final LoadingCache<String, JAXBContext> jaxbContextsCache = CacheBuilder.newBuilder()
            .build(
                    new CacheLoader<String, JAXBContext>() {
                        @Override
                        public JAXBContext load(String packageName) throws Exception {
                            return JAXBContext.newInstance(packageName);
                        }
                    }
            );

    public static JAXBContext getJAXBContext(Class clazz) {
        String packageName = clazz.getPackage().getName();
        try {
            return jaxbContextsCache.get(packageName);
        } catch (ExecutionException e) {
            throw new JaxbUtilsException("Error when getting JAXBContext from cache", e);
        }
    }

It is worth noting, that JAXBContext is thread safe, but Marshaller and Unmarshaller objects are not (at least by JAXB specification contract) and therefore should not be shared. You can implement some pooling if you need critical performance. This article explains marshaller/unmarshaller pooling and shows example code

Source code related to this post can be found on my git repository