I have a base exception handler defined like this:
<bean id="exceptionResolver"
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="defaultErrorView" value="errors.exception-handling" />
</bean>
and I have my controller methods with security like this:
#PreAuthorize("isAuthenticated()")
#RequestMapping(value = "/Home", method = RequestMethod.GET)
public String home(HttpServletRequest request, HttpSession sess) {
}
Now I have my NotAuthorized handler configured to redirect you to the login page if you hit /Home. However, with the exceptionResolver, I just get my page saying that there was an error. If I comment out the exceptionResolver it works fine.
How do I get it to ignore NotAuthroized and other such security exceptions?
You can add it like this
<property name="exceptionMappings">
<props>
<prop key="org.springframework.security.AccessDeniedException">loginPageUrl</prop>
</props>
</property>
UPDATE:
You can specify excludedExceptions as well to ignore NotAuthroized exception and let it be processed separately.
Related
I am not expert in Spring MVC and I'm have some dificulties to achieve the intented.
Basically, I need a Controller that will redirect to a web flow.
I know how to achieve this with the use of #Controller and #RequestMapping annotations. However, I cannot use spring-context as I'm restricted to version 2.5 (these annotations are present in 2.5 but application won't build with Java 8)
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/first/*">myMvcController</prop>
<prop key="/toflow/*">myFlowController</prop>
</props>
</property>
</bean>
<bean id="myMvcController" class="mypackage.controller.myController"/>
<bean id="myFlowController" class="org.springframework.webflow.executor.mvc.FlowController">
<property name="flowExecutor" ref="flowExecutor"/>
<property name="defaultFlowId" value="application-flow"/>
</bean>
And my controller looks something like:
public class myController extends Controller {
#Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
return new ModelAndView(forward:/toflow/variable)
Not sure if the forward is correct or if I should provide the url different, but the main problem is that the controller tries to resolve that as a view that doesn't exist. I just want to call /toflow/xxxx which I assume will be handle by my previous mapping and call my webflow.
Any suggestions?
Thanks
Use return new ModelAndView("redirect:/toflow/variable");
I want to be able to read the properties from certain bean definitions that are configured in my Spring configuration file (i.e. the one set by contextConfigLocation in my web.xml) at run time. I want to do this so that I can log property values so that I when I receive the log files for diagnosis I can see how the system integrators have set up the application.
Looking at the Spring debug logs I can see that they are read from the config file by the class XmlBeanDefinitionReader. I'm guessing there is a way that Spring provides for accessing the resulting bean definitions, but I can't find it.
By way of example these are the sort of bean definitions that for which I would like to read configurations.
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="jdbcUrl">
<value>jdbc:mysql://localhost:3306/an_example_db</value>
</property>
<property name="user">
<value>exampleuser</value>
</property>
<property name="password">
<value>examplepwd</value>
</property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="packagesToScan" value="com.my.example.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.id.new_generator_mappings">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.query.substitutions">true 1, false 0, yes 'Y', no 'N'</prop>
</props>
</property>
</bean>
Please note that these are examples only. I'd like to be able to read properties for any bean definition if that is possible.
You can create a bean that plugs in the post-construction phase of all beans created at which point you can perform you logging. This can be done by a bean that implements BeanPostProcessor.
Example:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
#Component
public class BeanPostProcessorAuditChecker implements BeanPostProcessor {
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean: " + beanName + " initialized with props: " + bean);
return bean;
}
}
Things to note:
This bean can be defined using annotations (as depicted above) or XML config as usual.
The interface is intercepting all bean constructions.
The interface method implementations are expecting you to return the bean object.
In my example I just System.out.println but you really want to SLF4J or otherwise log. Also I'm trusting that the toString() method is implemented properly exposing the properties you are interested in.
If you want to filter the logging to happen only on a subset of beans and not for all beans you'll have to do that yourself in the body of the method with reflection
Snippet:
if(bean instanceof DataSource ||
bean instanceof SessionFactory) { log.debug("{}",bean); }
Since your business domain is not known some alternatives provided:
If you can pointcut your domain you want to plugin AOP is another alternative proxy approach.
You could expose JMX on the beans and consume externally (decoupled approach)
Another decoupled approach is publishing Events using ApplicationEventPublisher. This is fyi since not advisable in your case - you are interested in construction only state properties.
Before Edit
The beans you are demonstrating are 1) singletons (by virtue of Spring default scope) and 2) properties are not likely to be changing after bean setup (via set method calls).
Under these assumptions why aren't you amassing these properties values in a props file
database.driverClass=com.mysql.jdbc.Driver
database.user=exampleuser
...
inject them in the context definition
...
<property name="user" value="#{database.user}"/>
...
and use the PropertyPlaceholderConfigurer to check the values.
I am using the Spring configuration to test Spring-Hibernate Transactions.
<beans ...>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- hibernate 4 onwards annotationsessionfactorybean is replaced with localsessionfactory bean -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.fg.arch.test.transaction.Foo</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<!-- <prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</prop> -->
</props>
</property>
</bean>
</beans>
My service layer is annotated with #Transactional.
This is my DAO:
public class FooHibernateDaoImpl implements FooDao {
private SessionFactory sessionFactory;
public void testFoo(Foo foo) throws Throwable {
System.out.println(" --- ");
sessionFactory.openSession().save(foo);
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
Explicitly opening the session using the openSession() method does not cause a problem however when I change to getCurrentSession() I am getting an exception.
I have two questions.
Is it good practice to call openSession() in every DAO method.
How can I make getCurrentSession() work so that it will not give me an exception like no active transaction present ?
Thanks.
To answer your questions:
No, its not. The #Transactional annotation that should be on your service class method calling testFoo() is opening the session for you. You should use getCurrentSession() in the DAO to get this session.
You can, but you shouldn't. That's the entire point of using the Hibernate SessionFactory with annotation based transaction management. As long as you are marking your service methods transactional, you shouldn't have a problem.
As a side note, why are you not Autowiring your SessionFactory? Don't use setters to set something that should be Autowired. Otherwise you may as well not use Spring.
Hi I am trying to authenticate the user but seems like its calling a jsp page instead of another controller mapping.
My dispatcher servlet is
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.user}" />
<property name="password" value="${database.password}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.beingjavaguys.domain.User</value>
<value>com.beingjavaguys.domain.Chat</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>
<bean id="hibernateTransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
My web.xml is
dispatcher
org.springframework.web.servlet.DispatcherServlet
1
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
and my controller is
#RequestMapping(value="/authenticate",method=RequestMethod.POST)
public ModelAndView getAuthenticateResult(#ModelAttribute("user") User user,
BindingResult result) {
if(userService.authenticate(user))
{
return new ModelAndView("/userList");
}
else{
return new ModelAndView("Login");
}
}
#RequestMapping(value="/userList", method=RequestMethod.GET)
public ModelAndView getUserList() {
Map<String, Object> model = new HashMap<String, Object>();
model.put("chat", userService.getChat());
return new ModelAndView("UserDetails", model);
}
I am calling authenticate.html from my login file using POST method but my problem is this error
HTTP Status 404 - /Spring-hibernate-integration-helloworld/WEB-INF/view/userList.jsp
type Status report
message /Spring-hibernate-integration-helloworld/WEB-INF/view/userList.html.jsp
description The requested resource is not available.
Why is it searching for the jsp file instead of redirecting it to a controller method?
But if i use redirect:/userList.html it works then.Whats the logic behind it?
If you return a string that is interpreted as a name of a view to render. The name of the view is passed no the a ViewResolver (in your case probably an InternalResourceViewResolver) which will generate an (internal) URL to forward to. In this case that will be a JSP.
Now the redirect: and forward: prefixes are 2 special cases. The redirect: will result in a client side redirect to that URL, which in turn will call your controller due to your configuration. A forward: is handled on the server side and not the client side.
To be exact. The logic behind it is:
org.springframework.web.servlet.view.UrlBasedViewResolver
/**
* Overridden to implement check for "redirect:" prefix.
* <p>Not possible in {#code loadView}, since overridden
* {#code loadView} versions in subclasses might rely on the
* superclass always creating instances of the required view class.
* #see #loadView
* #see #requiredViewClass
*/
#Override
protected View createView(String viewName, Locale locale) throws Exception {
// If this resolver is not supposed to handle the given view,
// return null to pass on to the next resolver in the chain.
if (!canHandle(viewName, locale)) {
return null;
}
// Check for special "redirect:" prefix.
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
return applyLifecycleMethods(viewName, view);
}
// Check for special "forward:" prefix.
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
return new InternalResourceView(forwardUrl);
}
// Else fall back to superclass implementation: calling loadView.
return super.createView(viewName, locale);
}
I'm following the tutorial here:
http://www.javacodegeeks.com/2013/05/hibernate-4-with-spring.html
to enable the "#Transactional annotation" in my Java web application but failed to make it run properly. Please advise if the JTA manager is really required, and why?
Please note that my webapp is based on Spring 3 + Hibernate 4 + Tomcat 7.
Background and my doubts:
My current web application uses my own custom class (implements HandlerInterceptor) to enable one-hibernatesession-per-request basis. Now I want to improve my application's maintainability by using the "#Transactional annotation" instead since that could save many lines of code.
According to my understanding, the #Transactional basically relies on the AOP concept to ensure the session (Hibernate session) is ready for use in the annotated method. This seems nothing to do with the JTA. But I wonder why can't I make it work on my webapp in Tomcat 7 (without JTA-provider).
After few searches on google, it looks like the JTA is required. This confuses me since this seems to be a very basic functionality that shouldn't have the complicated JTA-provider as a requirement.
Here is the error I got:
org.hibernate.HibernateException: No Session found for current thread
org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:988)
...
This is the code I use for testing:
....
#Autowired
org.hibernate.SessionFactory sessionFactory;
#Transactional
#RequestMapping(method = RequestMethod.GET)
protected String home() {
Session session = sessionFactory.getCurrentSession(); // I expected the session is good to use now
Province p = (Province) session.get(Province.class, 1L); // This causes no session found error :(
return "home";
}
The spring XML:
....
<tx:annotation-driven/>
<context:component-scan base-package="..."/>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/..."/>
<property name="lookupOnStartup" value="true"/>
<property name="proxyInterface" value="javax.sql.DataSource"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="persistenceExceptionTranslationPostProcessor" class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
....
Thank you !
Just a speculation:
Your controller is defined in some kind of dispatcher-servlet.xml therefore seperates from the applicationContext in which < tx:annotation-driven/> is defined. The compoment you want to enhance with #Transactional need to be within the same context with < tx:annotation-driven> if I'm not mistaken. So the #Transactional does not work.
That was my silly mistake. The Spring uses CGLIB to proxy methods with #Transactional annotated and it seems like CBLIB can't enhance protected method.
protected String home() {
Changing this to
public String home() {
fixed the problem.