Spring applicationcontext loading hooks - spring

Are there any hooks into the Spring ApplicationContext loading process?
I want to run a piece of code just before the application context loads (before any beans/properties/aspects/etc... are instantiated).
thanks in advance

Maybe BeanFactoryPostProcessors will suite your needs? They are run after the whole XML configuration files are read, but before any (other) beans are instantiated.

You can also use the ApplicationListener to receive notification of events like ContextClosedEvent, ContextStartedEvent or ContextStoppedEvent.
More information in the IoC Container chapter.

I just declared my own ContextLoaderListener in order to perform the desired work before loading the Spring context. It suits for web-apps, just declare it before the Spring context listener:
public class MyServletContextListener implements ServletContextListener {
#Override
public void contextDestroyed(ServletContextEvent arg0) {
}
#Override
public void contextInitialized(ServletContextEvent arg0) {
//Perform your stuff here
}
}
<listener>
<listener-class>
com.myCompany.listeners.MyServletContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Related

How to differentiate between the session timeout by the Tomcat container and logout link press by the user?

Is there a way to differentiate between the session timeout by the Tomcat container and logout link press by the user?
EDIT1: My environment details : Java 1.8, Apache Tomcat 8.0.36 on Windows Server 2012
I have a MyHttpSessionListener class that implements javax.servlet.http.HttpSessionListener
public class MyHttpSessionListener implements HttpSessionListener {
#Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println(httpSessionEvent.getSession().getId()+" was CREATED");
}
#Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println(httpSessionEvent.getSession().getId()+" was DESTROYED");
}
}
and corresponding configuration declaration within the web.xml file
<listener>
<listener-class>com.webapp.listeners.MyHttpSessionListener</listener-class>
</listener>
I'm not using Spring Security for my webapp.
HttpSessionListener will tackle it at Servlet level. Here one important question is that which Application/Web Server are you using?
You need to have a look at SessionDeletedEvent and SessionExpiredEvent
For now have a try with SessionDestroyedEvent
#Component
public class SessionEndedListener implements ApplicationListener<SessionDestroyedEvent> {
#Override
public void onApplicationEvent(SessionDestroyedEvent event)
{
for (SecurityContext securityContext : event.getSecurityContexts())
{
Authentication authentication = securityContext.getAuthentication();
YourPrincipalClass user = (YourPrincipalClass) authentication.getPrincipal();
// do something
}
}
}
and you also need to register this in web.xml
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
Updated Answer
After the recent edit, Now for this case you need to use
HttpSessionBindingListener
This is being called when object is removed from the session (either explicitly by removeAttribute() method of HTTPSession or by an invalidation/expire of the session).
You could parse session lastAccessTime, and if it's some time ago (configured expiration time) then it expired.

Spring Data Rest: ResourceProcessor configuration is not working properly

I have a strange behaviour with a Spring Data Rest implementation (version 2.5.2.RELEASE).
I'm trying to register a #Bean of ResourceProcessor<Resource<Entity>>, but there is something strange.
I'm trying with two kinds of solutions:
1) Declaring the #Bean in a class:
#Bean
public ResourceProcessor<Resource<Author>> authorProcessor() {
return new ResourceProcessor<Resource<Author>>() {
#Override
public Resource<Author> process(Resource<Author> resource) {
System.out.println("method process of bean ResourceProcessor of class RepositoryBaseConfiguration");
return resource;
}
};
}
2) Implementing the interface ResourceProcessor:
#Component
public class AuthorResourceProcessor implements ResourceProcessor<Resource<Author>> {
#Override
public Resource<Author> process(Resource<Author> resource) {
System.out.println("method process of class AuthorResourceProcessor");
return resource;
}
}
The processors are completely ignored: the message is never printed.
I noticed that the class org.springframework.data.rest.webmvc.ResourceProcessorInvoker has a constructor:
public ResourceProcessorInvoker(Collection<ResourceProcessor<?>> processors) {
//...
}
This constructor is invoked 2 times at the start of the application instead of only one time (as I will expect), and I don't understand why.
The first time, the "processors" variable is solved with the two beans (as expected) and with the bean org.springframework.data.rest.webmvc.ProfileResourceProcessor.
But the second time, the "processors" variable is solved with only the bean org.springframework.data.rest.webmvc.ProfileResourceProcessor.
The second configuration #Override the first one.
Any idea?
The problem depends on the configurations loaded at the startup of the application.
I had this configuration on the web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/spring-web-config.xml</param-value>
</context-param>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.data.rest.webmvc.RepositoryRestDispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
So, the ContextLoaderListener loaded the correct configuration in the first time; the "load-on-startup" property of the servlet "RepositoryRestDispatcherServlet" launch a second context configuration load.
I also had a custom class that extended org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration, but this custom class was ignored by the moment that the constructor of RepositoryRestDispatcherServlet load the default RepositoryRestMvcConfiguration, causing the lost of the configurations.
To solve that issue I have created a custom RepositoryRestDispatcherServlet in this way:
public class AppRepositoryRestDispatcherServlet extends DispatcherServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
public AppRepositoryRestDispatcherServlet() {
configure();
}
public AppRepositoryRestDispatcherServlet(WebApplicationContext webApplicationContext) {
super(webApplicationContext);
configure();
}
private void configure() {
setContextClass(AnnotationConfigWebApplicationContext.class);
setContextConfigLocation(RepositoryBaseConfiguration.class.getName());
}
}
The class is the same as RepositoryRestDispatcherServlet, with the only difference that in the setContextConfigLocation is passed the custom class that extends RepositoryRestMvcConfiguration (RepositoryBaseConfiguration in this example).
Obviously I had to update the web.xml as follows:
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>my.package.AppRepositoryRestDispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
In this way, the configuration is correctly loaded and mantained.

how to detect tomcat session expiration using spring

i am running wicket with spring and use spring security , when tomcat session , the one which declared in the web.xml expired
<session-config>
<session-timeout>1</session-timeout>
</session-config>
I want to catch this event using a filter(not overiding existing httpSession or Session )
how can I achive that using spring ?
10x
You can use a listener class to achieve this. Define a listener component as below:
#Component
public class AppLogoutListener implements
ApplicationListener<SessionDestroyedEvent> {
#Override
public void onApplicationEvent(SessionDestroyedEvent event) {
// from event you can obtain SecurityContexts to work with
}
}
You need to define a session event publisher in your web.xml:
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
Here the HttpSessionEventPublisher publishes the session life cycle events whenever sessions are created and expired.

GWTP using Spring in server side

I am working with gwtp and I would like to use Spring on the server side. I have seen that Spring is include in gwtp, but I don't know how I can use it. Anyone can help me about that?
Will be cool some example.
I have looked for by google, but no way :(
Thanks a lot!!
GWTP is using GIN pattern (Dependency Injection at Client Side) and it's default integration with GUICE at DI server side. for more detail GWTP
Spring is server side DI pattern.
I have seen that Spring is include in gwtp,
It does not include Spring at all. it's default integration with GUICE. but you can use spring with it.
gwtp-sample-basic-spring example
Well, at first you have to configure Spring in your web.xml descriptor:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<servlet>
<servlet-name>springGwtRemoteServiceServlet</servlet-name>
<servlet-class>org.spring4gwt.server.SpringGwtRemoteServiceServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springGwtRemoteServiceServlet</servlet-name>
<url-pattern>/yourProjectName/springGwtServices/*</url-pattern>
</servlet-mapping>
Notice that you need the Spring4GWT library for this example.
Next, in your RemoteService interfaces you need to specify the RemoteServiceRelativePath like this example:
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import com.google.gwt.user.client.rpc.RemoteService;
#RemoteServiceRelativePath("springGwtServices/userService")
public interface UserService extends extends RemoteService{
public User getUserByLogin(String name);
public void logout();
public void deleteUserById(Long userId);
}
And now, you just need to implement your service as in any Spring app.
Example, suppose you want an action to delete a User by ID and using the GWTP paradigm:
In server side, here is the Handler:
#Repository("deleteUserHandler")
public class DeleteUserHandler extends AbstractActionHandler<DeleteUserAction, DeleteUserResult> {
#Autowired
private UserService userService;
public DeleteUserHandler(){
super(DeleteUserAction.class);
}
#Override
public DeleteUserResult execute(DeleteUserAction action, ExecutionContext arg1)
throws ActionException {
Long idToDel = action.getUserToDeleteId();
if(idToDel != null){
userService.deleteUserById(idToDel);
}
return new DeleteUserResult();
}
#Override
public void undo(DeleteUserAction arg0, DeleteUserResult arg1,
ExecutionContext arg2) throws ActionException {
// TODO Auto-generated method stub
}
}
The DeleteUserAction is as follows
public class DeleteUserAction extends UnsecuredActionImpl<DeleteUserResult> {
private Long userToDeleteId;
public DeleteUserAction(Long userToDel) {
this.userToDeleteId = userToDel;
}
/**
* For serialization only.
*/
#SuppressWarnings("unused")
private DeleteUserAction() {
}
public Long getUserToDeleteId() {
return userToDeleteId;
}
public void setUserToDeleteId(Long userToDeleteId) {
this.userToDeleteId = userToDeleteId;
}
}
And finally the Result class:
public class DeleteUserResult implements Result {
/**
* For serialization only.
*/
//#SuppressWarnings("unused")
public DeleteUserResult() {
}
}
I hope this helps.
PS: I suppose you can do the Spring things (application context etc..) by yourself, if not, please tell
You can find some good examples on GWTP repository in Github. We recently migrated all of our from Google Code to Github, which hosts the latest version.
Remember you can also use REST communication using the new GWTP-Dispatch-Rest, with that you don't need a lot of configuration code to integrate GWTP with Spring server side.
https://github.com/ArcBees/GWTP-Samples

unittesting with ServletContextListener

i have an ServletContextListener which initializes my DB. and i've addid it in my web.xml:
<listener>
<listener-class>util.MySessionListener</listener-class>
</listener>
When i startup the server everything is fine.
but when i run my AbstractTransactionalJUnit4SpringContextTests-tests it is not called. what can i do?
Is this ServletContextListener or HttpSessionListener? Your naming is confusing.
Nevertheless, simply run this in #Before:
MockServletContext mockServletContext = new MockServletContext()
new MySessionListener().contextInitialized(
new ServletContextEvent(mockServletContext)
)
Where MockServletContext comes from Spring. If your listener uses WebApplicationContextUtils, you will need to add this before running contextInitialized():
mockServletContext.setAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
yourTestApplicationContext
);
Where yourTestApplicationContext is an instance of ApplicationContext you can simply inject in your test case:
#Autowired
private ApplicationContext yourTestApplicationContext;
i solved it with the
ApplicationContextAware
interface:
<bean id="springApplicationContext" class="server.utils.SpringApplicationContext" />
and in the
public void setApplicationContext(ApplicationContext context) throws BeansException {
i can do my initialisation, hibernate and everything is ready at this point

Resources