Configuring interceptor in Spring - spring-mvc

I am using Spring 3.0
I need to write an interceptor which intercepts all urls. in my application
I wrote one intercptor
public class HelloInterceptor extends HandlerInterceptorAdapter {
how can i configure it in spring-servlet.xml.

Using <mvc:interceptors> (see docs), e.g.
An example of registering an interceptor applied to all URL paths:
<mvc:interceptors>
<bean class="x.y.HelloInterceptor" />
</mvc:interceptors>

Related

how to inject userContext in JSP pages

how do I retrieve the values of a context in a jsp file? this tutorial is perfect for what I need but I need to retrieve the property values in the jsp file.
http://www.mkyong.com/spring/spring-listfactorybean-example/
is there a specific interceptor that I can use?
You're referring to spring context right?
In general, JSPs should be a template of a page only, so the only interaction with the back-end should be accessing the values of the scoped attributes. This means that whichever bean value you need you should instead store in the model.
This being said, there are a few ways you can expose spring beans to view. Depends on which View resolver you're using, the ones that extend UrlBasedViewResolver have the setExposeContextBeansAsAttributes property
Set whether to make all Spring beans in the application context
accessible as request attributes, through lazy checking once an
attribute gets accessed. This will make all such beans accessible in
plain ${...} expressions in a JSP 2.0 page, as well as in JSTL's c:out
value expressions.
Default is "false".
You would configure it like
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
<property name="exposeContextBeansAsAttributes" value="true" />
</bean>
Inject your bean (or source) of userContext into your controller, so you have access to it in a local variable.
So taking the example maybe this is:
#Autowired
private CustomerBean customerBean;
#RequestMapping(value="/foobar/index.jsp")
public String (HttpServletRequest request) {
Object userContext = customerBean.getLists();
request.setAttribute("userContext", userContext);
return "/foobar/index.jsp"; // expecting JstlView viewResolver to map to JSP file
}
In the CONTROLLER simply add data to the HttpServletRequest (which you just add as argument to the method to introduce it).
Then use request.setAttribute("userContext", userContext); then in JSP simply access it using Expression Language like ${userContext}. There are other ways using Spring model paradigm but they effectively do the above.
Ensure you have your JstlView setup to https://dzone.com/articles/exploring-spring-controller
More info about how to use EL in JSPs to retrieve data attached to request:
How to obtain request / session / servletcontext attribute in JSP using EL?

How to use WAS standard persistence provider with Spring

I'm developing a portlet which runs in WebSphere Application Server ( - I accept the same problem to appear if it was a servlet instead of a portlet). At the moment it depends on Hibernate. As WAS provides a JPA implementation itself, which is a modified version of OpenJPA 2.0, I want to get rid of Hibernate.
This is my setup. persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
>
<persistence-unit name="default" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/myDb</jta-data-source>
<properties>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform" />
<property name="hibernate.dialect" value="org.hibernate.dialect.DB2Dialect" />
</properties>
</persistence-unit>
</persistence>
myPortlet-portlet.xml
<!-- ... -->
<tx:jta-transaction-manager />
<jee:jndi-lookup jndi-name="jdbc/myDb" cache="true" id="dataSource" expected-type="javax.sql.DataSource" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="default" />
</bean>
In my DAO-classes I access the entityManager by using annotations:
#PersistenceContext(unitName = "default")
private EntityManager entityManager;
Everything works fine using Hibernate.
According to WebSphere Application Server docs, the default persistence provider is used if you don't specify it by using the <provider/>-tag in persistence.xml. But after commenting out the provider specification, Spring throws an exception due not being able to find the provider-class:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in PortletContext resource [/WEB-INF/myPortlet-portlet.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: No PersistenceProvider specified in EntityManagerFactory configuration, and chosen PersistenceUnitInfo does not specify a provider class name either
How can I use the provided JPA implementation together with Spring (Portlet) MVC?
Short answer
You cannot use WebSphere's default provider by omitting the provider, if you want to use LocalContainerEntityManagerFactoryBean.
Long answer
Normally an entity manager is created by an entity manager factory provided by the container. You retrieve it by doing a context loopkup (EntityManager em = (EntityManager) ctx.lookup(...)) manually or use Springs jndi-lookup capability:
<beans>
<jee:jndi-lookup id="myEmf" jndi-name="persistence/myPersistenceUnit"/>
</beans>
In the question, a different approach is used, a LocalContainerEntityManagerFactoryBean, which creates an entity manager factory itself. This entity manager factory is a proxy that implements all the interfaces of the native entity manager factory. For creating such a proxy, Spring must know the class of the native entity manager factory. Spring uses three different ways to determine the class:
Detect it by the <provider/>-entry in persistence.xml
Asking a jpaVendorAdapter (specified in the equally named property of the factory bean)
Using the entityManagerFactoryInterface-property of the factory bean
And that's why you cannot completely omit the specification of your provider.
This is most likely happening because the Spring JAR(s) that you include with your application contains a different implementation of the Persistence class, or other JPA classes, used to "bootstrap" JPA.
If you'd like to use WebSphere's default provider (or, more precisely, to use whichever JPA provide configured through WebSphere's administration screens), then you must ensure that the JPA "bootstrapping" code being called during runtime is WebSphere's, not yours.
You should look for a Spring distribution JAR that doesn't mess with JPA.

How to access request scoped bean in controller?

I'm trying to understand the request scoped beans. Suppose I have a controller and I have a request scoped bean instantiated using spring config xml
<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>
Do I need to add it as a dependency in controller to access it or I can access it directly from request object doing request.getAttribute("loginAction")
I just wanted to know how would I access this request scoped bean.
Thanks.
Use #Autowired annotation for this case.
#Autowired
private LoginAction loginAction;
and then add package for this bean as candidate for autowiring:
<context:annotation-config />
<context:component-scan base-package="com.foo"></context:component-scan>
and don't forget to mark this class as #Component or #Service.

How to configure Shiro + Spring MVC when #Controller REDIRECTS to a login page

I have a typical Spring MVC + GWT architecture with Apache Shiro as a security layer.
Problem:
No matter what protocol is used for a request to the App server, pages should be returned in the protocol specified in the request's "X-Forwarded-Proto" header (so, app server can receive a HTTP request, but if the header says HTTPS, it should respond using HTTPS). Obviously, the configuration specified in the Shiro-Spring tutorial won't work as it has nothing to do with the protocols (login.jsp will be returned using the protocol used in request):
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login.jsp"/>
<property name="filterChainDefinitions">
<value>
/** = authc
</value>
</property>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
</bean>
<bean id="myRealm" class="com.myapp.security.DBRealm">
<property name="credentialsMatcher" ref="sha256Matcher"/>
</bean>
Possible solution:
Use #Controller to REDIRECT to the login view with the specified protocol:
#RequestMapping(value="/login", method=RequestMethod.GET)
public RedirectView doLogin(HttpServletRequest req) throws MalformedURLException {
URL originalURL = new URL(req.getRequestURL().toString());
return new RedirectView(new URL(req.getHeader("X-Forwarded-Proto"), originalURL.getHost(), "/login.jsp").toString());
}
and change the loginUrl in shiro configuration to point to /login, so that #controller catches it:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login"/>
... leave everything else the same
</bean>
But with this configuration, although I get the same login page, the myRealm (com.myapp.security.DBRealm) is not triggered at all (meaning, the credentials are not checked), and login always fails. Seems like the redirected page loses the "hook" to the realm.
Any ideas on what I am doing wrong?
The reason this is failing is because the Shiro authc Filter (a FormAuthenticationFilter) expects the loginUrl to be the one where the login attempt occurs.
That is, when authc filters a request that matches the loginUrl, it will automatically support form-based authentication. Because you are redirecting the end-user to a URL that does not match the loginUrl (i.e. loginUrl=/login, but you redirect them to /login.jsp), the authc filter won't perform a login.
Your best option IMO:
Subclass FormAuthenticationFilter and override the redirectToLogin method to use your X-Forwarded-Proto logic. Then redefine 'authc' to be your custom subclass. For example, using shiro .ini:
[main]
...
authc = com.foo.my.FormAuthenticationFilterSubclass
Also, if you want this behavior in Shiro directly (so Shiro looks for that header when performing a redirect by default) so you can remove your subclass, please open a feature request in Apache Shiro's Jira.

How to enable Spring 3.0 MappingJacksonHttpMessageConverter with #ResponseBody AND pre-Spring-3.0 Controller SimpleUrlHandlerMapping together?

As the title suggests, I'm trying and failing to get the following combination working in Spring 3.0:
pre-Spring-3.0 controllers mapped with SimpleUrlHandlerMapping, and,
a Spring-3.0 #Controller using MappingJacksonHttpMessageConverter and #ResponseBody to return JSON.
All the pieces work - except when put together!
In more detail, I have an existing Spring web-app which includes many pre-Spring-3.0 controllers. These implement Controller and are mapped explicitly with a SimpleUrlHandlerMapping bean. (So one solution is to change them all to #Controller style). The same web-app (DispatcherServlet) also supports several newer controllers annotated with #Controller.
My bean config includes the following, and all is good:
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/path/name.ext">mySpring25Controller</prop>
</props>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
</bean>
Now I'm adding, to a new controller annotated with #Controller and #RequestMapping, use of MappingJacksonHttpMessageConverter so that with #ResponseBody some of my methods can return JSON via Jackson - to Ajax calls. Again all is good:
<!-- to generate JSON responses using Jackson (without using <mvc:annotation-driven/>) -->
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>
The problem is that now my explicit mappings defined in the SimpleUrlHandlerMapping bean are no longer working:
[http-8081-Processor25] ERROR org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/mayapp].[springapp] - Servlet.service() for servlet springapp threw exception
javax.servlet.ServletException: No adapter for handler [com.mycom.controller.mySpring25Controller ...]: Does your handler implement a supported interface like Controller?
at org.springframework.web.servlet.DispatcherServlet.getHandlerAdapter(DispatcherServlet.java:985)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:773)
These mappings still appear in my log at start-up (SimpleUrlHandlerMapping - Mapped URL path ... etc) - but evidently are now broken somehow.
INFO org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped URL path [/path/name.ext] onto handler [com.mycom.controller.mySpring25Controller ....]
I started with <mvc:annotation-driven/> which had the same problem. I've tried re-ordering without success, including order properties. And I've also not found an explanation in the Spring docs. It seems there is some interaction in the Spring auto-magic which I haven't got to the bottom of.
Interesting problem anyone? Insight gratefully received!
Post and ye shall find (delayed by 8 hours for lack of reputation)!
As per post No adapter for handler exception the answer appears to be that the explicit AnnotationMethodHandlerAdapter definition blows away the implicit SimpleControllerHandlerAdapter which was previously satisfying the SimpleUrlHandlerMapping mappings.
So add it explicitly:
<bean
class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">
</bean>
And we're good, though at the same time you might also need to introduce also an explicit replacement for the implicit HttpRequestHandlerAdapter also blown away:
<bean
class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter">
</bean>

Resources