Issue 1:
Marty Pitt opened SPR-9741 and commented

When specifying the name of a persistence unit to use for LocalContainerEntityManagerFactoryBean (ie., assuming there are multiple persistence units defined in persistence.xml), this name is now applied to the persistence unit from scanned pacakges.

In 3.1.0, the name applied to the generated package was 'default'. However, now, the name applied is the one defined in the entityManager configuration.

This results in an exception "Conflicting persistence unit definitions for name 'xxx'".

This is a breaking change in behaviour from 3.1.0 to 3.1.2.

The change is caused by new setter behaviour introduced in LocalContainerEntityManagerFactoryBean in 3.1.2, specifically this code:

{{

@Override

public void setPersistenceUnitName(String persistenceUnitName) {

super.setPersistenceUnitName(persistenceUnitName);

this.internalPersistenceUnitManager.setDefaultPersistenceUnitName(persistenceUnitName);

}

}}

This changes the internal defaultPersistenceUnitName from default. Later, when DefaultPersistenceUnit.buildDefaultPersistenceUnitInfo() is called, a new persistence unit is generated using this name:

{{

private SpringPersistenceUnitInfo buildDefaultPersistenceUnitInfo() {

SpringPersistenceUnitInfo scannedUnit = new SpringPersistenceUnitInfo();

scannedUnit.setPersistenceUnitName(this.defaultPersistenceUnitName);

scannedUnit.setExcludeUnlistedClasses(true);

}}

This then results in an exception being thrown.

As an example, here's the defined Persistence.xml, which contains both a prod config, and a test config:

{{

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="1.0"

xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">

<persistence-unit name="production">

<properties>

<!-- JPA Configuration goes here -->

</properties>

</persistence-unit>

<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">

<provider>org.hibernate.ejb.HibernatePersistence</provider>

<properties>

<!-- JPA Configuration goes here -->

</properties>

</persistence-unit>

</persistence>

}}

Then, the appropriate config is selected in the EntityManager configration:

{{

<bean id="entityManagerFactory"

class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<property name="dataSource" ref="dataSource" />

<property name="packagesToScan">

<list>

<value>aa.bb.cc</value>

</list>

</property>

<property name="persistenceUnitName" value="test" />

<property name="jpaVendorAdapter">

<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

<property name="showSql" value="true" />

<property name="generateDdl" value="true" />

<property name="databasePlatform" value="org.hibernate.dialect.H2Dialect" />

</bean>

</property>

</bean>

}}

This causes the exception.

Affects: 3.1.2

Reference URL: http://stackoverflow.com/questions/12189921/conflicting-persistence-unit-definitions-when-testing

Referenced from: commits 0cf4a26, f32e407

Issue 2:
薛伟 opened SPR-1003 and commented

A FactoryBean which can use the powerful OGNL expression language

with OGNL support,developers can invoke method,static method,static field and some advanced operation straightforward and easy.

the sourcecode

/*

Created on 2005-6-2

*/

package org.snowway.spring.extension;

import java.util.Collections;

import java.util.Hashtable;

import java.util.Map;

import org.springframework.beans.BeansException;

import org.springframework.beans.FatalBeanException;

import org.springframework.beans.factory.FactoryBean;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ApplicationContextAware;

import ognl.Ognl;

import ognl.OgnlException;

/**

@author snowway

@version $Id$

<p>

A FactoryBean which can use the powerful OGNL expression language<br>

need runtime OGNL support(e.g. ognl-2.6.5.jar)<br>

the default root object for OGNL expression is ApplicationContext instance<br>

*/

public class OgnlExpressionFactoryBean implements FactoryBean,ApplicationContextAware{

//the ognl expression

private String expression;

//the naming context for the evaluation

private Map context;

private ApplicationContext applicationContext;

//the ognl root object,default is ApplicationContext instance

private Object root;

//is user define custom root object

private boolean _hasSetRootExplicit = false;

/* (non-Javadoc)

@see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)

*/

public void setApplicationContext(ApplicationContext applicationContext)

throws BeansException {

this.applicationContext = applicationContext;

//when no custom root object,use ApplicationContext default

if(!_hasSetRootExplicit)

this.root = this.applicationContext;

}

/**

@param expression the ognl expression to set.

*/

public void setExpression(String expression) {

this.expression = expression;

}

/**

@param context the naming context for the evaluation

*/

public void setContext(Map context) {

this.context = context;

}

/**

@param root the root object for the OGNL expression

*/

public void setRoot(Object root) {

_hasSetRootExplicit = true;

this.root = root;

}

public Object getObject() throws Exception {

if(expression==null)

throw new IllegalArgumentException("ognl expression cannot be null!");

//the return object after ognl evaluation
Object returnObject = null;
try{
returnObject = OgnlExpressionEvaluator.evaluate(expression, context, root);
}catch(OgnlException ex){
//a better way is throw appropriate Exception insteadof RuntimeException
//I write RuntimeException for the sake of simplicity
throw new RuntimeException("error in evaluation ",ex);
}

if(returnObject==null)
throw new FatalBeanException("OgnlExpressionFactoryBean is not allowed to return null, " +
"but the expression '" + this.expression + "' return null");

return returnObject;

}

/**

unknown type

*/

public Class getObjectType() {

return null;

}

public boolean isSingleton() {

return true;

}

/**

@author snowway

@version $Id$

<p>

a helper class for evaluate ognl expression and cache the compiled expression object

*/

private static class OgnlExpressionEvaluator{

//a map for pre-compiled ognl expression object

private static Map expressions = new Hashtable();

/**

@param expression the OGNL expression

@param context the naming context for the evaluation

@param root the root object for the OGNL expression

*/

public static Object evaluate(String expression,

Map context,Object root) throws OgnlException{

//the context can not be null,otherwise OGNL will throw NullPointerException

if(context == null)

context = Collections.EMPTY_MAP;

//try to retrieve pre-compiled ognl expression object

Object compiledObject = expressions.get(expression);

//compile first if failed to retrieve pre-compiled object

if(compiledObject==null){

expressions.put(expression,compiledObject = Ognl.parseExpression(expression));

}

//evaluate

return Ognl.getValue(compiledObject,context,root);

}

}

}

the demo xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<!--

static method invocation

it will return java system properties

@ represent static method or field invocation

-->

<bean id="sysprops" class="org.snowway.spring.extension.OgnlExpressionFactoryBean">

<property name="expression">

<value>

@java.lang.System@getProperties()

</value>

</property>

</bean>

<!--
static filed reference
it will return java.io.PrintStream object
@ represent static method or field invocation
-->
<bean id="printStream" class="org.snowway.spring.extension.OgnlExpressionFactoryBean">
<property name="expression">
<value>@java.lang.System@out</value>
</property>
</bean>

<!--
method invocation return value
it will return "ABCDE"
-->
<bean id="uppercaseString" class="org.snowway.spring.extension.OgnlExpressionFactoryBean">
<property name="expression">
<value>"abcde".toUpperCase()</value>
</property>
</bean>

<!--
use existing bean as the root of OGNL expression
it will return java.version system property value (e.g. 1.4.2_05)
the root object is java.util.Properties,so you can invoke java.util.Properties.getProperty method
it can alse write as #this.getProperty("java.version"),#this represent the root now
-->
<bean id="javaVersion" class="org.snowway.spring.extension.OgnlExpressionFactoryBean">
<property name="expression">
<value>
getProperty("java.version")
</value>
</property>
<property name="root">
<ref local="sysprops"/>
</property>
</bean>

<!--
use naming context in OGNL evaluation
it will return such as "1.4.2_05 ABCDE"
when you need more object for evaluation,you can put object to naming context.
you can use #mapkey for object in naming contenxt
-->
<bean id="javaVersionAndUppercaseString"
class="org.snowway.spring.extension.OgnlExpressionFactoryBean">
<property name="expression">
<value>
#sysprops.getProperty("java.version") + " " +#uppercaseString
</value>
</property>
<property name="context">
<map>
<entry key="sysprops">
<ref local="sysprops"/>
</entry>
<entry key="uppercaseString">
<ref local="uppercaseString"/>
</entry>
</map>
</property>
</bean>

<!--
ApplicationContext bean reference
it will return user property(a list of Map.Entry item)
i use ApplicationContext object as OGNL root object for convenience.
getBean is the method of ApplicationContext
-->
<bean id="userprops" class="org.snowway.spring.extension.OgnlExpressionFactoryBean">
<property name="expression">
<value>
<!--
collection selection
the syntax is collection.{? expression_return_true_or_false }
in the {},#this is current item in collection,not the root object of OGNL
when expression_return_true_or_false evaluate to true,the current item is reserved
e.g. listeners.{? #this instanceof java.awt.event.ActionListener}
-->
getBean("sysprops").entrySet().{? #this.key.startsWith("user")}
</value>
</property>
</bean>

<!--
collection projection
it will return [2,3,4]
-->
<bean id="addOneForEachElement" class="org.snowway.spring.extension.OgnlExpressionFactoryBean">
<property name="expression">
<value>
<!--
collection projection
the syntax is collection.{ expression }
in the {},#this is current item in collection,not the root object for OGNL
collection projection expression will iterate all item,and each item will pass
into expression and return the expression value

use the #var=expression syntax to define a variable.
one more thing,OGNL use , to separate expressions, and the entire expression result
is the last one
-->
<![CDATA[
#list = new java.util.ArrayList(),
#list.add(1),#list.add(2),#list.add(3),
#list.{ #this + 1 }
]]>
</value>
</property>
</bean>

<!--
object navigation
it will return "my name is:snowway and my birthday is:Tue Sep 18 00:00:00 CST 1979 "
-->
<bean id="objectNavigation" class="org.snowway.spring.extension.OgnlExpressionFactoryBean">
<property name="expression">
<value>
<!--
use #{key1:value1,key2:value2} to define a map
use #@java.util.LinkedHashMap@{key1:value1,key2:value2}	to define specified map
map.key == map[key]
-->
<![CDATA[
#map = #@java.util.LinkedHashMap@{"name":"snowway",
"age":26,
"email":"snowway.xue@gmail.com",
"birthday":new java.util.GregorianCalendar(1979,8,18)},
"my name is:"+#map['name']+" and my birthday is:"+#map.birthday.time
]]>
</value>
</property>
</bean>
<!--
please read OGNL LanguageGuide(www.ognl.org) for other expression usage
-->

</beans>

Attachments:

ognl-2.6.5.jar (163.99 kB)

OgnlExpressionFactoryBean.rar (3.20 kB)

Issue Links:

#4739 Introducing Expression Language Support ("duplicates")