Pages

Showing posts with label springframework. Show all posts
Showing posts with label springframework. Show all posts

Thursday, October 30, 2014

Deploying Spring Petclinic demo application to JBoss/WildFly

Spring Petclinic is a very good demo application to experiment with - it is simple enough, yet demonstrates quite a good number of features. Usually I deploy it to Tomcat and obviously don't have any issues with it - it just deploys, runs, and works as expected.

Recently, however, for demonstration purposes, I needed to deploy this application to JBoss (or WildFly). And this is not as straightforward as one might expect.

First I tried with JBossAS 7.1.1.Final. The deployment fails with the following exception:

11:42:38,247 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/petclinic]] (MSC service thread 1-3) Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [spring/business-config.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: javax.persistence.JoinColumn.foreignKey()Ljavax/persistence/ForeignKey;
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1568) [spring-beans-4.1.1.RELEASE.jar:4.1.1.RELEASE]
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:540) [spring-beans-4.1.1.RELEASE.jar:4.1.1.RELEASE]
...

The latest Petclinic application (as of October 2014) uses JPA 2.1 and JBoss 7.1.1 bundles JPA 2.0 APIs. So I decided that it should probably work out of the box on WildFly since it comes with JPA 2.1 jars. And it did - the application deployed just fine, but then there's another library that prevents the application from operating properly - Dandelion:

Exception starting filter dandelionFilter: com.github.dandelion.core.DandelionException: The protocol vfs is not supported. 
        at com.github.dandelion.core.utils.ResourceScanner.scanForResourcePaths(ResourceScanner.java:204) [classes:] 
        at com.github.dandelion.core.utils.ResourceScanner.findResourcePaths(ResourceScanner.java:138) [classes:] 
        at com.github.dandelion.core.bundle.loader.spi.AbstractBundleLoader.loadBundles(AbstractBundleLoader.java:89) [dandelion-core-0.10.0.jar:] 

The issue was reported but at the time of writing this post the fix wasn't published yet. So hopefully Dandelion v0.11.0 will be capable to be deployed on WildFly.

So to overcome this and deploy Spring Petclinic (at the state of October 2014) to WildFly 8.1 one would have to get rid of the dependency on Dandelion, and rewrite some of the JSPs not to use Dandelion taglibs. Then the application deploys and works just fine.

So after making all the fixes I got Spring Petclinic running deployed to WildFly and could monitor it with XRebel:



Sunday, January 4, 2009

SpringSource + Adobe = SpringFramework + Flex

Late in 2008 SpringSource, the SpringFramework vendor, and Adobe, the father of Flex, have partnered to deliver rich Internet applications to Java developers via integration between Spring and Adobe’s Flex.
It was announced that
with support from Adobe, SpringSource is introducing Spring BlazeDS Integration

And just in a few weeks an M1 version for BlazeDS integration was public. This is exactly what I need for my current project, and I can use now an available component, without recreating the wheel :)

Spring, Adobe Partner for Java RIA
Adobe and SpringSource Promise Enhanced Flash-Java Integration
Using BlazeDS with Spring

AOP for Workfow Orchestration

At InfoQ, Oleg Zhurakousky from SpringSource has published an article about Workflow Orchestration Using Spring AOP and AspectJ. The article describes what is needed to implement a flow-like process, to make it flexible and configurable using AOP techniques. I would suggest this article to everyone who is dealing with data flow orchestration and batch processing at work.
Process is a collection of coordinated activities that lead to accomplishing a set goal

Oleg distinguishes the following attributes in his description:
  • Activities - activities defining this process

  • Shared data/context - defines mechanism to share data and facts accomplished by the activities

  • Transition rule - defines which activity comes next after the end of previous activity, based on the registered facts

  • Execution Decision - defines mechanism to enforce Transition rule

  • Initial data/context (optional) - initial state of the shared data to be operated on by this process

This is actually very similar from what we experienced in designing batch processes using SpringFramework at Swedbank.
I'm happy to see that what we did looks very similar to the example from the article.

Friday, March 21, 2008

CaseInsensitiveMap and CollectionFactory

The code of the subject:
  Map map = ...;
map.put("hello", "world")
System.out.println(map.get("hello"));
System.out.println(map.get("HELLO"));
The output:
  world
world
How could this possibly work?
In the real code, the map was received as a result from org.springframework.jdbc.core.JdbcTemplate#queryForList() method call, and SpringFramework 2.0.8 is in use. As it came out, the ResultSet extraction spans down to the org.springframework.core.CollectionFactory class which purpose is
... to avoid runtime dependencies on JDK 1.4+ or Commons Collections 3.x, simply using the best collection implementation that is available.

That said, there's a dependency on Commons Collections 3.x library. The while extracting the ResultSet received from the query call, the framework asks the factory for the map implementation to accumulate the results and makes a call to CollectionFactory#createLinkedCaseInsensitiveMapIfPossible() method:

private static final boolean commonsCollections3Available =
ClassUtils.isPresent("org.apache.commons.collections.map.LinkedMap",
CollectionFactory.class.getClassLoader());
...
public static Map createLinkedCaseInsensitiveMapIfPossible(int initialCapacity) {
if (commonsCollections3Available) {
logger.trace("Creating [org.apache.commons.collections.map.ListOrderedMap/CaseInsensitiveMap]");
return CommonsCollectionFactory.createListOrderedCaseInsensitiveMap(initialCapacity);
}
else if (JdkVersion.isAtLeastJava14()) {
logger.debug("Falling back to [java.util.LinkedHashMap] for linked case-insensitive map");
return JdkCollectionFactory.createLinkedHashMap(initialCapacity);
}
else {
logger.debug("Falling back to plain [java.util.HashMap] for linked case-insensitive map");
return new HashMap(initialCapacity);
}
}
...
private static Map createListOrderedCaseInsensitiveMap(int initialCapacity) {
// Commons Collections does not support initial capacity of 0.
return ListOrderedMap.decorate(
new CaseInsensitiveMap(
initialCapacity == 0 ? 1 :
initialCapacity));
}

So, if the Commons Collections 3.x exists in the classpath, we'll receive a CaseInsensitiveMap decorated with ListOrderedMap to preserve the order in which the objects would be isnerted into the map. In its turn, CaseInsensitiveMap stores calls the Object.toString().toLowerCase() method on any key object that is being added, so the keys are always lowercase strings! And this is why the example above was working.

The problem is that if you won't add the Commons Collections library to classpath, and will use lowercase strings to pick the values (i.e. map.get("some_key")), then you will most probably get null as a result, because there's absolutely no guarantee that the column name in the database is in lowercase.

Disqus for Code Impossible