Migrate AbstractLobType to Hibernate 4 and Spring 3.2 - spring

I am currently using Hibernate 3 and Spring 3.0. I want to migrate to Hibernate 4 and Spring 3.2. I am using a subclass of AbstractLobType to implement a UserType that maps from an InputStream to the database (MySQL LONGBLOB):
import java.io.InputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.HibernateException;
import org.springframework.jdbc.support.lob.LobCreator;
import org.springframework.jdbc.support.lob.LobHandler;
import org.springframework.orm.hibernate3.support.AbstractLobType;
public class BlobUserType extends AbstractLobType {
public int[] sqlTypes() {
return new int[] { Types.BLOB };
}
public Class returnedClass() {
return InputStream.class;
}
#Override
protected Object nullSafeGetInternal(ResultSet rs, String[] names, Object owner, LobHandler lobHandler)
throws SQLException, HibernateException {
return lobHandler.getBlobAsBinaryStream(rs, names[0]);
}
#Override
protected void nullSafeSetInternal(PreparedStatement ps, int index, Object value, LobCreator lobCreator)
throws SQLException, HibernateException {
if (value != null) {
lobCreator.setBlobAsBinaryStream(ps, index, (InputStream) value, -1);
} else {
lobCreator.setBlobAsBytes(ps, index, null);
}
}
}
Since AbstractLobType is in the hibernate3, I should not use it anymore, but what is the alternative?
I did read this JIRA issue on the spring project, but it does not help me at all.
This is the hibernate mapping:
<class name="SoundNotification" table="SoundNotification" entity-name="SoundNotificationWithData">
<id name="m_id" type="int" column="id" unsaved-value="-1">
<generator class="native"/>
</id>
<property name="m_name" column="name" unique="true" not-null="true"/>
<property name="m_data" column="data"
type="com.mycompany.server.common.service.persistence.impl.hibernate.usertype.BlobUserType"
not-null="true"/>
<property name="m_size" formula="OCTET_LENGTH(data)"/>
<property name="m_inUse"
formula="(select count(1) from EventTypeConfiguration etc where etc.soundNotification=id)"/>
</class>
And the Java class:
public class SoundNotification extends IntegerEntity
{
private String m_name;
private transient InputStream m_data;
private boolean m_inUse;
private long m_size;
// getters and setters ...
}
UPDATE with MaterializedBlobType:
My TrafficMap.hbm.xml:
<class name="TrafficMapImage" table="TrafficMapImage" entity-name="TrafficMapImageWithData">
<id name="m_id" column="id" type="int" unsaved-value="-1">
<generator class="native"/>
</id>
<property name="m_created" column="created" type="org.jadira.usertype.dateandtime.joda.PersistentDateTime"
not-null="true"/>
<property name="m_image" column="image"
type="org.hibernate.type.MaterializedBlobType"
not-null="true"/>
<property name="m_type" column="type" not-null="true">
<type name="com.traficon.tmsng.server.common.service.persistence.impl.hibernate.usertype.EnumUserType">
<param name="enumClass">com.traficon.domain.map.TrafficMapImageType</param>
</type>
</property>
</class>
The sessionFactory bean in my Spring context:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<value>
hibernate.dialect=${hibernate.dialect}
hibernate.hbm2ddl.auto=${hibernate.hbm2ddl.auto}
hibernate.show_sql=${hibernate.show_sql}
hibernate.jdbc.batch_size=50
hibernate.jdbc.use_streams_for_binary=true
hibernate.current_session_context_class=com.traficon.tmsng.server.common.spring.TransactionAwareSessionContext
</value>
</property>
<property name="mappingResources">
<list>
<value>hibernate/authentication.hbm.xml</value>
<value>hibernate/SystemPrefs.hbm.xml</value>
<value>hibernate/Detector.hbm.xml</value>
<value>hibernate/filters.hbm.xml</value>
<value>hibernate/EventTypeConfiguration.hbm.xml</value>
<value>hibernate/Scenario.hbm.xml</value>
<value>hibernate/RunningScenario.hbm.xml</value>
<value>hibernate/StorePoint.hbm.xml</value>
<value>hibernate/OfflineNetwork.hbm.xml</value>
<value>hibernate/Characteristics.hbm.xml</value>
<value>hibernate/EventType.hbm.xml</value>
<value>hibernate/EventStore.hbm.xml</value>
<value>hibernate/IntervalDataMessage.hbm.xml</value>
<value>hibernate/IntegrationPeriodConstraints.hbm.xml</value>
<value>hibernate/Media.hbm.xml</value>
<value>hibernate/TrafficMap.hbm.xml</value>
<value>hibernate/CommentLibrary.hbm.xml</value>
<value>hibernate/CommentHistory.hbm.xml</value>
<value>hibernate/Dashboard.hbm.xml</value>
</list>
</property>
<property name="entityInterceptor">
<bean class="com.traficon.tmsng.server.common.service.persistence.impl.hibernate.RollbackReintializerInterceptor"
scope="prototype"/>
</property>
</bean>
The logging output:
[WARNING] [talledLocalContainer] INFO: Initializing Spring root WebApplicationContext
[INFO] [talledLocalContainer] 13 Dec 2013 13:54:10,525 [main] INFO hibernate.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {4.0.2.Final}
[INFO] [talledLocalContainer] 13 Dec 2013 13:54:10,537 [main] INFO org.hibernate.Version - HHH000412: Hibernate Core {4.2.7.Final}
[INFO] [talledLocalContainer] 13 Dec 2013 13:54:10,544 [main] INFO org.hibernate.cfg.Environment - HHH000205: Loaded properties from resource hibernate.properties: {hibernate.jdbc.use_streams_for_binary=true, hibernate.bytecode.use_reflection_optimizer=false}
[INFO] [talledLocalContainer] 13 Dec 2013 13:54:10,545 [main] INFO org.hibernate.cfg.Environment - HHH000407: Using java.io streams to persist binary types
[INFO] [talledLocalContainer] 13 Dec 2013 13:54:10,546 [main] INFO org.hibernate.cfg.Environment - HHH000021: Bytecode provider name : javassist
[INFO] [talledLocalContainer] 13 Dec 2013 13:54:12,302 [main] INFO org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.MySQL5InnoDBDialect
....
[INFO] [talledLocalContainer] 13 Dec 2013 14:06:12,136 [http-8080-4] INFO hibernate.event.internal.DefaultLoadEventListener - HHH000327: Error performing load command : org.hibernate.PropertyAccessException: could not set a field value by reflection setter of com.traficon.domain.map.TrafficMapImage.m_image
[WARNING] [talledLocalContainer] Dec 13, 2013 2:06:12 PM org.apache.catalina.core.StandardWrapperValve invoke
[WARNING] [talledLocalContainer] SEVERE: Servlet.service() for servlet mediaServlet threw exception
[WARNING] [talledLocalContainer] java.lang.IllegalArgumentException: Can not set java.io.InputStream field com.traficon.domain.map.TrafficMapImage.m_image to [B
[WARNING] [talledLocalContainer] at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
[WARNING] [talledLocalContainer] at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
[WARNING] [talledLocalContainer] at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
[WARNING] [talledLocalContainer] at java.lang.reflect.Field.set(Field.java:741)
[WARNING] [talledLocalContainer] at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:139)
[WARNING] [talledLocalContainer] at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:710)
[WARNING] [talledLocalContainer] at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:379)
[WARNING] [talledLocalContainer] at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:4523)
[WARNING] [talledLocalContainer] at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:186)
[WARNING] [talledLocalContainer] at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:137)
[WARNING] [talledLocalContainer] at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1108)
[WARNING] [talledLocalContainer] at org.hibernate.loader.Loader.processResultSet(Loader.java:964)
[WARNING] [talledLocalContainer] at org.hibernate.loader.Loader.doQuery(Loader.java:911)
[WARNING] [talledLocalContainer] at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:342)
[WARNING] [talledLocalContainer] at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:312)
[WARNING] [talledLocalContainer] at org.hibernate.loader.Loader.loadEntity(Loader.java:2121)
[WARNING] [talledLocalContainer] at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:82)
[WARNING] [talledLocalContainer] at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:72)
[WARNING] [talledLocalContainer] at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3941)
[WARNING] [talledLocalContainer] at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:460)
[WARNING] [talledLocalContainer] at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:429)
[WARNING] [talledLocalContainer] at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:206)
[WARNING] [talledLocalContainer] at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:246)
[WARNING] [talledLocalContainer] at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:150)
[WARNING] [talledLocalContainer] at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1098)
[WARNING] [talledLocalContainer] at org.hibernate.internal.SessionImpl.access$2000(SessionImpl.java:175)
[WARNING] [talledLocalContainer] at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2482)
[WARNING] [talledLocalContainer] at org.hibernate.internal.SessionImpl.get(SessionImpl.java:998)
[WARNING] [talledLocalContainer] at com.traficon.tmsng.server.common.service.persistence.impl.hibernate.HibernateTrafficMapRepository.getTrafficMapImageWithData_aroundBody6(HibernateTrafficMapRepository.java:176)
[WARNING] [talledLocalContainer] at com.traficon.tmsng.server.common.service.persistence.impl.hibernate.HibernateTrafficMapRepository$AjcClosure7.run(HibernateTrafficMapRepository.java:1)
[WARNING] [talledLocalContainer] at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(AbstractTransactionAspect.aj:59)
[WARNING] [talledLocalContainer] at org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation(AbstractTransactionAspect.aj:65)
[WARNING] [talledLocalContainer] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
[WARNING] [talledLocalContainer] at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:63)
[WARNING] [talledLocalContainer] at com.traficon.tmsng.server.common.service.persistence.impl.hibernate.HibernateTrafficMapRepository.getTrafficMapImageWithData(HibernateTrafficMapRepository.java:173)
[WARNING] [talledLocalContainer] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[WARNING] [talledLocalContainer] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
[WARNING] [talledLocalContainer] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[WARNING] [talledLocalContainer] at java.lang.reflect.Method.invoke(Method.java:606)
[WARNING] [talledLocalContainer] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
[WARNING] [talledLocalContainer] at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
[WARNING] [talledLocalContainer] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
[WARNING] [talledLocalContainer] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
[WARNING] [talledLocalContainer] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
[WARNING] [talledLocalContainer] at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
[WARNING] [talledLocalContainer] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
[WARNING] [talledLocalContainer] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
[WARNING] [talledLocalContainer] at com.sun.proxy.$Proxy39.getTrafficMapImageWithData(Unknown Source)
[WARNING] [talledLocalContainer] at com.traficon.tmsng.server.web.mvc.DownloadTrafficMapImageController.onSubmit(DownloadTrafficMapImageController.java:40)
[WARNING] [talledLocalContainer] at org.springframework.web.servlet.mvc.SimpleFormController.processFormSubmission(SimpleFormController.java:272)
[WARNING] [talledLocalContainer] at org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:268)
[WARNING] [talledLocalContainer] at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
[WARNING] [talledLocalContainer] at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
[WARNING] [talledLocalContainer] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
[WARNING] [talledLocalContainer] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
[WARNING] [talledLocalContainer] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
[WARNING] [talledLocalContainer] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
[WARNING] [talledLocalContainer] at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
[WARNING] [talledLocalContainer] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
[WARNING] [talledLocalContainer] at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
[WARNING] [talledLocalContainer] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
[WARNING] [talledLocalContainer] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
[WARNING] [talledLocalContainer] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
[WARNING] [talledLocalContainer] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
[WARNING] [talledLocalContainer] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
[WARNING] [talledLocalContainer] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
[WARNING] [talledLocalContainer] at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:568)
[WARNING] [talledLocalContainer] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
[WARNING] [talledLocalContainer] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
[WARNING] [talledLocalContainer] at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
[WARNING] [talledLocalContainer] at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
[WARNING] [talledLocalContainer] at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
[WARNING] [talledLocalContainer] at java.lang.Thread.run(Thread.java:744)
[WARNING] [talledLocalContainer]

In theory you should use the hibernate provided MaterializedBlobType if you want to use InputStreams for your Blob then add the following property to you hibernate configuration
hibernate.jdbc.use_streams_for_binary=true
This will instruct the MaterializedBlobType to use an InputStream instead of a byte[].

I ended up creating my own UserType that converts between Blob and InputStream:
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.usertype.UserType;
import java.io.InputStream;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
public class BlobUserType implements UserType
{
// ------------------------ INTERFACE METHODS ------------------------
// --------------------- Interface UserType ---------------------
#Override
public int[] sqlTypes()
{
return new int[]{Types.BLOB};
}
#Override
public Class returnedClass()
{
return InputStream.class;
}
#Override
public boolean equals( Object x, Object y ) throws HibernateException
{
boolean result;
if (x == y)
{
result = true;
}
else if (x == null || y == null)
{
result = false;
}
else
{
result = x.equals( y );
}
return result;
}
#Override
public int hashCode( Object x ) throws HibernateException
{
return x.hashCode();
}
#Override
public Object nullSafeGet( ResultSet rs, String[] names, SessionImplementor session, Object owner ) throws HibernateException, SQLException
{
return rs.getBlob( names[0] ).getBinaryStream();
}
#Override
public void nullSafeSet( PreparedStatement st, Object value, int index, SessionImplementor session ) throws HibernateException, SQLException
{
if( value != null )
{
InputStream inputStream = (InputStream)value;
st.setBlob( index, inputStream );
}
else
{
st.setNull( index, Types.BLOB );
}
}
#Override
public Object deepCopy( Object value ) throws HibernateException
{
return value;
}
#Override
public boolean isMutable()
{
return false;
}
#Override
public Serializable disassemble( Object value ) throws HibernateException
{
return null;
}
#Override
public Object assemble( Serializable cached, Object owner ) throws HibernateException
{
return null;
}
#Override
public Object replace( Object original, Object target, Object owner ) throws HibernateException
{
return original;
}
}
Seems to be working fine loading and saving my entity from/to the database.

You should not use AbstractLobType because it is in the hibernate 3 as you said.
You can create your own UserType to convert between Blob and InputStream. However, if you are migrating existing data from Hibernate 3 to 4, your code will not work:
The format of BlobSerializableType has header's information in addition which is something like this:
’ t{"userServices":[{"accountStatus":"PendingTermsAndConditions","serviceIdentifier":"SNG"}]...}]}
Your code will working (reading, writing) to the format without header:
{"userServices":[{"accountStatus":"PendingTermsAndConditions","serviceIdentifier":"SNG"}]...}]}
My personal solution is to simulate the Hibernate 3 to write and read Blob data as below:
package com.newbay.acs.domain.hibernate;
import org.apache.commons.io.IOUtils;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.usertype.UserType;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
/**
* Created by qale0001 on 21/06/2016.
*/
public class CustomMaterializedBlobType implements UserType
{
private static final int OUTPUT_BYTE_ARRAY_INITIAL_SIZE = 1024;
#Override
public int[] sqlTypes()
{
return new int[]{Types.BLOB};
}
#Override
public Class returnedClass()
{
return String.class;
}
#Override
public boolean equals(Object x, Object y) throws HibernateException {
boolean result;
if (x == y)
{
result = true;
}
else if (x == null || y == null)
{
result = false;
}
else
{
result = x.equals( y );
}
return result;
}
#Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
#Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
java.sql.Blob blob = rs.getBlob( names[0] );
InputStream is = blob.getBinaryStream();
if (is != null) {
try {
ObjectInputStream ois = new ObjectInputStream(is);
try {
return ois.readObject();
} catch (ClassNotFoundException ex) {
throw new HibernateException("Could not deserialize BLOB contents", ex);
} finally {
ois.close();
}
} catch (IOException ex) {
throw new HibernateException("Could not deserialize BLOB contents", ex);
}
}
else {
return null;
}
}
#Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
if( value != null )
{
ByteArrayOutputStream baos = new ByteArrayOutputStream(OUTPUT_BYTE_ARRAY_INITIAL_SIZE);
try {
ObjectOutputStream oos = new ObjectOutputStream(baos);
try {
oos.writeObject(value);
oos.flush();
InputStream is = new ByteArrayInputStream(baos.toByteArray());
st.setBlob(index, is);
}
finally {
oos.close();
}
} catch (IOException ex) {
throw new HibernateException("Could not serialize BLOB contents", ex);
}
}
else
{
st.setNull( index, Types.BLOB );
}
}
#Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
#Override
public boolean isMutable() {
return false;
}
#Override
public Serializable disassemble(Object value) throws HibernateException {
return null;
}
#Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return null;
}
#Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
}

Related

JNDI Context Initialization error while migration from WAS to liberty

The WsnInitialContextFactory class not found exception. Liberty does not support this class, then how can I remove jndi.properties default settings. This property file contain this class name for InitialContext.
Properties:
INITIAL_CONTEXT_FACTORY = "com.ibm.websphere.naming.WsnInitialContextFactory"
CC_PROVIDER_URL = "iiop://localhost.svr.us.xxxxxxx.net:41516"
InitialContext Lookup:
try {
Hashtable params = new Hashtable();
params.put(Context.INITIAL_CONTEXT_FACTORY, ADProperties.WS_INITIAL_CONTEXT_FACTORY);
params.put(Context.PROVIDER_URL, ADProperties.AD_PROVIDER_URL);
Context ctx = new InitialContext(params);
try {
ds = (DataSource) ctx.lookup("java:comp/env/" + jndiName);
} catch (Exception ex) {
LogUtil.debugException("DBConnectionManager", "Exception in init: Resource reference DataSource lookup Error.", "init()", ex, "");
try {
ds = (DataSource) ctx.lookup("jdbc/" + jndiName);
} catch (Exception exp) {
LogUtil.debugException("DBConnectionManager", "Exception in init: Datasource lookup Error.", "init()", exp, "");
}
}
Exception:
[INFO] [err] java.lang.NoClassDefFoundError: Could not initialize class com.ibm.websphere.naming.WsnInitialContextFactory
[INFO] [err] at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[INFO] [err] at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
[INFO] [err] at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
[INFO] [err] at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
[INFO] [err] at com.ibm.ws.jndi.internal.WASInitialContextFactoryBuilder.createInitialContextFactory(WASInitialContextFactoryBuilder.java:57)
[INFO] [err] at [internal classes]
[INFO] [err] at java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:730)
[INFO] [err] at java.naming/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305)
[INFO] [err] at java.naming/javax.naming.InitialContext.init(InitialContext.java:236)
[INFO] [err] at java.naming/javax.naming.InitialContext.<init>(InitialContext.java:184)
Liberty does not support the WsnInitialContextFactory class. You can just do this (and it'll work in WebSphere traditional as well):
try {
Context ctx = new InitialContext(new Hashtable());
try {
ds = (DataSource) ctx.lookup("java:comp/env/" + jndiName);
} catch (Exception ex) {
LogUtil.debugException("DBConnectionManager", "Exception in init: Resource reference DataSource lookup Error.", "init()", ex, "");
try {
ds = (DataSource) ctx.lookup("jdbc/" + jndiName);
} catch (Exception exp) {
LogUtil.debugException("DBConnectionManager", "Exception in init: Datasource lookup Error.", "init()", exp, "");
}
}

ComponentScan and import org.springframework.context.annotation.ComponentScan can not be resolved as a type

I have a problem with my project in Spring. Firstly I couldn't run it on the server but after downloading all resources again it started.
But now I have some imports which Spring can not see
For example:
import org.springframework.context.annotation.ComponentScan can not be resolved as a type.
and autwired value
#ComponentScan can not be resolved as a type.
Because of that hibernate is not creating tables in my database ( I think so )
Also two configuration classes have some errors:
The hierarchy of the type Spring4Initializer is inconsistent
SpringSecurityInitializer
public class Spring4Initializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { Spring4Configuration.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return new Filter[] { characterEncodingFilter };
}
}
SpringSecurityInitializer Multiple markers at this line
- The type org.springframework.web.WebApplicationInitializer cannot be resolved. It is indirectly referenced from
required .class files
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
I've tried maven clean and maven build
[WARNING]
[WARNING] Some problems were encountered while building the effective model for pl.dmcs:eschool:war:1.0.0-BUILD-SNAPSHOT
[WARNING] 'dependencies.dependency.(groupId:artifactId:type:classifier)' must be unique: org.springframework:spring-context:jar -> version ${org.springframework-version} vs 4.3.7.RELEASE # line 74, column 17
[WARNING] 'dependencies.dependency.(groupId:artifactId:type:classifier)' must be unique: com.fasterxml.jackson.core:jackson-databind:jar -> version 2.8.8 vs 2.8.3 # line 157, column 15
[WARNING] 'dependencies.dependency.(groupId:artifactId:type:classifier)' must be unique: javax.servlet:servlet-api:jar -> version ${servlet-api-version} vs 2.5 # line 254, column 15
[WARNING] 'dependencies.dependency.(groupId:artifactId:type:classifier)' must be unique: org.springframework:spring-context:jar -> version ${org.springframework-version} vs 3.0.5.RELEASE # line 271, column 14
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building E-School 1.0.0-BUILD-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) # eschool ---
[INFO] Deleting C:\Users\Piotr\Desktop\E-School\target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Does anyone know what should I do with it to make hibernate working?
In Outline tree my function GetHibernateProperites() is marked as red
Have you included the spring-context in your maven dependencies? I think you are missing that dependency.

Injecting SoyTemplateRenderer in custom Atlassian JIRA plugin

I'm currently trying to develop a custom Jira plugin, which also uses a servlet to render a Soy template.
This is the code of my servlet:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package at.fraiss.plugins.custommenuitem.servlets;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import com.atlassian.soy.renderer.SoyTemplateRenderer;
import java.util.HashMap;
import java.util.Map;
/**
*
* #author Mario
*/
public class SoyTemplateServlet extends HttpServlet {
private SoyTemplateRenderer soyTemplateRenderer;
public SoyTemplateServlet(SoyTemplateRenderer soyTemplateRenderer)
{
this.soyTemplateRenderer = soyTemplateRenderer;
}
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
response.setContentType("text/html");
response.getWriter().write(getHtml());
}
public String getHtml()
{
Map<String, Object> data = new HashMap<String,Object>();
data.put("isLocal", true);
data.put("url", "http://www.example.com");
data.put("title", "example");
return this.soyTemplateRenderer.render("jira.webresources:soy-templates", "JIRA.Templates.Links.helpLink", data);
}
}
This is how I defined the soy template files inside the atlassian-plugin.xml descriptor:
<web-resource key="soy-templates">
<dependency>com.atlassian.soy.soy-template-plugin:soy-deps</dependency>
<!-- Available to the server-side only -->
<resource type="soy" name="links" location="links.soy"/>
 
<!-- Make available to the client-side in JS as well... -->
<transformation extension="soy">
<transformer key="soyTransformer"/>
</transformation>
<resource type="download" name="Links.soy.js" location="links.soy"/>
</web-resource>
I have added the following section to my pom.xml:
<dependency>
<groupId>com.atlassian.soy</groupId>
<artifactId>soy-template-renderer-api</artifactId>
<version>4.0.4</version>
<scope>provided</scope>
</dependency>
and always get this error when try to acces the servlet
[INFO] [talledLocalContainer] Caused by: org.springframework.beans.factory.Unsat isfiedDependencyException: Error creating bean with name 'at.fraiss.plugins.cust ommenuitem.servlets.SoyTemplateServlet': Unsatisfied dependency expressed throug h constructor argument with index 0 of type [com.atlassian.soy.renderer.SoyTempl ateRenderer]: : No qualifying bean of type [com.atlassian.soy.renderer.SoyTempla teRenderer] found for dependency: expected at least 1 bean which qualifies as au towire candidate for this dependency. Dependency annotations: {}; nested excepti on is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualif ying bean of type [com.atlassian.soy.renderer.SoyTemplateRenderer] found for dep endency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Con structorResolver.createArgumentArray(ConstructorResolver.java:749) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Con structorResolver.autowireConstructor(ConstructorResolver.java:185) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Abs tractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanF actory.java:1139) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Abs tractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFa ctory.java:1042) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Abs tractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory. java:504) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Abs tractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.ja va:342) [INFO] [talledLocalContainer] ... 2 filtered [INFO] [talledLocalContainer] at java.lang.reflect.Method.invoke(Method.java:4 97) [INFO] [talledLocalContainer] at com.atlassian.plugin.osgi.spring.DefaultSprin gContainerAccessor.createBean(DefaultSpringContainerAccessor.java:112) [INFO] [talledLocalContainer] at com.atlassian.plugin.module.ClassPrefixModule Factory.createModule(ClassPrefixModuleFactory.java:39) [INFO] [talledLocalContainer] at com.atlassian.plugin.module.PrefixDelegatingM oduleFactory.createModule(PrefixDelegatingModuleFactory.java:100) [INFO] [talledLocalContainer] at com.atlassian.plugin.servlet.descriptors.Serv letModuleDescriptor.getModule(ServletModuleDescriptor.java:48) [INFO] [talledLocalContainer] at com.atlassian.plugin.servlet.DelegatingPlugin Servlet.<init>(DelegatingPluginServlet.java:33) [INFO] [talledLocalContainer] at com.atlassian.plugin.servlet.DefaultServletMo duleManager$LazyLoadedServletReference.create(DefaultServletModuleManager.java:5 41) [INFO] [talledLocalContainer] at com.atlassian.plugin.servlet.DefaultServletMo duleManager$LazyLoadedServletReference.create(DefaultServletModuleManager.java:5 21) [INFO] [talledLocalContainer] at com.atlassian.util.concurrent.LazyReference$S ync.run(LazyReference.java:325) [INFO] [talledLocalContainer] at com.atlassian.util.concurrent.LazyReference.g ...
I also had this problem (and lost hours on it).
The Spring scanner apparently only processes classes marked with #Named.
This worked for me:
#Named("MyServlet")
public class MyServlet extends HttpServlet{
#ComponentImport
private final SoyTemplateRenderer soyTemplateRenderer;
#Inject
public MyServlet(#ComponentImport final SoyTemplateRenderer soyTemplateRenderer) {
this.soyTemplateRenderer = soyTemplateRenderer;
}
}
Apparently this has nothing to do with jiira, but in your frustration you seem to be blaming it and its documentation. It's actually a problem with your use of spring, and your apparent inability to read stack traces.
The first entry in the stack trace mentions, in may different ways, No qualif
ying bean of type [com.atlassian.soy.renderer.SoyTemplateRenderer] found. So, you seem to have not provided a bean definition for the SoyTemplateRenderer for spring to find. Rectify this and this particular problem will disappear.

Getting error while running storm connection with accumulo

I have Storm Bolt like follows,
package storm.bolt;
import java.util.Map;
import org.apache.accumulo.core.client.AccumuloException;
import org.apache.accumulo.core.client.AccumuloSecurityException;
import org.apache.accumulo.core.client.BatchWriter;
import org.apache.accumulo.core.client.Connector;
import org.apache.accumulo.core.client.MultiTableBatchWriter;
import org.apache.accumulo.core.client.TableExistsException;
import org.apache.accumulo.core.client.TableNotFoundException;
import org.apache.accumulo.core.client.ZooKeeperInstance;
import org.apache.accumulo.core.data.Mutation;
import org.apache.accumulo.core.data.Value;
import org.apache.hadoop.io.Text;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.IRichBolt;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.tuple.Tuple;
public class AccumuloBolt implements IRichBolt {
private static final long serialVersionUID = 1L;
private OutputCollector collector;
private ZooKeeperInstance instance;
private Connector connector;
private BatchWriter bw;
private Text colf;
private MultiTableBatchWriter mtbw;
private final String instanceName;
private final String zooServers;
private final String userName;
private final String password;
Map<String, Integer> counters;
/**
* #param zooServers The host on which Zookeeper is running.
* #param userName for which Accumula username.
* #param password The Acumula passowrd
* written to.
* String instanceName = "myistance";
* String zooServers = "192.168.1.81:2181";
* String userName = "root";
* String password = "aryadevi";
*/
public AccumuloBolt(String instanceName, String zooServers, String userName,
String password) {
this.instanceName = instanceName;
this.zooServers = zooServers;
this.userName = userName;
this.password = password;
}
public void prepare( Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
try {
//this.instance = new ZooKeeperInstance(instanceName, zooServers);
this.instance = new ZooKeeperInstance("myistance", "192.168.1.81:2181");
//this.connector= instance.getConnector(userName, password);
this.connector= instance.getConnector("root", "aryadevi");
this.mtbw=connector.createMultiTableBatchWriter(200000l, 300, 4);
this.bw=null;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void execute(Tuple input) {
if (shouldActOnInput(input)) {
try{
if (!this.connector.tableOperations().exists("new2"))
this.connector.tableOperations().create("new2");
this.bw = this.mtbw.getBatchWriter("new2");
this.colf=new Text("colfam");
System.out.println("writing ...");
String str = input.getString(0);
if(!counters.containsKey(str)){
counters.put(str, 1);
}else{
Integer c = counters.get(str) + 1;
counters.put(str, c);
}
}catch (Exception e) {
throw new RuntimeException(e);
}
//DBObject updateObj = getDBObjectForInput(input);
//this.bw.addMutation(m);
} else {
collector.ack(input);
}
}
public void cleanup() {
try{
for(Map.Entry<String, Integer> entry : counters.entrySet()){
Mutation m = new Mutation(new Text(String.format("row_%d",entry.getKey() )));
m.put(this.colf, new Text(String.format("colqual_%d", entry.getKey())), new Value((String.format("value_%d", entry.getValue())).getBytes()));
System.out.println(entry.getKey()+": "+entry.getValue());
bw.addMutation(m);
}
this.mtbw.close();
}catch (Exception e) {
throw new RuntimeException(e);
}
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
// TODO Auto-generated method stub
}
public boolean shouldActOnInput(Tuple input) {
return true;
}
public Map<String, Object> getComponentConfiguration() {
// TODO Auto-generated method stub
return null;
}
}
I just compile the this torm using "mvn comple" and create a package using mvn package
then i just run the storm using following commend
storm jar target/storm-twitter-0.0.1-SNAPSHOT-jar-with-dependencies.jar storm.TwitterStorm
after running this commend getting error like follows
java.lang.NoClassDefFoundError: Could not initialize class org.apache.accumulo.core.client.ZooKeeperInstance
at storm.bolt.AccumuloBolt.prepare(AccumuloBolt.java:60) ~[storm-twitter-0.0.1-SNAPSHOT-jar-with-dependencies.jar:na]
at backtype.storm.daemon.executor$fn__5641$fn__5653.invoke(executor.clj:690) ~[storm-core-0.9.2-incubating.jar:0.9.2-incubating]
at backtype.storm.util$async_loop$fn__457.invoke(util.clj:429) ~[storm-core-0.9.2-incubating.jar:0.9.2-incubating]
at clojure.lang.AFn.run(AFn.java:24) [clojure-1.5.1.jar:na]
at java.lang.Thread.run(Thread.java:744) [na:1.7.0_55]
46217 [Thread-8-count] ERROR backtype.storm.util - Async loop died!
java.lang.ExceptionInInitializerError: null
at org.apache.log4j.Logger.getLogger(Logger.java:39) ~[log4j-over-slf4j-1.6.6.jar:1.6.6]
at org.apache.log4j.Logger.getLogger(Logger.java:43) ~[log4j-over-slf4j-1.6.6.jar:1.6.6]
at org.apache.accumulo.core.client.ZooKeeperInstance.<clinit>(ZooKeeperInstance.java:63) ~[storm-twitter-0.0.1-SNAPSHOT-jar-with-dependencies.jar:na]
at storm.bolt.AccumuloBolt.prepare(AccumuloBolt.java:60) ~[storm-twitter-0.0.1-SNAPSHOT-jar-with-dependencies.jar:na]
at backtype.storm.daemon.executor$fn__5641$fn__5653.invoke(executor.clj:690) ~[storm-core-0.9.2-incubating.jar:0.9.2-incubating]
at backtype.storm.util$async_loop$fn__457.invoke(util.clj:429) ~[storm-core-0.9.2-incubating.jar:0.9.2-incubating]
at clojure.lang.AFn.run(AFn.java:24) [clojure-1.5.1.jar:na]
at java.lang.Thread.run(Thread.java:744) [na:1.7.0_55]
Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError. See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
at org.apache.log4j.Log4jLoggerFactory.<clinit>(Log4jLoggerFactory.java:49) ~[log4j-over-slf4j-1.6.6.jar:1.6.6]
... 8 common frames omitted
46218 [Thread-10-count] ERROR backtype.storm.daemon.executor -
java.lang.NoClassDefFoundError: Could not initialize class org.apache.accumulo.core.client.ZooKeeperInstance
at storm.bolt.AccumuloBolt.prepare(AccumuloBolt.java:60) ~[storm-twitter-0.0.1-SNAPSHOT-jar-with-dependencies.jar:na]
at backtype.storm.daemon.executor$fn__5641$fn__5653.invoke(executor.clj:690) ~[storm-core-0.9.2-incubating.jar:0.9.2-incubating]
at backtype.storm.util$async_loop$fn__457.invoke(util.clj:429) ~[storm-core-0.9.2-incubating.jar:0.9.2-incubating]
at clojure.lang.AFn.run(AFn.java:24) [clojure-1.5.1.jar:na]
at java.lang.Thread.run(Thread.java:744) [na:1.7.0_55]
46218 [Thread-8-count] ERROR backtype.storm.daemon.executor -
java.lang.ExceptionInInitializerError: null
at org.apache.log4j.Logger.getLogger(Logger.java:39) ~[log4j-over-slf4j-1.6.6.jar:1.6.6]
at org.apache.log4j.Logger.getLogger(Logger.java:43) ~[log4j-over-slf4j-1.6.6.jar:1.6.6]
at org.apache.accumulo.core.client.ZooKeeperInstance.<clinit>(ZooKeeperInstance.java:63) ~[storm-twitter-0.0.1-SNAPSHOT-jar-with-dependencies.jar:na]
at storm.bolt.AccumuloBolt.prepare(AccumuloBolt.java:60) ~[storm-twitter-0.0.1-SNAPSHOT-jar-with-dependencies.jar:na]
at backtype.storm.daemon.executor$fn__5641$fn__5653.invoke(executor.clj:690) ~[storm-core-0.9.2-incubating.jar:0.9.2-incubating]
at backtype.storm.util$async_loop$fn__457.invoke(util.clj:429) ~[storm-core-0.9.2-incubating.jar:0.9.2-incubating]
at clojure.lang.AFn.run(AFn.java:24) [clojure-1.5.1.jar:na]
at java.lang.Thread.run(Thread.java:744) [na:1.7.0_55]
Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError. See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
at org.apache.log4j.Log4jLoggerFactory.<clinit>(Log4jLoggerFactory.java:49) ~[log4j-over-slf4j-1.6.6.jar:1.6.6]
... 8 common frames omitted
46218 [Thread-6] INFO backtype.storm.daemon.executor - Loading executor count:[4 4]
46219 [Thread-6] INFO backtype.storm.daemon.task - Emitting: count __system ["startup"]
46220 [Thread-6] INFO backtype.storm.daemon.executor - Loaded executor tasks count:[4 4]
46224 [Thread-6] INFO backtype.storm.daemon.executor - Finished loading executor count:[4 4]
46224 [Thread-12-count] INFO backtype.storm.daemon.executor - Preparing bolt count:(4)
46225 [Thread-12-count] ERROR backtype.storm.util - Async loop died!
java.lang.NoClassDefFoundError: Could not initialize class org.apache.accumulo.core.client.ZooKeeperInstance
at storm.bolt.AccumuloBolt.prepare(AccumuloBolt.java:60) ~[storm-twitter-0.0.1-SNAPSHOT-jar-with-dependencies.jar:na]
at backtype.storm.daemon.executor$fn__5641$fn__5653.invoke(executor.clj:690) ~[storm-core-0.9.2-incubating.jar:0.9.2-incubating]
at backtype.storm.util$async_loop$fn__457.invoke(util.clj:429) ~[storm-core-0.9.2-incubating.jar:0.9.2-incubating]
at clojure.lang.AFn.run(AFn.java:24) [clojure-1.5.1.jar:na]
at java.lang.Thread.run(Thread.java:744) [na:1.7.0_55]
46226 [Thread-12-count] ERROR backtype.storm.daemon.executor -
java.lang.NoClassDefFoundError: Could not initialize class org.apache.accumulo.core.client.ZooKeeperInstance
at storm.bolt.AccumuloBolt.prepare(AccumuloBolt.java:60) ~[storm-twitter-0.0.1-SNAPSHOT-jar-with-dependencies.jar:na]
at backtype.storm.daemon.executor$fn__5641$fn__5653.invoke(executor.clj:690) ~[storm-core-0.9.2-incubating.jar:0.9.2-incubating]
at backtype.storm.util$async_loop$fn__457.invoke(util.clj:429) ~[storm-core-0.9.2-incubating.jar:0.9.2-incubating]
at clojure.lang.AFn.run(AFn.java:24) [clojure-1.5.1.jar:na]
at java.lang.Thread.run(Thread.java:744) [na:1.7.0_55]
46321 [Thread-10-count] INFO backtype.storm.util - Halting process: ("Worker died")
46321 [Thread-8-count] INFO backtype.storm.util - Halting process: ("Worker died")
It looks like this Storm ticket has a relevant discussion:
https://issues.apache.org/jira/browse/STORM-122
I think Accumulo has an slf4j-log4j12 dependency, and Storm uses log4j-over-slf4j which is incompatible. The discussion seems to suggest excluding logging dependencies like slf4j-log4j12 and log4j from your Accumulo dependency. I don't know if this will work, but it's worth a try.

Custom Liquibase Change error when integrating with Spring: Unknown Liquibase extension. Are you missing a jar from your classpath?

As part of the database upgrade for an existing application, a custom Liquibase change which extends AbstractChange has been created:
#DatabaseChange(name = "springBeanChange", description = "Runs a spring bean custom change", priority = ChangeMetaData.PRIORITY_DEFAULT)
public class SpringBeanChange extends AbstractChange {
private String beanName;
private String changeClass;
#DatabaseChangeProperty(description = "Spring bean name (optional)")
public String getBeanName() {
return this.beanName;
}
public void setBeanName(final String beanName) {
this.beanName = beanName;
}
#DatabaseChangeProperty(description = "Spring bean class")
public String getChangeClass() {
return this.changeClass;
}
public void setChangeClass(final String changeClass) {
this.changeClass = changeClass;
}
private CustomTaskChange bean;
#Override
public boolean generateStatementsVolatile(final Database database) {
return true;
}
#Override
public String getConfirmationMessage() {
return findBean().getConfirmationMessage();
}
#Override
public SqlStatement[] generateStatements(final Database database) {
try {
findBean().execute(database);
} catch (CustomChangeException e) {
throw new UnexpectedLiquibaseException(e);
}
return new SqlStatement[0];
}
#SuppressWarnings("unchecked")
private CustomTaskChange findBean() {
Class<CustomTaskChange> requiredType = CustomTaskChange.class;
if (this.changeClass != null) {
try {
Class<?> requestedType = Class.forName(this.changeClass);
if (CustomTaskChange.class.isAssignableFrom(requestedType)) {
requiredType = (Class<CustomTaskChange>) requestedType;
} else {
throw new UnexpectedLiquibaseException(
"Specified changeClass " + this.changeClass
+ " was not an instance of "
+ CustomTaskChange.class);
}
} catch (ClassNotFoundException e) {
throw new UnexpectedLiquibaseException(
"Could not create change class", e);
}
}
if (this.bean == null) {
if (getBeanName() == null) {
this.bean = SpringContextHolder.getInstance().getContext()
.getBean(requiredType);
} else {
this.bean = SpringContextHolder.getInstance().getContext()
.getBean(getBeanName(), requiredType);
}
}
return this.bean;
}
#Override
public ValidationErrors validate(final Database database) {
try {
return findBean().validate(database);
} catch (NullPointerException p_exception) {
return new ValidationErrors()
.addError("Exception thrown calling validate():"
+ p_exception.getMessage());
} catch (UnexpectedLiquibaseException p_exception) {
return new ValidationErrors()
.addError("Exception thrown calling validate():"
+ p_exception.getMessage());
} catch (NoSuchBeanDefinitionException p_exception) {
return new ValidationErrors()
.addError("Exception thrown calling validate():"
+ p_exception.getMessage());
} catch (BeanNotOfRequiredTypeException p_exception) {
return new ValidationErrors()
.addError("Exception thrown calling validate():"
+ p_exception.getMessage());
} catch (BeansException p_exception) {
return new ValidationErrors()
.addError("Exception thrown calling validate():"
+ p_exception.getMessage());
}
}
}
This is then configured in the database change log XML file as follows:
<changeSet id="15" author="theauthor">
<XXX:springBeanChange
changeClass="XXX.XXX.XXX.upgrade.tasks.TaskUpgrade" />
</changeSet>
Where TaskUpgrade implements CustomTaskChange and is the class that is returned get the call to getBean in SpringBeanChange.
The database change log file also contains many 'normal' liquibase commands such as addColumn.
A custom Java class has then been written which actually performs the upgrade (the following lines show the important lines of code which actually do the upgrade). This Java program is manually executed after the application has been deployed onto the server:
Liquibase liquibase =
new Liquibase(getChangeLogFile(), new ClassLoaderResourceAccessor(), new JdbcConnection(conn));
if ("update".equalsIgnoreCase(command)) {
liquibase.update(contexts);
} else {
throw new IllegalArgumentException("Unknown command " + command);
}
This works fine and executes the database upgrade.
I'm looking to avoid the need to use the custom Java program to perform the upgrade and actually do it when the application starts up. The app already uses Spring so it makes sense to to the upgrade when the Spring context is initialising.
To do this, I've added the following to the applicationContext file:
<bean id="myLiquibase" class="liquibase.integration.spring.SpringLiquibase">
<property name="dataSource" ref="dataSource" />
<property name="changeLog" value="classpath:databaseChangeLog.xml" />
<property name="contexts" value="test, production" />
</bean>
However, when the application starts up, I get the following exception:
2014-03-25 13:02:16,097 [main] ERROR context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myLiquibase' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is liquibase.exception.ChangeLogParseException: Invalid Migration File: Unknown Liquibase extension: springBeanChange. Are you missing a jar from your classpath?
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1488)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:549)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1282)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:518)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:499)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:224)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at XXX.XXX.XXX.demo.YYYDemo.main(YYYDemo.java:47)
Caused by: liquibase.exception.ChangeLogParseException: Invalid Migration File: Unknown Liquibase extension: springBeanChange. Are you missing a jar from your classpath?
at liquibase.parser.core.xml.XMLChangeLogSAXParser.parse(XMLChangeLogSAXParser.java:133)
at liquibase.Liquibase.update(Liquibase.java:129)
at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:291)
at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:258)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1547)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1485)
... 22 more
Caused by: org.xml.sax.SAXException: Unknown Liquibase extension: springBeanChange. Are you missing a jar from your classpath?
at liquibase.parser.core.xml.XMLChangeLogSAXHandler.startElement(XMLChangeLogSAXHandler.java:495)
at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
at org.apache.xerces.parsers.AbstractXMLDocumentParser.emptyElement(Unknown Source)
at org.apache.xerces.impl.xs.XMLSchemaValidator.emptyElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at liquibase.parser.core.xml.XMLChangeLogSAXParser.parse(XMLChangeLogSAXParser.java:99)
... 27 more
Caused by: org.xml.sax.SAXException: Unknown Liquibase extension: springBeanChange. Are you missing a jar from your classpath?
at liquibase.parser.core.xml.XMLChangeLogSAXHandler.startElement(XMLChangeLogSAXHandler.java:359)
... 39 more
I can't find anything on the Liquibase site or anywhere else which provides any help as to what JAR I'm missing (if indeed I am missing one) or if anything else is missing/not defined.
Does anyone have any ideas?
Thanks in advance.
The jar that contains the custom extension is what is missing from your classpath. I don't use Spring, so I don't know how it sets up the classpath, but you probably need to either put the jar in a standard location so Spring can find it or else configure the Spring classpath.

Resources