Skip to content

Commit 7ad540d

Browse files
beamerblvdphilwebb
authored andcommitted
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
1 parent 66cfe9f commit 7ad540d

File tree

4 files changed

+131
-4
lines changed

4 files changed

+131
-4
lines changed

spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceUnitReader.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.net.URL;
2222
import java.util.LinkedList;
2323
import java.util.List;
24+
2425
import javax.persistence.SharedCacheMode;
2526
import javax.persistence.ValidationMode;
2627
import javax.persistence.spi.PersistenceUnitTransactionType;
@@ -34,7 +35,6 @@
3435
import org.w3c.dom.Element;
3536
import org.xml.sax.ErrorHandler;
3637
import org.xml.sax.SAXException;
37-
3838
import org.springframework.core.io.Resource;
3939
import org.springframework.core.io.support.ResourcePatternResolver;
4040
import org.springframework.jdbc.datasource.lookup.DataSourceLookup;
@@ -83,6 +83,8 @@ class PersistenceUnitReader {
8383

8484
private static final String META_INF = "META-INF";
8585

86+
private static final String VERSION_1 = "1.0";
87+
8688

8789
private final Log logger = LogFactory.getLog(getClass());
8890

@@ -268,8 +270,14 @@ protected SpringPersistenceUnitInfo parsePersistenceUnitInfo(Element persistence
268270

269271
// exclude unlisted classes
270272
Element excludeUnlistedClasses = DomUtils.getChildElementByTagName(persistenceUnit, EXCLUDE_UNLISTED_CLASSES);
271-
if (excludeUnlistedClasses != null) {
272-
unitInfo.setExcludeUnlistedClasses(true);
273+
if (excludeUnlistedClasses == null) {
274+
// element is not defined, use default appropriate for version
275+
unitInfo.setExcludeUnlistedClasses(!VERSION_1.equals(version));
276+
}
277+
else {
278+
String excludeText = DomUtils.getTextValue(excludeUnlistedClasses);
279+
unitInfo.setExcludeUnlistedClasses(StringUtils.isEmpty(excludeText) ||
280+
Boolean.valueOf(excludeText));
273281
}
274282

275283
// set JPA 2.0 shared cache mode
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
4+
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
5+
version="1.0">
6+
7+
<persistence-unit name="NoExcludeElement" />
8+
9+
<persistence-unit name="EmptyExcludeElement">
10+
<exclude-unlisted-classes />
11+
</persistence-unit>
12+
13+
<persistence-unit name="TrueExcludeElement">
14+
<exclude-unlisted-classes>true</exclude-unlisted-classes>
15+
</persistence-unit>
16+
17+
<persistence-unit name="FalseExcludeElement">
18+
<exclude-unlisted-classes>false</exclude-unlisted-classes>
19+
</persistence-unit>
20+
</persistence>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
4+
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
5+
version="2.0">
6+
7+
<persistence-unit name="NoExcludeElement" />
8+
9+
<persistence-unit name="EmptyExcludeElement">
10+
<exclude-unlisted-classes />
11+
</persistence-unit>
12+
13+
<persistence-unit name="TrueExcludeElement">
14+
<exclude-unlisted-classes>true</exclude-unlisted-classes>
15+
</persistence-unit>
16+
17+
<persistence-unit name="FalseExcludeElement">
18+
<exclude-unlisted-classes>false</exclude-unlisted-classes>
19+
</persistence-unit>
20+
</persistence>

spring-orm/src/test/java/org/springframework/orm/jpa/persistenceunit/PersistenceXmlParsingTests.java

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
*
4444
* @author Costin Leau
4545
* @author Juergen Hoeller
46+
* @author Nicholas Williams
4647
*/
4748
public class PersistenceXmlParsingTests {
4849

@@ -60,6 +61,8 @@ public void testMetaInfCase() throws Exception {
6061
assertEquals(2, info[0].getJarFileUrls().size());
6162
assertEquals(new ClassPathResource("order.jar").getURL(), info[0].getJarFileUrls().get(0));
6263
assertEquals(new ClassPathResource("order-supplemental.jar").getURL(), info[0].getJarFileUrls().get(1));
64+
65+
assertFalse("Exclude unlisted should default false in 1.0.", info[0].excludeUnlistedClasses());
6366
}
6467

6568
@Test
@@ -72,6 +75,8 @@ public void testExample1() throws Exception {
7275
assertNotNull(info);
7376
assertEquals(1, info.length);
7477
assertEquals("OrderManagement", info[0].getPersistenceUnitName());
78+
79+
assertFalse("Exclude unlisted should default false in 1.0.", info[0].excludeUnlistedClasses());
7580
}
7681

7782
@Test
@@ -89,6 +94,8 @@ public void testExample2() throws Exception {
8994
assertEquals(1, info[0].getMappingFileNames().size());
9095
assertEquals("mappings.xml", info[0].getMappingFileNames().get(0));
9196
assertEquals(0, info[0].getProperties().keySet().size());
97+
98+
assertFalse("Exclude unlisted should default false in 1.0.", info[0].excludeUnlistedClasses());
9299
}
93100

94101
@Test
@@ -109,6 +116,8 @@ public void testExample3() throws Exception {
109116
assertEquals(0, info[0].getProperties().keySet().size());
110117
assertNull(info[0].getJtaDataSource());
111118
assertNull(info[0].getNonJtaDataSource());
119+
120+
assertFalse("Exclude unlisted should default false in 1.0.", info[0].excludeUnlistedClasses());
112121
}
113122

114123
@Test
@@ -134,7 +143,7 @@ public void testExample4() throws Exception {
134143
assertEquals("com.acme.Customer", info[0].getManagedClassNames().get(1));
135144
assertEquals("com.acme.Item", info[0].getManagedClassNames().get(2));
136145

137-
assertTrue(info[0].excludeUnlistedClasses());
146+
assertTrue("Exclude unlisted should be true when no value.", info[0].excludeUnlistedClasses());
138147

139148
assertSame(PersistenceUnitTransactionType.RESOURCE_LOCAL, info[0].getTransactionType());
140149
assertEquals(0, info[0].getProperties().keySet().size());
@@ -163,6 +172,8 @@ public void testExample5() throws Exception {
163172

164173
assertEquals("com.acme.AcmePersistence", info[0].getPersistenceProviderClassName());
165174
assertEquals(0, info[0].getProperties().keySet().size());
175+
176+
assertFalse("Exclude unlisted should default false in 1.0.", info[0].excludeUnlistedClasses());
166177
}
167178

168179
@Test
@@ -206,6 +217,8 @@ public void testExampleComplex() throws Exception {
206217

207218
assertSame(ds, pu1.getJtaDataSource());
208219

220+
assertFalse("Exclude unlisted should default false in 1.0.", pu1.excludeUnlistedClasses());
221+
209222
PersistenceUnitInfo pu2 = info[1];
210223

211224
assertSame(PersistenceUnitTransactionType.JTA, pu2.getTransactionType());
@@ -222,6 +235,8 @@ public void testExampleComplex() throws Exception {
222235

223236
assertNull(pu2.getJtaDataSource());
224237
assertEquals(ds, pu2.getNonJtaDataSource());
238+
239+
assertTrue("Exclude unlisted should be true when no value.", pu2.excludeUnlistedClasses());
225240
}
226241

227242
@Test
@@ -233,6 +248,8 @@ public void testExample6() throws Exception {
233248
assertEquals(1, info.length);
234249
assertEquals("pu", info[0].getPersistenceUnitName());
235250
assertEquals(0, info[0].getProperties().keySet().size());
251+
252+
assertFalse("Exclude unlisted should default false in 1.0.", info[0].excludeUnlistedClasses());
236253
}
237254

238255
@Ignore // not doing schema parsing anymore for JPA 2.0 compatibility
@@ -290,4 +307,66 @@ public void testPersistenceUnitRootUrlWithJar() throws Exception {
290307
assertTrue("the archive location should have been returned", archive.getURL().sameFile(url));
291308
}
292309

310+
@Test
311+
public void testJpa1ExcludeUnlisted() throws Exception {
312+
PersistenceUnitReader reader = new PersistenceUnitReader(
313+
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
314+
String resource = "/org/springframework/orm/jpa/persistence-exclude-1.0.xml";
315+
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
316+
317+
assertNotNull(info);
318+
assertEquals("The number of persistence units is incorrect.", 4, info.length);
319+
320+
PersistenceUnitInfo noExclude = info[0];
321+
assertNotNull("noExclude should not be null.", noExclude);
322+
assertEquals("noExclude name is not correct.", "NoExcludeElement", noExclude.getPersistenceUnitName());
323+
assertFalse("Exclude unlisted should default false in 1.0.", noExclude.excludeUnlistedClasses());
324+
325+
PersistenceUnitInfo emptyExclude = info[1];
326+
assertNotNull("emptyExclude should not be null.", emptyExclude);
327+
assertEquals("emptyExclude name is not correct.", "EmptyExcludeElement", emptyExclude.getPersistenceUnitName());
328+
assertTrue("emptyExclude should be true.", emptyExclude.excludeUnlistedClasses());
329+
330+
PersistenceUnitInfo trueExclude = info[2];
331+
assertNotNull("trueExclude should not be null.", trueExclude);
332+
assertEquals("trueExclude name is not correct.", "TrueExcludeElement", trueExclude.getPersistenceUnitName());
333+
assertTrue("trueExclude should be true.", trueExclude.excludeUnlistedClasses());
334+
335+
PersistenceUnitInfo falseExclude = info[3];
336+
assertNotNull("falseExclude should not be null.", falseExclude);
337+
assertEquals("falseExclude name is not correct.", "FalseExcludeElement", falseExclude.getPersistenceUnitName());
338+
assertFalse("falseExclude should be false.", falseExclude.excludeUnlistedClasses());
339+
}
340+
341+
@Test
342+
public void testJpa2ExcludeUnlisted() throws Exception {
343+
PersistenceUnitReader reader = new PersistenceUnitReader(
344+
new PathMatchingResourcePatternResolver(), new JndiDataSourceLookup());
345+
String resource = "/org/springframework/orm/jpa/persistence-exclude-2.0.xml";
346+
PersistenceUnitInfo[] info = reader.readPersistenceUnitInfos(resource);
347+
348+
assertNotNull(info);
349+
assertEquals("The number of persistence units is incorrect.", 4, info.length);
350+
351+
PersistenceUnitInfo noExclude = info[0];
352+
assertNotNull("noExclude should not be null.", noExclude);
353+
assertEquals("noExclude name is not correct.", "NoExcludeElement", noExclude.getPersistenceUnitName());
354+
assertTrue("Exclude unlisted should default true in 2.0.", noExclude.excludeUnlistedClasses());
355+
356+
PersistenceUnitInfo emptyExclude = info[1];
357+
assertNotNull("emptyExclude should not be null.", emptyExclude);
358+
assertEquals("emptyExclude name is not correct.", "EmptyExcludeElement", emptyExclude.getPersistenceUnitName());
359+
assertTrue("emptyExclude should be true.", emptyExclude.excludeUnlistedClasses());
360+
361+
PersistenceUnitInfo trueExclude = info[2];
362+
assertNotNull("trueExclude should not be null.", trueExclude);
363+
assertEquals("trueExclude name is not correct.", "TrueExcludeElement", trueExclude.getPersistenceUnitName());
364+
assertTrue("trueExclude should be true.", trueExclude.excludeUnlistedClasses());
365+
366+
PersistenceUnitInfo falseExclude = info[3];
367+
assertNotNull("falseExclude should not be null.", falseExclude);
368+
assertEquals("falseExclude name is not correct.", "FalseExcludeElement", falseExclude.getPersistenceUnitName());
369+
assertFalse("falseExclude should be false.", falseExclude.excludeUnlistedClasses());
370+
}
371+
293372
}

0 commit comments

Comments
 (0)