Parse JPA <exclude-unlisted-classes> correctly
Fix PersistenceUnitReader to correctly read <exclude-unlisted-classes>
in both JPA 1.0 and 2.0 persistence.xml files.
Prior to this commit PersistenceUnitReader would set the value of
excludeUnlistedClasses to true when a <exclude-unlisted-classes> element
was present, regardless of its value.
The following rules are now used when parsing:
- If the <exclude-unlisted-classes> element is missing the appropriate
default value is set (based on the JPA version).
- If an empty <exclude-unlisted-classes/> element is found the
excludeUnlistedClasses property is set to true.
- Otherwise the value of the <exclude-unlisted-classes> element is used
to set the excludeUnlistedClasses property.
Issue: SPR-10767
(cherry picked from 7ad540d)
Conflicts:
spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceUnitReader.java
This commit is contained in:
parent
199be0ad3c
commit
e608055021
|
|
@ -21,6 +21,7 @@ import java.io.InputStream;
|
|||
import java.net.URL;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.spi.PersistenceUnitTransactionType;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
|
@ -28,11 +29,6 @@ import javax.xml.parsers.ParserConfigurationException;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.jdbc.datasource.lookup.DataSourceLookup;
|
||||
|
|
@ -41,6 +37,10 @@ import org.springframework.util.ResourceUtils;
|
|||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.springframework.util.xml.SimpleSaxErrorHandler;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Internal helper class for reading JPA-compliant {@code persistence.xml} files.
|
||||
|
|
@ -81,6 +81,8 @@ class PersistenceUnitReader {
|
|||
|
||||
private static final String META_INF = "META-INF";
|
||||
|
||||
private static final String VERSION_1 = "1.0";
|
||||
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
|
|
@ -266,8 +268,14 @@ class PersistenceUnitReader {
|
|||
|
||||
// exclude unlisted classes
|
||||
Element excludeUnlistedClasses = DomUtils.getChildElementByTagName(persistenceUnit, EXCLUDE_UNLISTED_CLASSES);
|
||||
if (excludeUnlistedClasses != null) {
|
||||
unitInfo.setExcludeUnlistedClasses(true);
|
||||
if (excludeUnlistedClasses == null) {
|
||||
// element is not defined, use default appropriate for version
|
||||
unitInfo.setExcludeUnlistedClasses(!VERSION_1.equals(version));
|
||||
}
|
||||
else {
|
||||
String excludeText = DomUtils.getTextValue(excludeUnlistedClasses);
|
||||
unitInfo.setExcludeUnlistedClasses(StringUtils.isEmpty(excludeText) ||
|
||||
Boolean.valueOf(excludeText));
|
||||
}
|
||||
|
||||
// set JPA 2.0 shared cache mode
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
<persistence 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"
|
||||
version="1.0">
|
||||
|
||||
<persistence-unit name="NoExcludeElement" />
|
||||
|
||||
<persistence-unit name="EmptyExcludeElement">
|
||||
<exclude-unlisted-classes />
|
||||
</persistence-unit>
|
||||
|
||||
<persistence-unit name="TrueExcludeElement">
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
</persistence-unit>
|
||||
|
||||
<persistence-unit name="FalseExcludeElement">
|
||||
<exclude-unlisted-classes>false</exclude-unlisted-classes>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<persistence 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_2_0.xsd"
|
||||
version="2.0">
|
||||
|
||||
<persistence-unit name="NoExcludeElement" />
|
||||
|
||||
<persistence-unit name="EmptyExcludeElement">
|
||||
<exclude-unlisted-classes />
|
||||
</persistence-unit>
|
||||
|
||||
<persistence-unit name="TrueExcludeElement">
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
</persistence-unit>
|
||||
|
||||
<persistence-unit name="FalseExcludeElement">
|
||||
<exclude-unlisted-classes>false</exclude-unlisted-classes>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
|
|
@ -43,6 +43,7 @@ import static org.junit.Assert.*;
|
|||
*
|
||||
* @author Costin Leau
|
||||
* @author Juergen Hoeller
|
||||
* @author Nicholas Williams
|
||||
*/
|
||||
public class PersistenceXmlParsingTests {
|
||||
|
||||
|
|
@ -60,6 +61,8 @@ public class PersistenceXmlParsingTests {
|
|||
assertEquals(2, info[0].getJarFileUrls().size());
|
||||
assertEquals(new ClassPathResource("order.jar").getURL(), info[0].getJarFileUrls().get(0));
|
||||
assertEquals(new ClassPathResource("order-supplemental.jar").getURL(), info[0].getJarFileUrls().get(1));
|
||||
|
||||
assertFalse("Exclude unlisted should default false in 1.0.", info[0].excludeUnlistedClasses());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -72,6 +75,8 @@ public class PersistenceXmlParsingTests {
|
|||
assertNotNull(info);
|
||||
assertEquals(1, info.length);
|
||||
assertEquals("OrderManagement", info[0].getPersistenceUnitName());
|
||||
|
||||
assertFalse("Exclude unlisted should default false in 1.0.", info[0].excludeUnlistedClasses());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -89,6 +94,8 @@ public class PersistenceXmlParsingTests {
|
|||
assertEquals(1, info[0].getMappingFileNames().size());
|
||||
assertEquals("mappings.xml", info[0].getMappingFileNames().get(0));
|
||||
assertEquals(0, info[0].getProperties().keySet().size());
|
||||
|
||||
assertFalse("Exclude unlisted should default false in 1.0.", info[0].excludeUnlistedClasses());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -109,6 +116,8 @@ public class PersistenceXmlParsingTests {
|
|||
assertEquals(0, info[0].getProperties().keySet().size());
|
||||
assertNull(info[0].getJtaDataSource());
|
||||
assertNull(info[0].getNonJtaDataSource());
|
||||
|
||||
assertFalse("Exclude unlisted should default false in 1.0.", info[0].excludeUnlistedClasses());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -134,7 +143,7 @@ public class PersistenceXmlParsingTests {
|
|||
assertEquals("com.acme.Customer", info[0].getManagedClassNames().get(1));
|
||||
assertEquals("com.acme.Item", info[0].getManagedClassNames().get(2));
|
||||
|
||||
assertTrue(info[0].excludeUnlistedClasses());
|
||||
assertTrue("Exclude unlisted should be true when no value.", info[0].excludeUnlistedClasses());
|
||||
|
||||
assertSame(PersistenceUnitTransactionType.RESOURCE_LOCAL, info[0].getTransactionType());
|
||||
assertEquals(0, info[0].getProperties().keySet().size());
|
||||
|
|
@ -163,6 +172,8 @@ public class PersistenceXmlParsingTests {
|
|||
|
||||
assertEquals("com.acme.AcmePersistence", info[0].getPersistenceProviderClassName());
|
||||
assertEquals(0, info[0].getProperties().keySet().size());
|
||||
|
||||
assertFalse("Exclude unlisted should default false in 1.0.", info[0].excludeUnlistedClasses());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -206,6 +217,8 @@ public class PersistenceXmlParsingTests {
|
|||
|
||||
assertSame(ds, pu1.getJtaDataSource());
|
||||
|
||||
assertFalse("Exclude unlisted should default false in 1.0.", pu1.excludeUnlistedClasses());
|
||||
|
||||
PersistenceUnitInfo pu2 = info[1];
|
||||
|
||||
assertSame(PersistenceUnitTransactionType.JTA, pu2.getTransactionType());
|
||||
|
|
@ -222,6 +235,8 @@ public class PersistenceXmlParsingTests {
|
|||
|
||||
assertNull(pu2.getJtaDataSource());
|
||||
assertEquals(ds, pu2.getNonJtaDataSource());
|
||||
|
||||
assertTrue("Exclude unlisted should be true when no value.", pu2.excludeUnlistedClasses());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -233,6 +248,8 @@ public class PersistenceXmlParsingTests {
|
|||
assertEquals(1, info.length);
|
||||
assertEquals("pu", info[0].getPersistenceUnitName());
|
||||
assertEquals(0, info[0].getProperties().keySet().size());
|
||||
|
||||
assertFalse("Exclude unlisted should default false in 1.0.", info[0].excludeUnlistedClasses());
|
||||
}
|
||||
|
||||
@Ignore // not doing schema parsing anymore for JPA 2.0 compatibility
|
||||
|
|
@ -290,4 +307,66 @@ public class PersistenceXmlParsingTests {
|
|||
assertTrue("the archive location should have been returned", archive.getURL().sameFile(url));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJpa1ExcludeUnlisted() throws Exception {
|
||||
PersistenceUnitReader reader = new PersistenceUnitReader(
|
||||
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
|
||||
String resource = "/org/springframework/orm/jpa/persistence-exclude-1.0.xml";
|
||||
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
|
||||
|
||||
assertNotNull(info);
|
||||
assertEquals("The number of persistence units is incorrect.", 4, info.length);
|
||||
|
||||
PersistenceUnitInfo noExclude = info[0];
|
||||
assertNotNull("noExclude should not be null.", noExclude);
|
||||
assertEquals("noExclude name is not correct.", "NoExcludeElement", noExclude.getPersistenceUnitName());
|
||||
assertFalse("Exclude unlisted should default false in 1.0.", noExclude.excludeUnlistedClasses());
|
||||
|
||||
PersistenceUnitInfo emptyExclude = info[1];
|
||||
assertNotNull("emptyExclude should not be null.", emptyExclude);
|
||||
assertEquals("emptyExclude name is not correct.", "EmptyExcludeElement", emptyExclude.getPersistenceUnitName());
|
||||
assertTrue("emptyExclude should be true.", emptyExclude.excludeUnlistedClasses());
|
||||
|
||||
PersistenceUnitInfo trueExclude = info[2];
|
||||
assertNotNull("trueExclude should not be null.", trueExclude);
|
||||
assertEquals("trueExclude name is not correct.", "TrueExcludeElement", trueExclude.getPersistenceUnitName());
|
||||
assertTrue("trueExclude should be true.", trueExclude.excludeUnlistedClasses());
|
||||
|
||||
PersistenceUnitInfo falseExclude = info[3];
|
||||
assertNotNull("falseExclude should not be null.", falseExclude);
|
||||
assertEquals("falseExclude name is not correct.", "FalseExcludeElement", falseExclude.getPersistenceUnitName());
|
||||
assertFalse("falseExclude should be false.", falseExclude.excludeUnlistedClasses());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJpa2ExcludeUnlisted() throws Exception {
|
||||
PersistenceUnitReader reader = new PersistenceUnitReader(
|
||||
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
|
||||
String resource = "/org/springframework/orm/jpa/persistence-exclude-2.0.xml";
|
||||
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
|
||||
|
||||
assertNotNull(info);
|
||||
assertEquals("The number of persistence units is incorrect.", 4, info.length);
|
||||
|
||||
PersistenceUnitInfo noExclude = info[0];
|
||||
assertNotNull("noExclude should not be null.", noExclude);
|
||||
assertEquals("noExclude name is not correct.", "NoExcludeElement", noExclude.getPersistenceUnitName());
|
||||
assertTrue("Exclude unlisted should default true in 2.0.", noExclude.excludeUnlistedClasses());
|
||||
|
||||
PersistenceUnitInfo emptyExclude = info[1];
|
||||
assertNotNull("emptyExclude should not be null.", emptyExclude);
|
||||
assertEquals("emptyExclude name is not correct.", "EmptyExcludeElement", emptyExclude.getPersistenceUnitName());
|
||||
assertTrue("emptyExclude should be true.", emptyExclude.excludeUnlistedClasses());
|
||||
|
||||
PersistenceUnitInfo trueExclude = info[2];
|
||||
assertNotNull("trueExclude should not be null.", trueExclude);
|
||||
assertEquals("trueExclude name is not correct.", "TrueExcludeElement", trueExclude.getPersistenceUnitName());
|
||||
assertTrue("trueExclude should be true.", trueExclude.excludeUnlistedClasses());
|
||||
|
||||
PersistenceUnitInfo falseExclude = info[3];
|
||||
assertNotNull("falseExclude should not be null.", falseExclude);
|
||||
assertEquals("falseExclude name is not correct.", "FalseExcludeElement", falseExclude.getPersistenceUnitName());
|
||||
assertFalse("falseExclude should be false.", falseExclude.excludeUnlistedClasses());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue