I have a Spring MVC service which lets me upload a file. It uses #PreAuthorize from Spring Security to handle access controls on resources. The controller uses Servlet 3 async servlets by use of a Callable.
#PreAuthorize("...")
#RequestMapping(value = "upload", method = RequestMethod.PUT)
public Callable<ResponseEntity> upload(final InputStream inputStream)
{
return new Callable<ResponseEntity>()
{
#Override
public ResponseEntity call() throws Exception
{
...
}
};
}
Somewhere in the service - outside of my code - an exception is being thrown.
An Authentication object was not found in the SecurityContext
The exception appears to be thrown by the cglib generated code for my Spring controller. Here is bulk of the stack trace.
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:339) ~[spring-security-core-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:198) ~[spring-security-core-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:60) ~[spring-security-core-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[spring-aop-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631) ~[spring-aop-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at com.testing.upload.controller.RESTService$$EnhancerByCGLIB$$66a0c4c9.upload(<generated>) ~[spring-core-3.2.4.RELEASE.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_65]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.6.0_65]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_65]
at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_65]
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219) ~[spring-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132) ~[spring-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) ~[spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745) ~[spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686) ~[spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) ~[spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925) ~[spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) ~[spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936) [spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:849) [spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:758) [javax.servlet-3.0.0.v201112011016.jar:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812) [spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848) [javax.servlet-3.0.0.v201112011016.jar:na]
I have updated my web.xml from the instructions at the bottom of this blog post about async support in Spring Security 3.2.
Finally, the error does not always happen. It only appears to happen when I try to upload a large file. This makes me think that it does indeed have something to do with trying to make the controller an async controller.
Versions:
Spring 3.2.4
Spring Security 3.2
cglib 3.1
Java Servlet 3.0
Java 6
Jetty 8
It is possible that the security context is unavailable if the upload is happening in a spawned thread. This is because the security context by default is bound to the parent thread and a new child threads won't know about it.
You can try changing the SecurityContextHolder strategy to InheritableThreadLocal making it available to spawned threads.
You can set this programatically:
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL
Or in the Spring XML config:
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"
value="org.springframework.security.core.context.SecurityContextHolder"/>
<property name="targetMethod" value="setStrategyName"/>
<property name="arguments"><list><value>MODE_INHERITABLETHREADLOCAL</value></list></property>
</bean>
Or you can set an system property when you start your app:
-Dspring.security.strategy=MODE_INHERITABLETHREADLOCAL
Related
Caused by: java.lang.NullPointerException
at org.springframework.boot.actuate.endpoint.DataSourcePublicMetrics.initialize(DataSourcePublicMetrics.java:64) ~[spring-boot-actuator-1.3.2.RELEASE.jar:1.3.2.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_79]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_79]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_79]
at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_79]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:354) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
I disabled the metrics too but no luck
endpoints.enabled=false
endpoints.autoconfig.enabled=false
endpoints.metrics.enabled=false
The DataSourcePublicMetrics bean always gets created, even when the metrics are disabled. This causes a NullPointerException when the database connection is unavailable, causing spring boot not to start.
I am using Hikari datasource and it fails to construct data source object when database is unavailable. Hence NPE from DataSourcePublicMetrics bean. I am able to circumvent the issue creating a Hikari data source that is lazy initialized with database config even when database is unavailable for later use when database becomes available. Not sure why HikariDataSource does not have a constructor for lazy init. It does have a default constructor but database config can't be set using any setter method. This is useful for applications where database is not always necessary to start them up.
public class LazyConnectionDataSource extends HikariDataSource {
public LazyConnectionDataSource(HikariConfig config) {
config.validate();
config.copyState(this);
}
}
I'm trying to create a websocket app using sprint boot and spring messaging. However, when i try to call a function inside one of our service classes, i got the following exception:
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? 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:131) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at com.propspace.intl.psauth.service.PsSessionHandler.getCurrentRequest(PsSessionHandler.java:83) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
at com.propspace.intl.psauth.service.PsTokenService.getTokenValue(PsTokenService.java:167) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
at com.propspace.intl.psauth.service.PsTokenService.getCurrentToken(PsTokenService.java:66) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
at com.propspace.intl.psauth.service.AuthPersistenceService.getCurrentUser(AuthPersistenceService.java:124) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
at com.propspace.intl.psauth.service.AuthPersistenceService$$FastClassBySpringCGLIB$$b662e141.invoke(<generated>) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:121) ~[spring-retry-1.1.1.RELEASE.jar:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at com.propspace.intl.psauth.service.AuthPersistenceService$$EnhancerBySpringCGLIB$$d5176572.getCurrentUser(<generated>) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
at com.propspace.intl.psauth.service.AuthorizationService.getCurrentLoggedInUser(AuthorizationService.java:115) ~[propspace-auth-0.1.6-SNAPSHOT.jar:na]
at com.propspace.intl.common.service.PsNotificationHandler.refindUserId(PsNotificationHandler.java:196) ~[propspace-common-0.1.6-SNAPSHOT.jar:na]
at com.propspace.intl.common.service.PsNotificationHandler.getAllNotificationsOfUser(PsNotificationHandler.java:68) ~[propspace-common-0.1.6-SNAPSHOT.jar:na]
at com.propspace.intl.pushnotifications.controller.NotificationController.greeting(NotificationController.java:47) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_60]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_60]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_60]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_60]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:198) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:116) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:490) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:497) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:87) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:451) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:389) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:135) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_60]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_60]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_60]
After doing some reading on it, it turned out i needed to make this service (bean) a scoped bean, so i did this:
#Scope(value= "request", proxyMode=org.springframework.context.annotation.ScopedProxyMode.TARGET_CLASS)
On my bean class, and in my controller i did this:
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
After doing those changes, the exception changes to the following:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.notificationController': Scope 'request' 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, or processing a request outside of the originally receiving thread? 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.doGetBean(AbstractBeanFactory.java:355) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.getTarget(CglibAopProxy.java:685) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:636) ~[spring-aop-4.2.2.RELEASE.jar:4.2.2.RELEASE]
at com.propspace.intl.pushnotifications.controller.NotificationController$$EnhancerBySpringCGLIB$$d92fa60c.greeting(<generated>) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_60]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_60]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_60]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_60]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:198) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:116) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:490) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:497) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:87) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:451) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:389) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:135) [spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_60]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_60]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_60]
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? 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:131) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:41) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:340) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
... 20 common frames omitted
Here's my config class:
#Configuration
#EnableWebSocketMessageBroker
#EnableAspectJAutoProxy(proxyTargetClass = true)
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/hello").withSockJS();
}
#Bean()
public NotificationHandler notificationHandler( ) {
return new PsNotificationHandler();
}
#Bean
#ConditionalOnMissingBean
public RequestContextFilter requestContextFilter() {
RequestContextFilter rcf = new RequestContextFilter();
rcf.setThreadContextInheritable(true);
return rcf;
}
#Bean
#ConditionalOnMissingBean
public RequestContextListener RequestContextListener() {
return new RequestContextListener();
}
#Bean
public HttpSessionIdHandshakeInterceptor httpSessionIdHandshakeInterceptor() {
return new HttpSessionIdHandshakeInterceptor();
}
}
My code is mostly based on a sample code for running websockets with spring boot, except for this part:
Object nots = notificationHandler.getAllNotificationsOfUser(null, false, false);
where i'm getting the notifications, help appreciated
Here's a stripped down version of the code
http://www.4shared.com/file/BinrToCqce/pushnotifications.html
Seems to be Message broker has its own thread. So Message broker and DispathcherServlet work in different threads. But you can't use HttpServletRequest from another thread. Because, when asynchronous job will try to process HttpServletRequest, there is possibility that request(or session) is not actual or does not exist anymore. This is means, that you can't use request scoped beans as well as session scoped beans outside of DispatcherServlet's thread.
Since, you can't access request or session data directly from another thread you have to pass this data manually.
We are using the CommandLineJobRunner to execute Spring Batch jobs. We are using -next on the command line:
java -Dlog4j.configuration=file:./prop/log4j.properties -Dlogfile=logfile_load_data -jar EtlLoadData.jar loaddata_etl_config.xml loaddata_etl_job -next
We started coming down with an error:
Job Terminated in error: A job instance already exists and is complete for parameters={run.id=10}. If you want to run this job again, change the parameters.
org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException: A job instance already exists and is complete for parameters={run.id=10}. If you want to run this job again, change the parameters.
at org.springframework.batch.core.repository.support.SimpleJobRepository.createJobExecution(SimpleJobRepository.java:122)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.batch.core.repository.support.AbstractJobRepositoryFactoryBean$1.invoke(AbstractJobRepositoryFactoryBean.java:168)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy14.createJobExecution(Unknown Source)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:111)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.start(CommandLineJobRunner.java:349)
at org.springframework.batch.core.launch.support.CommandLineJobRunner.main(CommandLineJobRunner.java:574)
I thought that if you were running with the -next option, this shouldn't be an issue. Any ideas?
As a temporary workaround, I cleaned up the SpringBatch table in the database, but I don't want this to happen again.
not aware of a -next option.
quickest way is to pass in the the current timestamp as a parameter to your job. that way it will be unique and won't really interfere with your job.
With de -next option, you should set a JobParametersIncrementer Implementation,
in this example i use -> new RunIdIncrementer to avoid the message : A job instance already exists and is complete for parameters
#Autowired
private JobBuilderFactory jobs;
...
#Bean(name=JOB_NAME)
public Job job() {
return jobs.get(JOB_NAME)
.start(this.login())
.next(this.launchDuke())
.incrementer(new RunIdIncrementer())
.build();
}
I am attempting to write my own Validator (as per the JSR-303 specification) under Spring 3.0.x.
I annotated the isValid(Serializable, CosntraintValidatorContext) method with #Transactional, but it seems that transactional advice is not being applied to this method - when the isValid() method is invoked, a call to sessionFactory.getCurrentSession() creates the Exception:
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
I have an #Autowired sessionFactory in the same Validator bean which is injected without issues. My current workaround is to use openSession() instead of getCurrentSession(), but that involves manual transaction management which I would prefer to avoid.
Doing a stack trace in the constructor of my validator bean, it seems that my Validator bean is being constructed via a call to the o.s.b.f.s.AbstractAutowireCapableBeanFactory.createBean(). I assume this means that the factory is capable of populating #Autowired fields in my Validator, but it seems that it is not applying any transactional advice?
Thanks in advance for any help on this matter.
EDIT: If it is of any help, I have included a partial stacktrace (via create new Exception()) that is logged in the constructor:
at com.mydomain.validators.UniqueValidator.<init>(UniqueValidator.java:49) ~[UniqueValidator.class:na]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [na:1.6.0_20]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) [na:1.6.0_20]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) [na:1.6.0_20]
at java.lang.reflect.Constructor.newInstance(Constructor.java:513) [na:1.6.0_20]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:126) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:74) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:958) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:911) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:286) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory.getInstance(SpringConstraintValidatorFactory.java:50) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.hibernate.validator.engine.ConstraintTree.createAndInitializeValidator(ConstraintTree.java:192) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ConstraintTree.getInitializedValidator(ConstraintTree.java:171) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:113) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.metadata.MetaConstraint.validateConstraint(MetaConstraint.java:121) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:334) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForRedefinedDefaultGroup(ValidatorImpl.java:278) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:260) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:213) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:119) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:86) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.validation.DataBinder.validate(DataBinder.java:692) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doBind(HandlerMethodInvoker.java:807) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:359) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:171) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426) [spring-webmvc-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414) [spring-webmvc-3.0.5.RELEASE.jar:3.0.5.RELEASE]
Transactional configuration appears to be correct (the STS IDE reports that the isValid() method is properly advised by the transactional manager by org.springframework.transaction.interceptor.TransactionInterceptor.invoke (with an #Component annotation on the Validator itself)), but my understanding is that if the validation bean is created outside the normal lifecycle of the Spring container, then the advice will not be properly applied when validation is done during data binding.
have you added the
<tx:annotation-driven/>
code into your configuration?
I am getting following error while executing a unti test case(JUNIT).I am using it to understand the part of the project.Project is a web based project.Project is using OPENJPA
<openjpa-1.2.1-SNAPSHOT-r422266:686069 fatal store error> org.apache.openjpa.persistence.RollbackException: Unable to obtain a TransactionManager using null.
at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:523)
at com.XYZ.cloud.admin.loadCatalog.LoadCatalogTest.populateOffering(LoadCatalogTest.java:253)
at com.XYZ.cloud.admin.loadCatalog.LoadCatalogTest.CatalogUploadTest(LoadCatalogTest.java:160)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:599)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:44)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: <openjpa-1.2.1-SNAPSHOT-r422266:686069 nonfatal general error> org.apache.openjpa.persistence.PersistenceException: Unable to obtain a TransactionManager using null.
at org.apache.openjpa.jdbc.sql.DBDictionary.narrow(DBDictionary.java:4231)
at org.apache.openjpa.jdbc.sql.DBDictionary.newStoreException(DBDictionary.java:4196)
at org.apache.openjpa.jdbc.sql.DB2Dictionary.newStoreException(DB2Dictionary.java:503)
at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:102)
at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:88)
at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:64)
at org.apache.openjpa.jdbc.kernel.AbstractJDBCSeq.next(AbstractJDBCSeq.java:65)
at org.apache.openjpa.util.ImplHelper.generateValue(ImplHelper.java:160)
at org.apache.openjpa.util.ImplHelper.generateFieldValue(ImplHelper.java:144)
at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.assignField(JDBCStoreManager.java:698)
at org.apache.openjpa.util.ApplicationIds.assign(ApplicationIds.java:487)
at org.apache.openjpa.util.ApplicationIds.assign(ApplicationIds.java:463)
at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.assignObjectId(JDBCStoreManager.java:682)
at org.apache.openjpa.kernel.DelegatingStoreManager.assignObjectId(DelegatingStoreManager.java:134)
at org.apache.openjpa.kernel.StateManagerImpl.assignObjectId(StateManagerImpl.java:519)
at org.apache.openjpa.kernel.StateManagerImpl.preFlush(StateManagerImpl.java:2823)
at org.apache.openjpa.kernel.PNewState.beforeFlush(PNewState.java:39)
at org.apache.openjpa.kernel.StateManagerImpl.beforeFlush(StateManagerImpl.java:959)
at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:1948)
at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:1908)
at org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:1826)
at org.apache.openjpa.kernel.LocalManagedRuntime.commit(LocalManagedRuntime.java:81)
at org.apache.openjpa.kernel.BrokerImpl.commit(BrokerImpl.java:1350)
at org.apache.openjpa.kernel.DelegatingBroker.commit(DelegatingBroker.java:877)
at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:512)
... 26 more
Caused by: java.sql.SQLException: Unable to obtain a TransactionManager using null.
at org.apache.openjpa.jdbc.kernel.TableJDBCSeq.allocateSequence(TableJDBCSeq.java:419)
at org.apache.openjpa.jdbc.kernel.TableJDBCSeq.nextInternal(TableJDBCSeq.java:290)
at org.apache.openjpa.jdbc.kernel.AbstractJDBCSeq.next(AbstractJDBCSeq.java:60)
... 44 more
Caused by: javax.transaction.NotSupportedException: Unable to obtain a TransactionManager using null.
at org.apache.openjpa.ee.AutomaticManagedRuntime.doNonTransactionalWork(AutomaticManagedRuntime.java:306)
at org.apache.openjpa.jdbc.kernel.TableJDBCSeq.allocateSequence(TableJDBCSeq.java:415)
... 46 more
Caused by: <openjpa-1.2.1-SNAPSHOT-r422266:686069 fatal user error> org.apache.openjpa.util.InvalidStateException: Could not perform automatic lookup of EJB container's javax.transaction.TransactionManager implementation. Please ensure that you are running the application from within an EJB 1.1 compliant EJB container, and then set the org.apache.openjpa.ManagedRuntime property to
at org.apache.openjpa.ee.AutomaticManagedRuntime.getTransactionManager(AutomaticManagedRuntime.java:250)
at org.apache.openjpa.ee.AutomaticManagedRuntime.doNonTransactionalWork(AutomaticManagedRuntime.java:304)
... 47 more
Caused by: javax.naming.ConfigurationException: Name space accessor for the java: name space has not been set. Possible cause is that the user is specifying a java: URL name in a JNDI Context method call but is not running in a J2EE client or server environment.
at com.XYZ.ws.naming.java.javaURLContextFactory.isNameSpaceAccessable(javaURLContextFactory.java:93)
at com.XYZ.ws.naming.urlbase.UrlContextFactory.getObjectInstance(UrlContextFactory.java:82)
at javax.naming.spi.NamingManager.getURLContext(NamingManager.java:655)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:434)
at javax.naming.InitialContext.lookup(InitialContext.java:450)
at org.apache.openjpa.ee.RegistryManagedRuntime.getTransactionManager(RegistryManagedRuntime.java:61)
at org.apache.openjpa.ee.AutomaticManagedRuntime.getTransactionManager(AutomaticManagedRuntime.java:154)
... 48 more
My guess is that you are trying to use a persistence.xml declaring a jta-data-source in a unit test context (i.e. in a Java SE context).
In other words, you're not using an appropriate persistence.xml for a testing context. You need a specific persistence.xml using a RESOURCE_LOCAL transaction type and configure it to use a built-in connection pool (instead of a datasource).
Show your persistence.xml if you need more guidance.
Like the error message suggests: You need to make sure that you are running the application from within an EJB 1.1 compliant EJB container.
I wasted nearly an hour o fix this. The issue was very basic. The #Id and #GeneratedValue was not annotated on the id field.
As we are using JPA Tools in RAD, Eclipse to generate the entity classes, it does not annotate id field.
So, this can be fixed by placing the #Id field.
#Id
#GeneratedValue(strategy=GenerationType.Identity)
#Column(name="some_name")
private long someNameId;