Session destroy event with JTA Transaction - spring

I am working on JBOSS application and I am facing issue for loggin sessionTimeout event
I want to make JTA transaction once the session is expire.
My code is as follow
spring.xml
...
<bean
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
id="transactionManager">
<property name="sessionFactory" >
<ref local="sessionFactory" />
</property>
</bean>
<bean id="msg" class="com.Message">
....
</bean>
...
web.xml
...
<listener>
<listener-class>
com.demo.MySessionListener
</listener-class>
</listener>
...
Class File
public class MySessionListener implements HttpSessionListener{
public void sessionCreated(HttpSessionEvent event) {
}
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(session.getServletContext());
Message msg = (Message)ctx.getBean("msg");
msg.save(); // throws error org.springframework.transaction.CannotCreateTransactionException
}
}
I found that All the JTA operation must be done in session, But in this case how can I achieve this ? Because I want to perform JTA transaction because of the session expiration event.
Let me know if anyone have solve this problem even before.
Thanks
StackTrace
at org.jboss.web.tomcat.service.session.ClusteredSession.removeAttributeInternal(ClusteredSession.java:1292)
at org.jboss.web.tomcat.service.session.ClusteredSession.expire(ClusteredSession.java:844)
at org.jboss.web.tomcat.service.session.ClusteredSession.expire(ClusteredSession.java:740)
at org.jboss.web.tomcat.service.session.ClusteredSession.isValid(ClusteredSession.java:720)
at org.jboss.web.tomcat.service.session.ClusteredSession.isValid(ClusteredSession.java:685)
at org.jboss.web.tomcat.service.session.JBossCacheManager.processExpires(JBossCacheManager.java:1236)
at org.jboss.web.tomcat.service.session.JBossManager.backgroundProcess(JBossManager.java:817)
at org.jboss.web.tomcat.service.session.JBossCacheManager.backgroundProcess(JBossCacheManager.java:1185)
at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1270)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1555)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1564)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1564)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1544)
at java.lang.Thread.run(Thread.java:619)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'workContext': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request? If you are actually operating within a web request and still receive this message,your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:33)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.getTarget(Cglib2AopProxy.java:661)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:611)
at com.ideas.carparkpro.commons.bean.CproWorkContext$$EnhancerByCGLIB$$ef8de176.getDataSource()
at com.ideas.carparkpro.core.util.UserRoutingDataSource.determineCurrentLookupKey(UserRoutingDataSource.java:103)
... 30 more
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request? If you are actually operating within a web request and still receive this message,your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:102)
at org.springframework.web.context.request.SessionScope.get(SessionScope.java:88)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:285)
... 36 more

Related

Error Casting Spring's JndiObjectFactoryBean to ConnectionFactory for Solace-MQ JMS

I have a good working XML configuration for Camel Context that uses JNDI with Spring
Later Solace.JndiObjectFactoryBean gets used as connectionFactory
<bean id="Solace.JmsComponent" class=" on">
<property name="connectionFactory" ref="Solace.JndiObjectFactoryBean" />
<property name="destinationResolver" ref="Solace.JndiDestinationResolver" />
</bean>
I am trying to convert this into a Java class that extends from org.apache.camel.spring.javaconfig.CamelConfiguration. But there is one problem. When I try to set a connection factory on JMS component
component.setConnectionFactory(getJndiObjectFactoryBean()); getJndiObjectFactoryBean(),
I get a compile time exception :
The method setConnectionFactory(ConnectionFactory) in the type JmsComponent
is not applicable for the arguments (JndiObjectFactoryBean)
But when I try to cast JndiObjectFactoryBean returned from getJndiObjectFactoryBean explicitly to SolConnectionFactory, I get a runtime error
016-02-05 17:39:09,234|[localhost-startStop-1]|[]|[]|[ERROR] web.context.ContextLoader [line:307] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getJMSConfiguration' defined in class path resource [com//camel
/CamelRoutesConfig.class]: Instantiation of bean failed; nested exception is org
.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.apache.camel.component.jms.JmsConfiguration com.camel.CamelRoutesConfig.getJMSConfiguration()] threw exception; nested exception is java.lang.ClassCastException: org.springframework.jndi.JndiObjectFactoryBean$$EnhancerByCG
LIB$$18b94f95 cannot be cast to com.solacesystems.jms.SolConnectionFactory
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsi
ngFactoryMethod(ConstructorResolver.java:581)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1029)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
.createBeanInstance(AbstractAutowireCapableBeanFactory.java:925)
I believe do have have requisite jars in the class path. sol-common-x.y.z.jar, sol-jcsmp-x.y.z.jar, sol-jms-x.y.z.jar
A JndiObjectFactoryBean cannot be casted into a ConnectionFactory.
There are two options:
Use JndiObjectFactoryBean.getObject() in the JndiObjectFactoryBean that's returned by your getJndiObjectFactoryBean() method.
Get Spring to provide the ConnectionFactory.
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
ConnectionFactory connectionFactory = (ConnectionFactory) context.getBean("Solace.JndiObjectFactoryBean");
We faced a simular situation when porting a working Spring XML configuration (used by Apache Camel to read from a Weblogic JMS Server queue) to a Spring-Boot favoured Java configuration.
jmsConfiguration.setConnectionFactory( (javax.jms.ConnectionFactory)getJndiFactoryBean().getObject());
Above code did the trick to emulate
<bean id="jmsConfiguration" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="jndiFactoryBean"/>
<property name="destinationResolver" ref="jndiDestinationResolver"/>
</bean>
(Unclear what Spring XML does extra under the cover though, since it's not as simple as setting the jndiFactoryBean on the jmsConfiguration)
In case you are using the getObject() approach make sure you call afterPropertiesSet() before you use getObject()
org.springframework.jndi.JndiObjectFactoryBean cf = new org.springframework.jndi.JndiObjectFactoryBean();
JndiTemplate jndiTemplate = new org.springframework.jndi.JndiTemplate();
Properties environment = new Properties();
environment.setProperty("java.naming.factory.initial", "com.xxx"); //initial context
environment.setProperty("java.naming.provider.url", "xxx://xxx"); //url
jndiTemplate.setEnvironment(environment);
cf.setJndiTemplate(jndiTemplate);
cf.setJndiName("XXX");
//System.out.println(cf.getObject()); //null
cf.afterPropertiesSet();
//System.out.println(cf.getObject()); //now has the value
org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter adapter = new org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter();
adapter.setTargetConnectionFactory((ConnectionFactory) cf.getObject());

Exported service not injecting in my bundle in Spring Dynamic Modules

I am using Spring Dynamic Modules for the first time. I have tried to expose a service (simple listofValuesDAO Bean) through a bundle and am trying to inject it in another bundle to use the bean.
Below is configuration tag in osgi-context.xml of Bundle1 through which service was exposed:
<osgi:service ref="listOfValuesDAO" auto-export="interfaces"/>
and I am trying to fetch it in Bundle2 through below tag in osgi-context.xml:
<osgi:reference id="listOfValuesDAO" interface="com.dao.IListOfValuesDAO" />
The issue is that when I try to inject it in my bean in Bundle2 using below configuration:
<bean id="exportServiceImpl" class="com.service.impl.ExportServiceImpl">
<property name="listOfValuesDAO" ref="listOfValuesDAO"/>
</bean>
System throws below exception:
Exception in thread "SpringOsgiExtenderThread-85"org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'exportServiceImpl' defined in URL [bundle://325.16:0/META-INF/spring/module-context.xml]:
Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'listOfValuesDAO' of bean class [com.service.impl.ExportServiceImpl]:
Bean property 'listOfValuesDAO' is not writable or has an invalid setter method. Did you mean 'listOfValuesDao'?
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1396)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
Below is property in my ExportServiceImpl Class:
public class ExportServiceImpl implements IExportService {
IListOfValuesDAO listOfValuesDao;
public void setListOfValuesDao(IListOfValuesDAO listOfValuesDao) {
this.listOfValuesDao = listOfValuesDao;
}
public IListOfValuesDAO getListOfValuesDao() {
return listOfValuesDao;
}
}
Could someone please help me in resolving this issue?
It seems to be a problem with case inconsistency: listOfValuesDao and listOfValuesDAO are different names.
You use the first version in the Service, and the second in the XML bean definition. Try:
<bean id="exportServiceImpl" class="com.service.impl.ExportServiceImpl">
<property name="listOfValuesDao" ref="listOfValuesDao"/>
</bean>

Spring Transactions not rolling back on Exception (Oracle JNDI datasource)

I am using annotation based transactions in a Spring MVC 3.1 project, and my transactions are not being rolled back when an exception is thrown.
Here is my Service code
#Service
public class ImportService {
#Autowired
ImportMapper importMapper;
#Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED, rollbackFor=Throwable.class)
public void processImport() throws ServiceException, DatabaseException {
iImport import = new Import();
createImport(import);
throw new ServiceException("");
}
#Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED, rollbackFor=Throwable.class)
private void createImport(Import import) throws DatabaseException {
try {
importMapper.createImport(eventImport);
} catch (Exception e) {
throw new DatabaseException(e);
}
}
So, hopefully, the createImport method should be rolled back after the exception is thrown. But unfortunately it's not.
I am defining my datasource in the server context.xml
<Resource name="datasource.import" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="user" password="password" driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:#INFO" />
And I'm looking it up with JNDI:
<jee:jndi-lookup id="dataSource" jndi-name="datasource.import"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven />
I'm using an Oracle database, and the JDBC spec says that auto commit is true by default. I thought that if I set it to false explicitly that would help, but I can't figure out how to do that.
Is there any way to get rollbacks working, while looking up your Oracle datasource by JNDI.
Please be aware that Spring's transaction management rolls-back transactions only for unchecked exceptions (RuntimeException) by default. If you wish to perform rollback also on checked exceptions, you need to define that.
When using annotations as attribute source, you need to provide rollbackFor attribute with the list of exception classes, which should cause a transaction to be rolled-back (quote from the JavaDoc):
/**
* Defines zero (0) or more exception {#link Class classes}, which must be a
* subclass of {#link Throwable}, indicating which exception types must cause
* a transaction rollback.
* <p>This is the preferred way to construct a rollback rule, matching the
* exception class and subclasses.
* <p>Similar to {#link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(Class clazz)}
*/
Class<? extends Throwable>[] rollbackFor() default {};
It is said that, if a #transational method is invoked by another #transational method, the first one will not work. You may try to remove the first #transational and have a try.

Returning null from factory method in Spring

In my spring configuration file, I have declared one bean which is instantiated via a static factory method. The factory method invokes some remote services. The factory method returns null incase it is not able to access the remote service.
My problem everything goes wrong when the factory method returns null. and The spring initialization fails.
I really want to set the bean to null, if the factory method is not able to invoke the remote service.
Part of my config file is as follows :
<bean id="Helper" class="com.test.Helper">
<constructor-arg ref="myBean" />
</bean>
<bean id="myBean" class="com.test.Factory" factory-method="getBean" />
the getBean() method is as follows:
Factory {
public static Bean getBean() throws Exception{
try {
//Invokes some Remote Services and does some processing
....
....
//returns bean object
}catch(Exception e) {
return null;
}
}
}
Please help me how can I solve this.
Use MethodInvokingFactoryBean like so:
<bean id="myBean"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"><value>com.test.Factory</value></property>
<property name="targetMethod"><value>getBean</value></property>
</bean>
you can return null . but be sure that b'coz of this null value there will be no NullPointerException raised . if it is raising just keep a simple if condition or return the control back from where it come or handle as think is perfect

Catch Spring MVC No Mapping Error

I configured below exception resolver in my web configuration file but I am not sure why it cannot handle
errors such as this 'No Matching error found for servlet request: path '/etc'
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.Exception">
exception
</prop>
</props>
</property>
</bean>
My app relies on Ajax and there are cases that I change the target url based on some user interactions.
My question is, is it possible for me to catch the error in my Spring MVC and forward it to my exception.jsp so that my user wont get
a nasty 404.
SimpleMappingExceptionResolver (and the HandlerExceptionResolver framework in general) will only be invoked to handle exceptions generated by the request handler (i.e. your controllers). If no handler is configured to handle the request, then it won't get that far, and your resolver won't be invoked.
The simplest thing for you to do is to configure a 404-handling page in your web.xml, e.g.
<error-page>
<error-code>404</error-code>
<location>/error.html</location>
</error-page>
You could set up a catch-all #RequestMapping and throw a custom exception if it is executed. Then you could handle that exception with the SimpleMappingExceptionResolver or an #ExceptionHandler method (maybe in a #ControllerAdvice class).
The catch-all controller:
#RequestMapping(value = "/**")
public ModelAndView noHandlerMappingFound() throws HandlerNotFoundException {
throw new HandlerNotFoundException("No handler mapping found.");
}
Here HandlerNotFoundException is your custom exception type.
The controller advice:
#ExceptionHandler(NoSuchEntityException.class)
#ResponseStatus(HttpStatus.NOT_FOUND)
public ModelAndView handleNoSuchEntityException(final HttpServletRequest req, final Exception ex) {
return new ModelAndView("error-page");
}

Resources