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");
Related
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.
We are currently migrating from xml configuration to complete annotation with java configuration based Spring application. With the annotation approach #Transactional we can achieve but the we need to write for each and every method.
In XML we configured (OLD).
<bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="delete*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED</prop>
<prop key="update*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED</prop>
<prop key="save*">PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED</prop>
<prop key="get*">PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITTED,readOnly</prop>
<prop key="is*">PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITTED,readOnly</prop>
<!--<prop key="*">PROPAGATION_REQUIRED</prop> -->
</props>
</property>
</bean>
transactionManager is org.springframework.orm.hibernate3.HibernateTransactionManager
<bean id="xxxxSVC" parent="txProxyTemplate">
<property name="target">
<bean class="XXX.XXX.XXX.SVCImpl">
<property name="xxxxDao" ref="xxxDao"></property>
</bean>
</property>
</bean>
txProxyTemplate is parent class of each service class.
So, please suggest how to configure similar code in java configuration. Thanks for your valuable time spent and support us.
#Barath Comment
Bean
#Bean
public TransactionProxyFactoryBean setTransactionProperties() throws IOException {
TransactionProxyFactoryBean transactionProxyFactoryBean = new TransactionProxyFactoryBean();
transactionProxyFactoryBean.setTransactionManager(transactionManager(sessionFactory()));
Properties transactionAttributesProps = new Properties();
transactionAttributesProps.setProperty("delete*", "PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED");
transactionAttributesProps.setProperty("update*", "PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED");
transactionAttributesProps.setProperty("save*", "PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED");
transactionAttributesProps.setProperty("get*", "PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITTED,readOnly");
transactionAttributesProps.setProperty("is*", "PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITTED,readOnly");
transactionProxyFactoryBean.setTransactionAttributes(transactionAttributesProps);
transactionProxyFactoryBean.afterPropertiesSet();
return transactionProxyFactoryBean;
}
How to configure with each service implementation class, we can use it for single as a service layer may contain N classes. There is a method setTarget(Object target). Now how can we configure all the N classes. Please sugggest how can we configure.
A sample configuration for this case :
#Bean
public TransactionProxyFactoryBean txProxyTemplate(){
TransactionProxyFactoryBean txFactory=new TransactionProxyFactoryBean();
txFactory.setTransactionManager(new JpaTransactionManager()); // any transcation manager
txFactory.setTransactionAttributes(properties());
return txFactory;
}
#Bean
Properties properties(){
Properties properties=new Properties();
properties.put("delete*", "PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED");
//set al lthe properties
return properties;
}
#Bean
public TransactionProxyFactoryBean xxxxSVC(TransactionProxyFactoryBean txFactory){
txFactory.setTarget(testEntity());
return txFactory;
}
#Bean
TestEntity testEntity(){
return new TestEntity();
}
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.
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.