HHH-10131 - CacheableFileXmlSource.doBind returns null instead of created binding when .hbm.xml.bin have not been created yet

(cherry picked from commit ed892971af)
This commit is contained in:
Steve Ebersole 2015-09-25 12:26:46 -05:00
parent cf47c8d88f
commit 1c9976d114
4 changed files with 216 additions and 15 deletions

View File

@ -14,6 +14,7 @@ import java.io.Serializable;
import org.hibernate.boot.MappingException;
import org.hibernate.boot.jaxb.Origin;
import org.hibernate.boot.jaxb.SourceType;
import org.hibernate.boot.jaxb.spi.Binder;
import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.boot.jaxb.spi.XmlSource;
@ -39,20 +40,23 @@ public class CacheableFileXmlSource extends XmlSource {
this.serFile = determineCachedFile( xmlFile );
final boolean useCachedFile = xmlFile.exists()
&& serFile.exists()
&& xmlFile.lastModified() < serFile.lastModified();
if ( strict && !useCachedFile ) {
throw new MappingException(
String.format( "Cached file [%s] could not be found or could not be used", origin.getName() ),
origin
);
if ( strict ) {
if ( !serFile.exists() ) {
throw new MappingException(
String.format( "Cached file [%s] could not be found", origin.getName() ),
origin
);
}
if ( xmlFile.exists() && xmlFile.lastModified() > serFile.lastModified() ) {
throw new MappingException(
String.format( "Cached file [%s] could not be used as the mapping file is newer", origin.getName() ),
origin
);
}
}
}
private static File determineCachedFile(File xmlFile) {
public static File determineCachedFile(File xmlFile) {
return new File( xmlFile.getAbsolutePath() + ".bin" );
}
@ -90,12 +94,12 @@ public class CacheableFileXmlSource extends XmlSource {
}
log.readingMappingsFromFile( xmlFile.getPath() );
final Object binding = FileXmlSource.doBind( binder, xmlFile, getOrigin() );
final Binding binding = FileXmlSource.doBind( binder, xmlFile, getOrigin() );
writeSerFile( binding );
}
return null;
return binding;
}
}
private <T> T readSerFile() throws SerializationException, FileNotFoundException {
@ -104,14 +108,30 @@ public class CacheableFileXmlSource extends XmlSource {
}
private void writeSerFile(Object binding) {
writeSerFile( (Serializable) binding, xmlFile, serFile );
}
private static void writeSerFile(Serializable binding, File xmlFile, File serFile) {
try {
log.debugf( "Writing cache file for: %s to: %s", xmlFile.getAbsolutePath(), serFile.getAbsolutePath() );
SerializationHelper.serialize( (Serializable) binding, new FileOutputStream( serFile ) );
SerializationHelper.serialize( binding, new FileOutputStream( serFile ) );
boolean success = serFile.setLastModified( System.currentTimeMillis() );
if ( !success ) {
log.warn( "Could not update cacheable hbm.xml bin file timestamp" );
}
}
catch ( Exception e ) {
log.unableToWriteCachedFile( serFile.getAbsolutePath(), e.getMessage() );
}
}
public static void createSerFile(File xmlFile, Binder binder) {
final Origin origin = new Origin( SourceType.FILE, xmlFile.getAbsolutePath() );
writeSerFile(
FileXmlSource.doBind( binder, xmlFile, origin ),
xmlFile,
determineCachedFile( xmlFile )
);
}
}

View File

@ -0,0 +1,135 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.boot.binding.cacheable;
import java.io.File;
import java.io.FileNotFoundException;
import java.net.URL;
import org.hibernate.boot.MappingException;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.jaxb.internal.CacheableFileXmlSource;
import org.hibernate.boot.jaxb.internal.MappingBinder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.spi.XmlMappingBinderAccess;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.jboss.logging.Logger;
import static org.junit.Assert.fail;
/**
* Originally developed to help diagnose HHH-10131 - the original tests
* check 4 conditions:<ol>
* <li>strict usage where the cached file does exist</li>
* <li>strict usage where the cached file does not exist</li>
* <li>non-strict usage where the cached file does exist</li>
* <li>non-strict usage where the cached file does not exist</li>
* </ol>
*
* @author Steve Ebersole
*/
public class CacheableHbmXmlTest {
private static final Logger log = Logger.getLogger( CacheableHbmXmlTest.class );
private static final String HBM_RESOURCE_NAME = "org/hibernate/test/boot/binding/cacheable/SimpleEntity.hbm.xml";
private StandardServiceRegistry ssr;
private MappingBinder binder;
private File hbmXmlFile;
private File hbmXmlBinFile;
@Before
public void before() throws Exception {
ssr = new StandardServiceRegistryBuilder()
.build();
binder = new XmlMappingBinderAccess( ssr ).getMappingBinder();
final URL hbmXmlUrl = getClass().getClassLoader().getResource( HBM_RESOURCE_NAME );
if ( hbmXmlUrl == null ) {
throw couldNotFindHbmXmlFile();
}
hbmXmlFile = new File( hbmXmlUrl.getFile() );
if ( ! hbmXmlFile.exists() ) {
throw couldNotFindHbmXmlFile();
}
hbmXmlBinFile = CacheableFileXmlSource.determineCachedFile( hbmXmlFile );
}
private Exception couldNotFindHbmXmlFile() {
throw new IllegalStateException( "Could not locate hbm.xml file by resource lookup" );
}
@After
public void after() {
if ( ssr != null ) {
StandardServiceRegistryBuilder.destroy( ssr );
}
}
@Test
public void testStrictCaseWhereFileDoesPreviouslyExist() throws FileNotFoundException {
deleteBinFile();
createBinFile();
try {
new MetadataSources( ssr ).addCacheableFileStrictly( hbmXmlFile ).buildMetadata();
}
catch (MappingException e) {
fail( "addCacheableFileStrictly led to MappingException when bin file existed" );
}
}
@Test
public void testStrictCaseWhereFileDoesNotPreviouslyExist() throws FileNotFoundException {
deleteBinFile();
try {
new MetadataSources( ssr ).addCacheableFileStrictly( hbmXmlFile ).buildMetadata();
fail( "addCacheableFileStrictly should be led to MappingException when bin file does not exist" );
}
catch (MappingException ignore) {
// this is the expected result
}
}
@Test
public void testNonStrictCaseWhereFileDoesPreviouslyExist() {
deleteBinFile();
createBinFile();
new MetadataSources( ssr ).addCacheableFile( hbmXmlFile ).buildMetadata();
}
@Test
public void testNonStrictCaseWhereFileDoesNotPreviouslyExist() {
deleteBinFile();
new MetadataSources( ssr ).addCacheableFile( hbmXmlFile ).buildMetadata();
}
private void deleteBinFile() {
// if it exists
if ( hbmXmlBinFile.exists() ) {
final boolean success = hbmXmlBinFile.delete();
if ( !success ) {
log.warn( "Unable to delete existing cached hbm.xml.bin file", new Exception() );
}
}
}
private void createBinFile() {
if ( hbmXmlBinFile.exists() ) {
log.warn( "Cached hbm.xml.bin file already existed on request to create", new Exception() );
}
else {
CacheableFileXmlSource.createSerFile( hbmXmlFile, binder );
}
}
}

View File

@ -0,0 +1,31 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.boot.binding.cacheable;
/**
* @author Steve Ebersole
*/
public class SimpleEntity {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
-->
<hibernate-mapping xmlns="http://www.hibernate.org/xsd/hibernate-mapping" package="org.hibernate.test.boot.binding.cacheable">
<class name="SimpleEntity">
<id name="id" column="id" type="java.lang.Long">
<generator class="increment"/>
</id>
<property name="name" type="string"/>
</class>
</hibernate-mapping>