Java Ninja Chronicles By Norris Shelton

Things I learned in the pursuit of code

ou would normally marshall a JAXB object to it’s XML String form by something similar to:

marshaller.marshal(tloPersonSearchOutput, stringWriter);

This assumes that the object is annotated with the JAXB @XmlRootElement annotation. If it is not, then you have to create a root element for it, by something like:

marshaller.marshal(new JAXBElement<TLOGenericSearchInput>(new QName("", "rootTag"),
                                                          TLOGenericSearchInput.class,
                                                          searchInput),
                   stringWriter);

You have to create the root element for the object. In this case, the root element is going to be called “rootTag”.

March 13th, 2012

Posted In: Java, xml

Tags: , , ,

Leave a Comment

Springframework has a built-in caching abstraction. The premise is simple enough. Add @Cacheable to a method that I want cached. Add the name of the cache to my existing ehcache.xml file, paste the three lines that they give you into my applicationContext.xml and away you go.

    <!-- Ehcache library setup -->
    <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>

    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cacheManager-ref="ehcache"/>

    <cache:annotation-driven/>

Not so fast there. Guess what happens when you run your Junit tests?

java.lang.IllegalStateException: Failed to load ApplicationContext

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘ehcache’ defined in class path resource [applicationContext-test.xml]: Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: Another unnamed CacheManager already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following:
1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
2. Shutdown the earlier cacheManager before creating new one with same name.
The source of the existing CacheManager is: DefaultConfigurationSource [ ehcache.xml or ehcache-failsafe.xml ]

Just great. You will search feverishly for where you created a second cache manager only for your search to be in vain. The problem is that the cache manager is created for each test, but the previous one still exists. The solution is to add shared=”true” to the declaration of the Ehcache manager factory bean.

    <!-- Ehcache library setup -->
    <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:shared="true"/>

    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cacheManager-ref="ehcache"/>

    <cache:annotation-driven/>

This is all to cause a certain line of code to be executed in the cache manager factory:

	public void afterPropertiesSet() throws IOException, CacheException {
		logger.info("Initializing EHCache CacheManager");
		if (this.configLocation != null) {
			InputStream is = this.configLocation.getInputStream();
			try {
				this.cacheManager = (this.shared ? CacheManager.create(is) : new CacheManager(is));
			}
			finally {
				is.close();
			}
		}
		else {
			this.cacheManager = (this.shared ? CacheManager.create() : new CacheManager());
		}
		if (this.cacheManagerName != null) {
			this.cacheManager.setName(this.cacheManagerName);
		}
	}

That calls the aforementioned create instead of new.

March 8th, 2012

Posted In: Java, Spring

Tags: , , ,

28 Comments

Maven works great and solves lots of conflicting API problems for you.  The one case when it can’t help and usually hurts is when APIs change groupId or artifactId.  I recently had a case where I needed a CXF generated client to log the outbound and inbound soap messages. I added the following to my client spring config file.

<cxf:bus>
    <cxf:features>
        <cxf:logging/>
    </cxf:features>
 </cxf:bus>

This worked great in the small test app that I wrote.  It was an epic fail when I added it to my much larger webapp.

The problem was that the Xerces api that it was finding wasn’t the same version that it thought it was calling.

After much searching, I found Xerces and xml-api Dependency Hell.  This blog went into the history of the various names.  The gist is that now, you use xml-apis:xml-apis for your Maven XML dependency.  You may also have to exclude xerces:xmlParserAPIs and xml-apis:xmlParserAPIs.

While researching this, I ran across Using the EnvironmentCheck utility that can help diagnose XML API classpath problems.

March 1st, 2012

Posted In: Java, xml

One Comment

LinkedIn Auto Publish Powered By : XYZScripts.com