Jooq CastException on Spring Boot context refreshed - java

when spring boot first startup, jooq works well.
but if i make change to code and after spring boot context refreshed,
then i stucked in trouble with class cast exception.
the problem is cast exception on same class.
my boot conf is :
#Autowired
private DataSource dataSource;
public ExecuteListener exceptionTransformer() {
return new DefaultExecuteListener() {
private static final long serialVersionUID = 1L;
#Override
public void exception(ExecuteContext context) {
SQLDialect dialect = context.configuration().dialect();
SQLExceptionTranslator translator = (dialect != null)
? new SQLErrorCodeSQLExceptionTranslator(dialect.name())
: new SQLStateSQLExceptionTranslator();
context.exception(
translator.translate("jOOQ", context.sql(), context.sqlException()));
}
};
}
#Primary
#Bean
public DefaultDSLContext dsl() {
return new DefaultDSLContext(configuration());
}
public DataSourceConnectionProvider connectionProvider() {
return new DataSourceConnectionProvider(new TransactionAwareDataSourceProxy(dataSource));
}
public DefaultConfiguration configuration() {
DefaultConfiguration configuration = new DefaultConfiguration();
configuration.set(connectionProvider());
configuration.set(new DefaultExecuteListenerProvider(exceptionTransformer()));
configuration.set(SQLDialect.MYSQL);
// #formatter:off
configuration.set(
new Settings()
.withExecuteLogging(true)
.withRenderFormatted(true)
);
// #formatter:on
configuration.set(SfmRecordMapperProviderFactory.newInstance().ignorePropertyNotFound().newProvider());
return configuration;
}
query code is :
User user = dsl.select()
.from(USER)
.where(USER.USER_ID.eq(id)).fetchOneInto(User.class);
admin.domain.User is:
#Data
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String userId;
#JsonIgnore
private String pswd;
private String name;
private String useYn;
private Timestamp registDatetime;
private Timestamp updateDatetime;
}
stack trace is :
java.lang.ClassCastException: admin.domain.User cannot be cast to admin.domain.User
at admin.dao.UserDao.getUserByIdWithRoles(UserDao.java:123)
at admin.dao.UserDao$$FastClassBySpringCGLIB$$f7b71f39.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:747)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
what is my fault?

Do you have spring boot automatic restart enabled?
This look likes it, you could try:
to run without the devtools (https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html#using-boot-devtools-restart-disable)
add the correct path to your live reload (
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html#using-boot-devtools-restart-additional-paths and https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html#using-boot-devtools-customizing-classload )
:)

Related

Java Springboot #Autowired Mybatis Mapper is null

Autowired mapper in service is null.
There is mapper - VaMapper.java
#Mapper
#Repository
public interface VaMapper {
int getSiteVa(ParameterMap param) throws Exception;
}
There is service class. - VaService.java
#Service
public class VaService {
private static final Logger logger = LoggerFactory.getLogger(VaService.class);
#Autowired
public VaMapper vaMapper; //This mapper is null
public void handlVaInfo(JSONObject vaObj) throws Exception{
String vaHost = vaObj.get("vaHost").toString();
System.out.println("vaHost:"+vaHost);
int a = vaMapper.getSiteVa(new ParameterMap());
}
And I want to use this service on below class. - SimpleEchoSocket.java
#WebSocket(maxTextMessageSize = 64 * 1024)
public class SimpleEchoSocket{
public VaServiceva vaService(){
return new VaService();
}
#OnWebSocketMessage
public void onMessageBuffer(Session session, byte[] byteArray, int offset, int length) throws Exception {
System.out.println("onMessageBuffer");
String vaHost = session.getRemoteAddress().toString().replaceAll("/", "");
System.out.println("vaHost:"+vaHost);
int thisIdx = -1;
JSONObject thisObj = null;
for(int i=0; i<vaArray.size(); i++){
JSONObject vaObj = (JSONObject) vaArray.get(i);
if(vaObj.get("vaHost").toString().equals(vaHost)){
vaObj.put("plateImg", byteArray);
thisIdx = i;
thisObj = vaObj;
break;
}
}
if(thisIdx != -1){
vaArray.remove(thisIdx);
vaService().handlVaInfo(thisObj);
}
}
}
However NullPointerExcpetion occured like below.
java.lang.NullPointerException: Cannot invoke "com.iimp.pom.mapper.va.VaMapper.getSiteVa(com.iimp.pom.util.ParameterMap)" because "this.vaMapper" is null
at com.iimp.pom.service.va.VaService.getSiteVa(VaService.java:50)
at com.iimp.pom.va.VaProcessor.handlVaInfo(VaProcessor.java:44)
at com.iimp.pom.socket.SimpleEchoSocket.onMessageBuffer(SimpleEchoSocket.java:118)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.eclipse.jetty.websocket.common.events.annotated.CallableMethod.call(CallableMethod.java:70)
at org.eclipse.jetty.websocket.common.events.annotated.OptionalSessionCallableMethod.call(OptionalSessionCallableMethod.java:68)
at org.eclipse.jetty.websocket.common.events.JettyAnnotatedEventDriver.onBinaryMessage(JettyAnnotatedEventDriver.java:143)
at org.eclipse.jetty.websocket.common.message.SimpleBinaryMessage.messageComplete(SimpleBinaryMessage.java:75)
at org.eclipse.jetty.websocket.common.events.AbstractEventDriver.appendMessage(AbstractEventDriver.java:67)
at org.eclipse.jetty.websocket.common.events.JettyAnnotatedEventDriver.onBinaryFrame(JettyAnnotatedEventDriver.java:130)
at org.eclipse.jetty.websocket.common.events.AbstractEventDriver.incomingFrame(AbstractEventDriver.java:147)
at org.eclipse.jetty.websocket.common.WebSocketSession.incomingFrame(WebSocketSession.java:326)
at org.eclipse.jetty.websocket.common.extensions.ExtensionStack.incomingFrame(ExtensionStack.java:202)
at org.eclipse.jetty.websocket.common.Parser.notifyFrame(Parser.java:225)
at org.eclipse.jetty.websocket.common.Parser.parseSingleFrame(Parser.java:259)
at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onFillable(AbstractWebSocketConnection.java:459)
at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onFillable(AbstractWebSocketConnection.java:440)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:135)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:882)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1036)
at java.base/java.lang.Thread.run(Thread.java:831)
...
As Denuim said, SimpleEchoSocket is managed by jetty not springboot.
But I think I succeed to load VaService on SimpleEchoSocket.
I changed code for load mapper instead of autowired.
However VaMapper is abstract, so I can't load mapper just like that.
How can I load vaMapper on VaService?
Please help me.
Thank you all.

Apache Ignite Cache Store + HikariCP DataSource

I am trying to set up Apache Ignite cache store using PostgreSQL as an external storage.
public class MyCacheStore extends CacheStoreAdapter<String, MyCache> {
private static final String GET_QUERY= "SELECT * FROM ..";
private static final String UPDATE_QUERY = "UPDATE ...";
private static final String DELETE_QUERY = "DELETE FROM ..";
#CacheStoreSessionResource
private CacheStoreSession session;
#Override
public MyCache load(String key) throws CacheLoaderException {
Connection connection = session.attachment();
try (PreparedStatement preparedStatement = connection.prepareStatement(GET_QUERY)) {
// some stuff
}
}
#Override
public void loadCache(IgniteBiInClosure<String, MyCache> clo, Object... args) {
super.loadCache(clo, args);
}
#Override
public void write(Cache.Entry<? extends String, ? extends MyCache> entry) throws CacheWriterException {
Connection connection = session.attachment();
try (PreparedStatement preparedStatement = connection.prepareStatement(UPDATE_QUERY)) {
// some stuff
}
}
#Override
public void delete(Object key) throws CacheWriterException {
Connection connection = session.attachment();
try (PreparedStatement preparedStatement = connection.prepareStatement(DELETE_QUERY)) {
// some stuff
}
}
}
MyCache is a standard class:
public class MyCache implements Serializable {
#QuerySqlField(index = true, name = "id")
private String id;
public MyCache() {
}
public MyCache(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Here is a configuration class
import javax.cache.configuration.Factory;
import javax.cache.configuration.FactoryBuilder;
#Configuration
public class ServiceConfig {
// no problems here
#Bean
#ConfigurationProperties(prefix = "postgre")
DataSource dataSource() {
return DataSourceBuilder
.create()
.build();
}
#Bean
public Ignite igniteInstance(IgniteConfiguration igniteConfiguration) {
return Ignition.start(igniteConfiguration);
}
#Bean
public IgniteConfiguration igniteCfg () {
// some other stuff here
IgniteConfiguration cfg = new IgniteConfiguration();
cfg.setClientMode(true);
CacheConfiguration myCacheConfiguration = new CacheConfiguration("MY_CACHE")
.setIndexedTypes(String.class, MyCache.class)
.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL)
.setReadThrough(true)
.setReadThrough(true)
.setCacheStoreSessionListenerFactories(new MyCacheStoreSessionListenerFactory(dataSource))
.setCacheStoreFactory(FactoryBuilder.factoryOf(MyCacheStore.class));
cfg.setCacheConfiguration(myCacheConfiguration);
return cfg;
}
private static class MyCacheStoreSessionListenerFactory implements Factory {
DataSource dataSource;
MyCacheStoreSessionListenerFactory(DataSource dataSource) {
this.dataSource = dataSource;
}
#Override
public CacheStoreSessionListener create() {
// Data Source
CacheJdbcStoreSessionListener listener = new CacheJdbcStoreSessionListener();
listener.setDataSource(dataSource);
return listener;
}
}
}
And this is what I get in logs:
...
Caused by: class org.apache.ignite.IgniteCheckedException: Failed to validate cache configuration
(make sure all objects in cache configuration are serializable): MyCache
at org.apache.ignite.internal.processors.cache.GridCacheProcessor$11.applyx(GridCacheProcessor.java:4766)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor$11.applyx(GridCacheProcessor.java:4743)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.withBinaryContext(GridCacheProcessor.java:4788)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.cloneCheckSerializable(GridCacheProcessor.java:4743)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.addCacheOnJoin(GridCacheProcessor.java:818)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.addCacheOnJoinFromConfig(GridCacheProcessor.java:891)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.startCachesOnStart(GridCacheProcessor.java:753)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor.start(GridCacheProcessor.java:795)
at org.apache.ignite.internal.IgniteKernal.startProcessor(IgniteKernal.java:1700)
... 77 more
Caused by: class org.apache.ignite.IgniteCheckedException: Failed to serialize object: CacheConfiguration [name=MyCache, grpName=null, memPlcName=null, storeConcurrentLoadAllThreshold=5, rebalancePoolSize=2, rebalanceTimeout=10000, evictPlc=null, evictPlcFactory=null, onheapCache=false, sqlOnheapCache=false, sqlOnheapCacheMaxSize=0, evictFilter=null, eagerTtl=true, dfltLockTimeout=0, nearCfg=null, writeSync=null, storeFactory=javax.cache.configuration.FactoryBuilder$ClassFactory#d87782a1, storeKeepBinary=false, loadPrevVal=false, aff=null, cacheMode=PARTITIONED, atomicityMode=TRANSACTIONAL, backups=0, invalidate=false, tmLookupClsName=null, rebalanceMode=ASYNC, rebalanceOrder=0, rebalanceBatchSize=524288, rebalanceBatchesPrefetchCnt=2, maxConcurrentAsyncOps=500, sqlIdxMaxInlineSize=-1, writeBehindEnabled=false, writeBehindFlushSize=10240, writeBehindFlushFreq=5000, writeBehindFlushThreadCnt=1, writeBehindBatchSize=512, writeBehindCoalescing=true, maxQryIterCnt=1024, affMapper=null, rebalanceDelay=0, rebalanceThrottle=0, interceptor=null, longQryWarnTimeout=3000, qryDetailMetricsSz=0, readFromBackup=true, nodeFilter=null, sqlSchema=null, sqlEscapeAll=false, cpOnRead=true, topValidator=null, partLossPlc=IGNORE, qryParallelism=1, evtsDisabled=false, encryptionEnabled=false]
at org.apache.ignite.marshaller.jdk.JdkMarshaller.marshal0(JdkMarshaller.java:103)
at org.apache.ignite.marshaller.AbstractNodeNameAwareMarshaller.marshal(AbstractNodeNameAwareMarshaller.java:70)
at org.apache.ignite.marshaller.jdk.JdkMarshaller.marshal0(JdkMarshaller.java:117)
at org.apache.ignite.marshaller.AbstractNodeNameAwareMarshaller.marshal(AbstractNodeNameAwareMarshaller.java:58)
at org.apache.ignite.internal.util.IgniteUtils.marshal(IgniteUtils.java:10250)
at org.apache.ignite.internal.processors.cache.GridCacheProcessor$11.applyx(GridCacheProcessor.java:4762)
... 85 more
Caused by: java.io.NotSerializableException: com.zaxxer.hikari.HikariDataSource
at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185)
at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
I have read all official documentation about it and examined many other examples, but can't make it run.
HikariCP is the most popular connection pool library, I can't understand why Ignite throws an exception about not being able to serialize DataSource.
Any advice or idea would be appreciated, thank you!
Since your Cache Store is not serializable, you should not use Factory.factoryOf (which is a no-op wrapper) but instead supply a real serializable factory implementation which will acquire local HikariCP on node and then construct the Cache Store.

EntityManagerFactory closed after context reloaded with #DirtiesContext

I have a Spring Boot app which uses JMS to connect to a queue and listen for incoming messages. In the app I have an integration test which sends some messages to a queue, then makes sure that the things that are supposed to happen when the listener picks up a new message actually happen.
I have annotated my test class with #DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
to ensure my database is clean after each test. Each test passes when it is run in isolation. However when running them all together after the first test passes successfully the next test fails with the exception below when the code under test attempts to save an entity to the database:
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: EntityManagerFactory is closed
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:431) ~[spring-orm-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373) ~[spring-tx-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:447) ~[spring-tx-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:277) ~[spring-tx-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at com.sun.proxy.$Proxy95.handleWorkflowEvent(Unknown Source) ~[na:na]
at com.mottmac.processflow.infra.jms.EventListener.onWorkflowEvent(EventListener.java:51) ~[classes/:na]
at com.mottmac.processflow.infra.jms.EventListener.onMessage(EventListener.java:61) ~[classes/:na]
at org.apache.activemq.ActiveMQMessageConsumer.dispatch(ActiveMQMessageConsumer.java:1401) [activemq-client-5.14.3.jar:5.14.3]
at org.apache.activemq.ActiveMQSessionExecutor.dispatch(ActiveMQSessionExecutor.java:131) [activemq-client-5.14.3.jar:5.14.3]
at org.apache.activemq.ActiveMQSessionExecutor.iterate(ActiveMQSessionExecutor.java:202) [activemq-client-5.14.3.jar:5.14.3]
at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:133) [activemq-client-5.14.3.jar:5.14.3]
at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:48) [activemq-client-5.14.3.jar:5.14.3]
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_77]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_77]
at java.lang.Thread.run(Unknown Source) [na:1.8.0_77]
Caused by: java.lang.IllegalStateException: EntityManagerFactory is closed
at org.hibernate.jpa.internal.EntityManagerFactoryImpl.validateNotClosed(EntityManagerFactoryImpl.java:367) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.jpa.internal.EntityManagerFactoryImpl.internalCreateEntityManager(EntityManagerFactoryImpl.java:316) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.jpa.internal.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:286) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]
at org.springframework.orm.jpa.JpaTransactionManager.createEntityManagerForTransaction(JpaTransactionManager.java:449) ~[spring-orm-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:369) ~[spring-orm-4.3.6.RELEASE.jar:4.3.6.RELEASE]
... 17 common frames omitted
My test class:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { TestGovernance.class })
#DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
public class ActivitiIntegrationTest
{
private static final String TEST_PROCESS_KEY = "oneTaskProcess";
private static final String FIRST_TASK_KEY = "theTask";
private static final String NEXT_TASK_KEY = "nextTask";
#Autowired
private JmsTemplate jms;
#Autowired
private WorkflowEventRepository eventRepository;
#Autowired
private TaskService taskService;
#Test
public void workFlowEventForRunningTaskMovesItToTheNextStage() throws InterruptedException
{
sendMessageToCreateNewInstanceOfProcess(TEST_PROCESS_KEY);
Task activeTask = getActiveTask();
assertThat(activeTask.getTaskDefinitionKey(), is(FIRST_TASK_KEY));
sendMessageToUpdateExistingTask(activeTask.getProcessInstanceId(), FIRST_TASK_KEY);
Task nextTask = getActiveTask();
assertThat(nextTask.getTaskDefinitionKey(), is(NEXT_TASK_KEY));
}
#Test
public void newWorkflowEventIsSavedToDatabaseAndKicksOffTask() throws InterruptedException
{
sendMessageToCreateNewInstanceOfProcess(TEST_PROCESS_KEY);
assertThat(eventRepository.findAll(), hasSize(1));
}
#Test
public void newWorkflowEventKicksOffTask() throws InterruptedException
{
sendMessageToCreateNewInstanceOfProcess(TEST_PROCESS_KEY);
Task activeTask = getActiveTask();
assertThat(activeTask.getTaskDefinitionKey(), is(FIRST_TASK_KEY));
}
private void sendMessageToUpdateExistingTask(String processId, String event) throws InterruptedException
{
WorkflowEvent message = new WorkflowEvent();
message.setRaisedDt(ZonedDateTime.now());
message.setEvent(event);
// Existing
message.setIdWorkflowInstance(processId);
jms.convertAndSend("workflow", message);
Thread.sleep(5000);
}
private void sendMessageToCreateNewInstanceOfProcess(String event) throws InterruptedException
{
WorkflowEvent message = new WorkflowEvent();
message.setRaisedDt(ZonedDateTime.now());
message.setEvent(event);
jms.convertAndSend("workflow", message);
Thread.sleep(5000);
}
private Task getActiveTask()
{
// For some reason the tasks in the task service are hanging around even
// though the context is being reloaded. This means we have to get the
// ID of the only task in the database (since it has been cleaned
// properly) and use it to look up the task.
WorkflowEvent workflowEvent = eventRepository.findAll().get(0);
Task activeTask = taskService.createTaskQuery().processInstanceId(workflowEvent.getIdWorkflowInstance().toString()).singleResult();
return activeTask;
}
}
The method that throws the exception in the application (repository is just a standard Spring Data CrudRepository):
#Override
#Transactional
public void handleWorkflowEvent(WorkflowEvent event)
{
try
{
logger.info("Handling workflow event[{}]", event);
// Exception is thrown here:
repository.save(event);
logger.info("Saved event to the database [{}]", event);
if(event.getIdWorkflowInstance() == null)
{
String newWorkflow = engine.newWorkflow(event.getEvent(), event.getVariables());
event.setIdWorkflowInstance(newWorkflow);
}
else
{
engine.moveToNextStage(event.getIdWorkflowInstance(), event.getEvent(), event.getVariables());
}
}
catch (Exception e)
{
logger.error("Error while handling workflow event:" , e);
}
}
My test configuration class:
#SpringBootApplication
#EnableJms
#TestConfiguration
public class TestGovernance
{
private static final String WORKFLOW_QUEUE_NAME = "workflow";
#Bean
public ConnectionFactory connectionFactory()
{
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
return connectionFactory;
}
#Bean
public EventListenerJmsConnection connection(ConnectionFactory connectionFactory) throws NamingException, JMSException
{
// Look up ConnectionFactory and Queue
Destination destination = new ActiveMQQueue(WORKFLOW_QUEUE_NAME);
// Create Connection
Connection connection = connectionFactory.createConnection();
Session listenerSession = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
MessageConsumer receiver = listenerSession.createConsumer(destination);
EventListenerJmsConnection eventListenerConfig = new EventListenerJmsConnection(receiver, connection);
return eventListenerConfig;
}
}
The JMS message listener (not sure if that will help):
/**
* Provides an endpoint which will listen for new JMS messages carrying
* {#link WorkflowEvent} objects.
*/
#Service
public class EventListener implements MessageListener
{
Logger logger = LoggerFactory.getLogger(EventListener.class);
private WorkflowEventHandler eventHandler;
private MessageConverter messageConverter;
private EventListenerJmsConnection listenerConnection;
#Autowired
public EventListener(EventListenerJmsConnection listenerConnection, WorkflowEventHandler eventHandler, MessageConverter messageConverter)
{
this.eventHandler = eventHandler;
this.messageConverter = messageConverter;
this.listenerConnection = listenerConnection;
}
#PostConstruct
public void setUpConnection() throws NamingException, JMSException
{
listenerConnection.setMessageListener(this);
listenerConnection.start();
}
private void onWorkflowEvent(WorkflowEvent event)
{
logger.info("Recieved new workflow event [{}]", event);
eventHandler.handleWorkflowEvent(event);
}
#Override
public void onMessage(Message message)
{
try
{
message.acknowledge();
WorkflowEvent fromMessage = (WorkflowEvent) messageConverter.fromMessage(message);
onWorkflowEvent((WorkflowEvent) fromMessage);
}
catch (Exception e)
{
logger.error("Error: ", e);
}
}
}
I've tried adding #Transactional' to the test methods and removing it from the code under test and various combinations with no success. I've also tried adding various test execution listeners and I still can't get it to work. If I remove the#DirtiesContext` then the exception goes away and all the tests run without exception (they do however fail with assertion errors as I would expect).
Any help would be greatly appreciated. My searches so far haven't turned up anything, everything suggests that #DirtiesContext should work.
Using #DirtiesContext for this is a terrible idea (imho) what you should do is make your tests #Transactional. I would also suggest to remove the Thread.sleep and use something like awaitility instead.
In theory when you execute a query all pending changes should be committed so you could use awaitility to check for at most 6 seconds to see if something has been persisted in the database. If that doesn't work you can try adding a flush before the query.
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { TestGovernance.class })
#Transactional
public class ActivitiIntegrationTest {
private static final String TEST_PROCESS_KEY = "oneTaskProcess";
private static final String FIRST_TASK_KEY = "theTask";
private static final String NEXT_TASK_KEY = "nextTask";
#Autowired
private JmsTemplate jms;
#Autowired
private WorkflowEventRepository eventRepository;
#Autowired
private TaskService taskService;
#Autowired
private EntityManager em;
#Test
public void workFlowEventForRunningTaskMovesItToTheNextStage() throws InterruptedException
{
sendMessageToCreateNewInstanceOfProcess(TEST_PROCESS_KEY);
await().atMost(6, SECONDS).until(getActiveTask() != null);
Task activeTask = getActiveTask());
assertThat(activeTask.getTaskDefinitionKey(), is(FIRST_TASK_KEY));
sendMessageToUpdateExistingTask(activeTask.getProcessInstanceId(), FIRST_TASK_KEY);
Task nextTask = getActiveTask();
assertThat(nextTask.getTaskDefinitionKey(), is(NEXT_TASK_KEY));
}
private Task getActiveTask()
{
em.flush(); // simulate a commit
// For some reason the tasks in the task service are hanging around even
// though the context is being reloaded. This means we have to get the
// ID of the only task in the database (since it has been cleaned
// properly) and use it to look up the task.
WorkflowEvent workflowEvent = eventRepository.findAll().get(0);
Task activeTask = taskService.createTaskQuery().processInstanceId(workflowEvent.getIdWorkflowInstance().toString()).singleResult();
return activeTask;
}
}
You might need / want to polish your getActiveTask a little to be able to return null or maybe this change makes it even behave like you expected it to do.
I just did a single method the others you can probably figure out yourself. Your gain with this approach is probably 2 fold, 1 it will not wait for 5 seconds anymore but less and you don't have to reload your whole application between tests. Both of which should make your tests faster.

Java SpringMVC autowired BeanCreationException

I am using Spring MVC on Tomcat. When I try to start tomcat I get this exception:
WARNING: Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.springframework.web.bind.annotation.RequestMapping.path()[Ljava/lang/String;
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:667)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:539)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:493)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1231)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1034)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4913)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5200)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoSuchMethodError: org.springframework.web.bind.annotation.RequestMapping.path()[Ljava/lang/String;
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.createRequestMappingInfo(RequestMappingHandlerMapping.java:257)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.createRequestMappingInfo(RequestMappingHandlerMapping.java:214)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.getMappingForMethod(RequestMappingHandlerMapping.java:193)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.getMappingForMethod(RequestMappingHandlerMapping.java:53)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$1.matches(AbstractHandlerMethodMapping.java:210)
at org.springframework.web.method.HandlerMethodSelector$1.doWith(HandlerMethodSelector.java:62)
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:524)
at org.springframework.web.method.HandlerMethodSelector.selectMethods(HandlerMethodSelector.java:57)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(AbstractHandlerMethodMapping.java:207)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods(AbstractHandlerMethodMapping.java:182)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.afterPropertiesSet(AbstractHandlerMethodMapping.java:163)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.afterPropertiesSet(RequestMappingHandlerMapping.java:133)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 25 more
SRC:
Controller:
#Controller
public class IndexController {
private final Logger logger = LoggerFactory.getLogger(IndexController.class);
private final TaskStorage storage;
#Autowired
public IndexController(TaskStorage storage) {
this.storage = storage;
}
#RequestMapping(value = "/", method = RequestMethod.GET)
public String index(Map<String, Object> model) {
model.put("tasks", storage.getAllTasks());
return "index";
}
...
Service:
#Service
public class TaskStorage {
public TaskStorage() {
}
public void gitCreateBranch(String key, String branchName) {
ServiceManager.get().git.createBranch(branchName);
}
...
Service manager:
public class ServiceManager {
private static volatile ServiceManager instance;
public final JiraService jira;
public final GitService git;
public final JenkinsService jenkins;
#Autowired
private ServiceConfiguration conf;
private ServiceManager() {
this.jira = new JiraServiceSynchronousImpl(conf);
this.git = new JGitGitServiceImpl(conf);
this.jenkins = new SimpleJenkinsServiceImpl(conf);
}
public static ServiceManager get() {
if (instance == null) {
synchronized (ServiceManager.class) {
if (instance == null) {
instance = new ServiceManager();
}
}
}
return instance;
}
Service configuration:
package com.etnetera.dev.storage;
#Component
public class ServiceConfiguration {
public final JiraConfiguration jira;
public final GitConfiguration git;
public final JenkinsConfiguration jenkins;
public final JnpConfiguration jnp;
public ServiceConfiguration() {
this(null, null, null, null);
}
#Autowired
public ServiceConfiguration(JiraConfiguration jira, GitConfiguration git,
JenkinsConfiguration jenkins, JnpConfiguration jnp) {
super();
this.jira = jira;
this.git = git;
this.jenkins = jenkins;
this.jnp = jnp;
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigIn() {
return new PropertySourcesPlaceholderConfigurer();
}
#Component
public static class JenkinsConfiguration {
public final String url;
public final String defaultJobName;
public final String defaultJobNameParam;
public final String userName;
public final String password;
public JenkinsConfiguration() {
this(null, null, null, null, null);
}
#Autowired
public JenkinsConfiguration(
#Value("${jenkins.url}") String url,
#Value("${jenkins.defaultJobName}") String defaultJobName,
#Value("${jenkins.defaultJobNameParam}") String defaultJobNameParam,
#Value("${jenkins.userName}") String userName,
#Value("${jenkins.password}") String password) {
super();
this.url = url;
this.defaultJobName = defaultJobName;
this.defaultJobNameParam = defaultJobNameParam;
this.userName = userName;
this.password = password;
}
public String getJobUrl(String jobName) {
return getJobUrl(jobName, null);
}
}
#Component
public static class GitConfiguration {
public final Git git;
public final String localRepoPath;
public GitConfiguration() throws IOException {
this(null);
}
#Autowired
public GitConfiguration(
#Value("${git.localRepoPath}") String localRepoPath)
throws IOException {
this.git = new Git(new FileRepository(localRepoPath + "/.git"));
this.localRepoPath = localRepoPath;
}
}
#Component
public static class JiraConfiguration {
public final JiraRestClient client;
public final SearchRestClient searchClient;
public final IssueRestClient issueClient;
public final String jiraUser;
public JiraConfiguration() throws URISyntaxException {
this(null, null, null);
}
#Autowired
public JiraConfiguration(#Value("${jira.userName}") String userName,
#Value("${jira.pass}") String pass,
#Value("${jira.url}") String url) throws URISyntaxException {
this.jiraUser = userName;
JiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
URI uri = new URI(url);
this.client = factory.createWithBasicHttpAuthentication(uri,
userName, pass);
this.searchClient = client.getSearchClient();
this.issueClient = client.getIssueClient();
}
}
#Component
public static class JnpConfiguration {
public final Map<String, String> serviceUrls;
public final String defaultServiceUrl;
public final String defaultProjectName;
public JnpConfiguration() {
this(null, null);
}
#Autowired
public JnpConfiguration(
#Value("${jnp.defaultServer}") String defaultServiceUrl,
#Value("${jnp.defaultProjectName}") String defaultProjectName) {
super();
this.serviceUrls = null;
this.defaultServiceUrl = defaultServiceUrl;
this.defaultProjectName = defaultProjectName;
}
}
}
Web config:
package com.etnetera.dev.config;
#EnableWebMvc
#Configuration
#ComponentScan({ "com.etnetera.dev.web" })
public class SpringWebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
Root config:
package com.etnetera.dev.config;
#Configuration
#ComponentScan({ "com.etnetera.dev.storage" })
#PropertySource("classpath:service.config.properties")
public class SpringRootConfig {
}
Properties file is located in
/src/main/resources
Gradle script:
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'eclipse-wtp'
//apply plugin: 'jetty'
apply plugin: 'org.akhikhl.gretty'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.akhikhl.gretty:gretty:+'
}
}
gretty {
port = 8081
contextPath = 'spring4'
servletContainer = 'jetty9'
}
// JDK 7
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
maven { url = 'https://maven.atlassian.com/content/repositories/atlassian-public/'}
mavenLocal()
mavenCentral()
}
dependencies {
compile(
['org.eclipse.jgit:org.eclipse.jgit:4.0.1.201506240215-r'],
['com.atlassian.jira:jira-rest-java-client:2.0.0-m2'],
['javax.servlet:jstl:1.2'],
['org.springframework:spring-webmvc:4.2.1.RELEASE'],
['org.springframework:spring-aspects:4.2.1.RELEASE'],
['ch.qos.logback:logback-classic:1.1.3'])
//include in compile only, exclude in the war
providedCompile 'javax.servlet:servlet-api:2.5'
}
//For Eclipse IDE only
eclipse {
wtp {
component {
//define context path, default to project folder name
contextPath = 'spring4'
}
}
}
I have linked Gradle dependencies in Eclipse project and Web App Libraries which seems to be same. Both have Spring in version 4.2.1.RELEASE
There are no Spring libs in Tomcat8/lib
In Eclipse Tomcat has linked Spring libs in version 4.2.1.RELEASE (found under Tomcat 8 overview -> launch configuration -> source)
I am kinda newbie with Spring and I have tried googling solutions for few hours with no luck. Thanks for any help.
I have resolved the issue by cleaning project, cleaning Tomcat and cleaning Tomcat Work dir.
Anyway I had another issue with my code:
public class ServiceManager {
private static volatile ServiceManager instance;
public final JiraService jira;
public final GitService git;
public final JenkinsService jenkins;
#Autowired
private ServiceConfiguration conf;
private ServiceManager() {
this.jira = new JiraServiceSynchronousImpl(conf);
this.git = new JGitGitServiceImpl(conf);
this.jenkins = new SimpleJenkinsServiceImpl(conf);
}
It is wrong because Spring doesn't autowire field to use it in constructor. I fixed it with this:
public class ServiceManager {
private static volatile ServiceManager instance;
public final JiraService jira;
public final GitService git;
public final JenkinsService jenkins;
#Autowired
private ServiceManager(ServiceConfiguration conf) {
this.jira = new JiraServiceSynchronousImpl(conf);
this.git = new JGitGitServiceImpl(conf);
this.jenkins = new SimpleJenkinsServiceImpl(conf);
}
I highly suspect that you are having different versions of dependencies spring-web and spring-webmvc. Check your pom.xml and unsure you are using the very same version for all your spring dependencies and try again
See this part in your stack trace:
Caused by: java.lang.NoSuchMethodError: org.springframework.web.bind.annotation.RequestMapping.path()[Ljava/lang/String;
Make sure you don't have multiple jar files with different versions of Spring in your pom.xml.

JSON serialization with simple spring memcached

I'm unable to use simple-spring-memcached with default serialization type set to JSON. The error I get is:
java.lang.IllegalArgumentException: Cannot use JSON serialization because dedicated cache transcoder is null!
at com.google.code.ssm.CacheImpl.set(CacheImpl.java:290) ~[simple-spring-memcached-3.5.0.jar:na]
at com.google.code.ssm.CacheImpl.set(CacheImpl.java:125) ~[simple-spring-memcached-3.5.0.jar:na]
at com.google.code.ssm.PrefixedCacheImpl.set(PrefixedCacheImpl.java:130) ~[simple-spring-memcached-3.5.0.jar:na]
at com.google.code.ssm.spring.SSMCache.put(SSMCache.java:159) ~[spring-cache-3.5.0.jar:na]
at org.springframework.cache.interceptor.CacheAspectSupport.update(CacheAspectSupport.java:351) [spring-context-3.2.9.RELEASE.jar:3.2.9.RELEASE]
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:214) [spring-context-3.2.9.RELEASE.jar:3.2.9.RELEASE]
at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:66) [spring-context-3.2.9.RELEASE.jar:3.2.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) [spring-aop-3.2.9.RELEASE.jar:3.2.9.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) [spring-aop-3.2.9.RELEASE.jar:3.2.9.RELEASE]
at com.sun.proxy.$Proxy105.findByValue(Unknown Source) [na:na]
My Configuration is :
#Configuration()
#EnableAspectJAutoProxy
#EnableCaching
public class SimpleSpringCacheConfig {
#Autowired
private Environment env;
private static final String DEFAULT_MEMCACHED_HOST = "127.0.0.1:11211";
private static final Integer DEFAULT_MEMCACHED_TTL_SECONDS = 3600;
private static final Integer DEFAULT_MEMCACHED_TIMEOUT_MILLIS = 500;
private static final String PROPERTY_MEMCACHED_HOSTS = "service.caching.memcached.hosts";
private static final String PROPERTY_DEFAULT_TTL_SECONDS="service.caching.default.ttl.seconds";
private static final Logger log = LoggerFactory.getLogger(SimpleSpringCacheConfig.class);
//reference config on https://code.google.com/p/simple-spring-memcached/wiki/Getting_Started#Spring_3.1_Cache_Integration
#Bean
public CacheManager cacheManager() throws Exception
{
MemcacheClientFactoryImpl cacheClientFactory = new MemcacheClientFactoryImpl();
AddressProvider addressProvider = new DefaultAddressProvider(env.getProperty(PROPERTY_MEMCACHED_HOSTS, DEFAULT_MEMCACHED_HOST));
CacheConfiguration cacheConfiguration = new CacheConfiguration();
cacheConfiguration.setKeyPrefixSeparator("_");
cacheConfiguration.setUseNameAsKeyPrefix(true);
cacheConfiguration.setConsistentHashing(true);
cacheConfiguration.setOperationTimeout(DEFAULT_MEMCACHED_TIMEOUT_MILLIS);
CacheFactory cacheFactory = new CacheFactory();
cacheFactory.setCacheName("simpleMemcachedCache");
cacheFactory.setCacheClientFactory(cacheClientFactory);
cacheFactory.setAddressProvider(addressProvider);
cacheFactory.setConfiguration(cacheConfiguration);
cacheFactory.setDefaultSerializationType(SerializationType.JSON);
Cache object = cacheFactory.getObject();
int ttl = env.getProperty(PROPERTY_DEFAULT_TTL_SECONDS, Integer.class, DEFAULT_MEMCACHED_TTL_SECONDS);
//#CacheEvict(..., "allEntries" = true) won't work because allowClear is false,
//so we won't flush accidentally all entries from memcached instance..
SSMCache ssmCache = new SSMCache(object, ttl, false);
ArrayList<SSMCache> ssmCaches = new ArrayList<SSMCache>();
ssmCaches.add(0, ssmCache);
SSMCacheManager ssmCacheManager = new SSMCacheManager();
ssmCacheManager.setCaches(ssmCaches);
return ssmCacheManager;
}
}
According to the guide here https://code.google.com/p/simple-spring-memcached/wiki/Getting_Started#Serialization it doesn't seem necessary to define a custom transcoder. What could I be doing wrong?
I'm using the following versions..
spring-cache: v3.5.0
spymemcached-provider: v3.5.0
spring: v3.2.8.RELEASE
There is no requirement to define JSON transcoder if you use SSM xml configuration. In your case you need to fully initialize CacheFactory object so invoke:
cacheFactory.afterPropertiesSet();
just before
Cache object = cacheFactory.getObject();

Categories