Access Spring Web MVC Exception Resolver from Spring Security Context - spring

I have a Spring Web MVC configuration with a SimpleMappingExceptionResolver in it to handle some access exceptions:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" p:defaultErrorView="uncaughtException">
<property name="exceptionMappings">
<props>
<prop key=".DataAccessException">dataAccessFailure</prop>
<prop key=".NoSuchRequestHandlingMethodException">resourceNotFound</prop>
<prop key=".TypeMismatchException">resourceNotFound</prop>
<prop key=".MissingServletRequestParameterException">resourceNotFound</prop>
</props>
</property>
</bean>
I also have a Spring Security context configuration where I would like to handle some authentication related exceptions. Currently, I have an ExceptionMappingAuthenticationFailureHandler set up as follows:
<form-login authentication-failure-handler-ref="exceptionMapper" ... />
...
<bean id="exceptionMapper" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler" >
<property name="exceptionMappings">
<props>
<prop key=".CredentialsExpiredException">/resetPassword</prop>
<prop key=".BadCredentialsException">/login?failure=true</prop>
</props>
</property>
</bean>
I was thinking that it would be nice to consolidate these into a single exception handling configuration by moving the security mappings to the MVC configuration. My problem is that I don't know how to tell Spring Security that I want form-login's authentication-failure-handler to use the resolver.
I can't just add an id to SimpleMappingExceptionResolver because 1) authentication-failure-handler-ref expects a Handler, not a Resolver, and 2) any beans that are defined in the MVC configuration don't seem to be visible from the security context...
Thanks for any help!

To answer part 2) of your question, you can share bean definitions between configurations via the use of the <import resource="..."/> tag.
I'm not sure how successful you will be for part 1) (single exception resolver), because having looked at the API both classes are completely different - no shared interface. You may have to roll your own, using one of the classes as the platform and building the functionality of the other class into it.

Related

Spring 3.2 + JPA (with Hibernate 3.6) + Websphere 8 (JTA) not flushing/commiting some operations

I have some issues after changing my backend from Hibernate to JPA (+Hibernate). I am using Websphere and container transaction management through org.springframework.transaction.jta.WebSphereUowTransactionManager. Some operations don't behave as expected:
DELETE OPERATION: If I don't flush the EntityManager manually it won't issue the delete, nothing happens actually.
#Transactional
#Override
public void deleteApplication(Integer appId) {
Application app = appDAO.findOne(appId);
//em.flush(); to force the flush(), otherwise it doesn't do anything
appDAO.delete(app);
}
INSERT WITH CASCADE OPERATION: The Application entity has a N:M relation with Attribute. I try to persist an Application with some Attribute added to its Application.attributes List. Right after the appDAO.save() I see a insert into Application sentence. However, there are never any inserts for the cascaded Attributes into the join table. Again, I need to manually flush() the em to issue de sql statements left.
#Transactional
#Override
public Application createApplication(Application application) {
appDAO.save(application);
//em.flush(); Needed to force the cascade into the join table
return application
}
I have tried changing the transactionManager for a non-container-managed one (org.springframework.orm.jpa.JpaTransactionManager) and it works perfectly without needing to use manual flush.
I am not using the persistence.xml file, following the approach introduced in Spring 3.1 (jtaDataSource + packagesToScan). However I have also tried with the traditional config with a persistence.xml file and I experienced the same wrong behaviour.
¿Any suggestions?
My setup:
<bean id="mainEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="mainPersistenceUnit"/>
<property name="jtaDataSource" ref="mainDataSource"/>
<property name="packagesToScan" ref="packages-mainEntityManagerFactory"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.flush_before_completion">true</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</prop>
</props>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
</bean>
<tx:annotation-driven order="0" />
<!-- Drives transactions using local JPA APIs -->
<bean name="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
In case someone has the same problem. The solution comes down to using
<prop key="hibernate.transaction.factory_class">org.hibernate.ejb.transaction.JoinableCMTTransactionFactory</prop>
instead of
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</prop>

Hibernate packageesToScan fails, but annotatedClasses works

We have a new webapp that we are prepping for deployment. We changed how we include our jars, from just manually dumping them into the web-inf/lib to using eclipse's deployment assembly to move them from a common location into the web-inf/lib dynamically, creating one repository for our libs. This tactic works fine with everything but one jar...the one our hibernate entities are in.
The jar is there, we can see it. It's in the classpath, we can instantiate it. But when we run, we get an exception for unknown entity as if the annotations from the target entity were never run. When we replace our "packagesToScan" declaration with a "annotatedClasses" list, it works fine. Yet our packagesToScan looks right. I'd much rather use the flexible packagesToScan than has developers required to do the easy-to-forget step of declaring their classes each time.
Anyone have any idea why this might be?
spring config (the below shows all three at the same time, in reality we comment one in at a time):
<bean id="rptappSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="rptappDataSource" />
<!-- works -->
<property name="annotatedClasses">
<list><value>a.b.c.report.model.table.BOReportTask</value></list>
</property>
<!-- does not work -->
<property name="packagesToScan">
<list><value>a.b.c.report.model.table</value></list>
</property>
<!-- also does not work -->
<property name="packagesToScan" value="a.b.*" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.DB2Dialect</prop>
<prop key="hibernate.connection.driver_class">com.ibm.db2.jcc.DB2Driver</prop>
<prop key="hibernate.bytecode.provider">javassist</prop>
<prop key="hibernate.show_sql">${hibernate.show.sql}</prop>
<prop key="format_sql">false</prop>
<prop key="use_sql_comments">false</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.default_schema">K702PRDR</prop>
</props>
</property>
</bean>
Exception:
Caused by: org.hibernate.hql.ast.QuerySyntaxException: BOReportTask is not mapped [from BOReportTask r where r.reportStatus = :status order by r.submissionTimestamp asc]
at org.hibernate.hql.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:181)
at org.hibernate.hql.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:111)
at org.hibernate.hql.ast.tree.FromClause.addFromElement(FromClause.java:93)
at org.hibernate.hql.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:313)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3353)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3237)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:724)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:575)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:292)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:235)
at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:254)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:185)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:136)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:101)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:80)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:98)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:156)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:135)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1760)
at a.b.c.report.dao.hibernate.table.ReportTaskDao.fetchByStatus(ReportTaskDao.java:68)
So I recently rediscovered this post and thought I'd post the solution for posterity. When exporting the jars in RAD, the jar wizard has a checkbox called "Add Directory Entries" on the first page of the wizard. Check that. Without it, my packagesToScan reference, which was to a root of the package with the entities in it (since there is more than one package of entities), would not be found. It acted like there were no entitites. Checking this adds stuff to the manifest and causes the classes to be found by the annotation scanner.

hibernate.search.default.directory_provider in spring beans rather than persistence.xml

I am in a rather nasty situation. We use compass for Hibernate search integration with Lucene and have implemented database directory search (using JdbcDirectory) instead of FSDirectoryProvider, RAMDirectoryProvider etc.
The problem is that the directory provider is passed as a property inside the META-INF/persistence.xml like the one below:
<property name="hibernate.search.default.directory_provider" value="uk.company.package.JdbcDirectoryProvider" />
We need to pass the database details to the the JdbcDirectoryProvider as JdbcDirectory requires a datasource to be passed.
We are constructing the datasource (for the directory provider) in an unconventional way using a property file (in the class path) with the database and index details.
If we have uk.company.JdbcDirectoryProvider configured as a spring bean, we can inject the datasource. This works well with Tomcat but not with OAS or Weblogic as still as we are passing the directory_provider in the persistence.xml. Probably becasue the datasource is initialized by the spring (becasue of the way classloaders work in these app servers).
My question is how can we configure the hibernate.search.default.directory_provider directly inside aSpring bean instead of the persistence.xml?
The closest place is:
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
But it only takes three properties:
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
Solution
You could pass the hibernate properties in spring bean as jpaProperties
<property name="jpaProperties">
<props>
<prop key="hibernate.search.default.directory_provider">
uk.company.package.JdbcDirectoryProvider
</prop>
</props>
</property>
I found the solution.
You could pass the hibernate properties in spring bean as jpaProperties
<property name="jpaProperties">
<props>
<prop key="hibernate.search.default.directory_provider">
uk.company.package.JdbcDirectoryProvider
</prop>
</props>
</property>

how to flush hibernate session using spring transaction manager for non read only methods?

I've read several topics but still don't understand. I have a spring mvc application that use hibernate on a DAO layer. The sessionFactory and transaction manager was configured in a standard way, service layer use `#Transaction` Also I use `OpenSessionInViewFilter`. I know that this filter set session flush mode to NEVER but then tx manager set it to AUTO for each tx and return it back once tx is commited. Also I get session as `sessionFactory.getCurrentSession()`.
My problem is with the non-read-only methods. Objects do not appears in the database after method is finished. Only after I explicitly call session.flush() the session state synchronized with the DB. As for me it's not a normal way. I think there is should be a property for tx manager or maybe sessionFactory or another bean that make a auto commit for non-read-only methods.
So, why FlushMode.AUTO may not work? Is it normal to call session.flush() manually in each non-read-only methods?
<bean name="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="aimsDataSource">
<property name="packagesToScan">
<list>
<value>net.adaptiveservices.aims.rc.model</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop> <!--TODO Remove in production-->
</props>
</property>
</bean>
<bean name="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory"/>

NoSuchMethodException thrown by AnnotationValidationInterceptor when executing an action

Details of jars used:
Struts2 2.2.1
Spring 3.0.5.RELEASE
Hibernate 3.6.0.FINAL
I am experiencing a strange issue when trying to execute an action mapped as follows:
<action name="supplierSearch" class="supplierSearchAction">
<result>/pages/suppliersearch.jsp</result>
</action>
<action name="searchForSupplier" class="supplierSearchAction" method="doSearch">
<result>/pages/suppliersearch.jsp</result>
</action>
the first action sends the user to a search page, they enter a search string and then the second action is invoked when the post the form.
The action in spring config is as follows:
<bean id="supplierSearchAction"
class="com.blah.SupplierSearchAction"
scope="prototype">
<property name="searchService" ref="supplierSearchService"></property>
</bean>
the search service uses hibernate search and is defined as follows:
<bean id="supplierSearchService"
class="com.devcentre.yubi.application.service.SupplierSearchServiceImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
I am using spring aop to configure my transaction boundaries and the persistence config is as follows:
<tx:annotation-driven transaction-manager="txManager" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
// annotated classes here
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">upgrade</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.provider_class">
net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop>
<prop key="hibernate.search.default.directory_provider">org.hibernate.search.store.FSDirectoryProvider
</prop>
<prop key="hibernate.search.default.indexBase">/lucene/indexes</prop>
<prop key="hibernate.search.default.batch.merge_factor">10</prop>
<prop key="hibernate.search.default.batch.max_buffered_docs">10</prop>
</props>
</property>
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Spring is configured as follows in my web.xml:
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/src/spring-config.xml
/WEB-INF/src/persistence-config.xml
</param-value>
</context-param>
On the search JSP page I have a form which submits the search string to the action which should invoke the doSearch method. However, when I submit the search I get an exception as follows (because devmode is enabled):
Struts has detected an unhandled exception:
Messages: $Proxy28.doSearch()
File: java/lang/Class.java Line
number: 1,605
and then the stack trace:
java.lang.NoSuchMethodException: $Proxy28.addComponent()
java.lang.Class.getMethod(Class.java:1605)
org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.getActionMethod(AnnotationValidationInterceptor.java:75)
org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:47)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
This is very odd because there is a method on the action class with the signature:
public String doSearch()
Can anyone help shed light on why the ActionProxy doesn't have the expected method?
Thanks,
Alex
java.lang.NoSuchMethodException: $Proxy25.doSearch()
Notice that the name of your action class is $Proxy25. It appears that something is creating a dynamic proxy to your action class. This is usually seen when using Aspect Oriented Programming (AOP) method interceptors on methods of a class — e.g., for things like transactions.
For example, I use Google Guice from time-to-time and when using AOP method interceptors on methods of a class, an action called LoginAction would have a dynamic proxy created called LoginAction$$EnhancerByGuice$$someAdditionalCharacters. While this dynamic proxy subclasses the methods of the class, it does not inherit annotations. My guess is that the same thing is happening here.
I don't use Spring, so I am not familiar with what libraries it uses to create dynamic proxies.
Update
If you remove the AOP annotations from your action class, then it should work as expected. Your action class can delegate to a service-layer class to handle persisting to the database (you can put the #Transactional annotation on that class's method(s)).
The struts2 spring & annotation integration seems to have its catches still...
the first call to getMethod from the AnnotationValidationInterceptor can be avoided using exclude parameters.
<interceptor-ref name="validation">
<param name="excludeMethods">YOURMETHODHERE</param>
</interceptor-ref>
however, this simply postpones the problem until the actual method is called by the DefaultActionInvocation ending up at the same code location (getMethod Class#1597) which fails with the given method name on the proxy.
WORKAROUND
The only functional workaround I found was to use the standard execute() method for the action and split the actions up into different classes.
Hope that helps.

Resources