views:

125

answers:

2

My application of OEIV Filter doesn't seem to be getting applied to my Struts actions. I am using Spring 3, Spring Security 3, Struts2, Tiles2 and JPA backed by Hibernate 3. When I try to access a collection for an entity in a struts action, unless the Entity has a fetch type of eager, I am getting a JPA LazyInitializationException. I see the filter in the stack trace, but can't figure out why it's not being applied.

Can anyone help with this?

Here's my web.xml filters and filter mappings:

    <!-- Filters -->
<filter>
    <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<!-- Filter Mappings -->
  <filter-mapping>
    <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
<filter-mapping>
      <filter-name>springSecurityFilterChain</filter-name>
      <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

My Entity:

@Entity
@Table(name = "DEALER")

public class Dealer implements Serializable {
    private static final long serialVersionUID = -1831628098752177382L;

    @Id
    @Basic(optional = false)
    @Column(name = "DEALER_ID")
    private Integer id;

    @Basic(optional = false)
    @Column(name = "NAME")
    private String name;
    ...    

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "dealer")
    private Set<InventoryPart> inventoryParts;

    ..getter/setter methods ommitted for brevity
}

The Struts 2 Action causing the error...

public class DealerAction extends BaseStrutsAction 
implements ModelDriven<Dealer>, Preparable {

public void prepare() throws Exception {
    PermissionedUser user= getAuthenticatedUser();
    if(user != null){
        dealer= user.getDealer();
        if(dealer != null){
            dealerId= dealer.getId();
        }
    }
}
...
public List<InventoryPart> getInventoryParts() {
    inventoryParts= new ArrayList<InventoryPart>(dealer.getInventoryParts());
    return inventoryParts;
}
// other methods ommitted for brevity

}

Finally the Stack Trace...

    83985 [http-8080-6] ERROR org.hibernate.LazyInitializationException - failed to lazily initialize a collection of role: ...model.Dealer.inventoryParts, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ...model.Dealer.inventoryParts, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
    at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:186)
    at org.apache.struts2.util.MakeIterator.convert(MakeIterator.java:82)
    at org.apache.struts2.components.IteratorComponent.start(IteratorComponent.java:270)
    at org.apache.struts2.views.jsp.ComponentTagSupport.doStartTag(ComponentTagSupport.java:53)
    at org.apache.jsp.WEB_002dINF.jsp.dealer.list_002dinventory_002dparts_jsp._jspx_meth_s_005fiterator_005f0(list_002dinventory_002dparts_jsp.java:169)
    at org.apache.jsp.WEB_002dINF.jsp.dealer.list_002dinventory_002dparts_jsp._jspService(list_002dinventory_002dparts_jsp.java:121)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)
    at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:551)
    at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:488)
    at org.apache.jasper.runtime.JspRuntimeLibrary.include(JspRuntimeLibrary.java:968)
    at org.apache.jasper.runtime.PageContextImpl.doInclude(PageContextImpl.java:650)
    at org.apache.jasper.runtime.PageContextImpl.include(PageContextImpl.java:644)
    at org.apache.tiles.jsp.context.JspTilesRequestContext.include(JspTilesRequestContext.java:103)
    at org.apache.tiles.jsp.context.JspTilesRequestContext.dispatch(JspTilesRequestContext.java:96)
    at org.apache.tiles.renderer.impl.UntypedAttributeRenderer.write(UntypedAttributeRenderer.java:62)
    at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:670)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:336)
    at org.apache.tiles.template.InsertAttributeModel.renderAttribute(InsertAttributeModel.java:210)
    at org.apache.tiles.template.InsertAttributeModel.end(InsertAttributeModel.java:126)
    at org.apache.tiles.jsp.taglib.InsertAttributeTag.doTag(InsertAttributeTag.java:311)
    at org.apache.jsp.WEB_002dINF.jsp.fragments.root_jsp._jspx_meth_tiles_005finsertAttribute_005f4(root_jsp.java:291)
    at org.apache.jsp.WEB_002dINF.jsp.fragments.root_jsp._jspService(root_jsp.java:151)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
    at org.apache.tiles.servlet.context.ServletTilesRequestContext.forward(ServletTilesRequestContext.java:241)
    at org.apache.tiles.servlet.context.ServletTilesRequestContext.dispatch(ServletTilesRequestContext.java:222)
    at org.apache.tiles.renderer.impl.TemplateAttributeRenderer.write(TemplateAttributeRenderer.java:44)
    at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:670)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:690)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:644)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:627)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:321)
    at org.apache.struts2.views.tiles.TilesResult.doExecute(TilesResult.java:105)
    at org.apache.struts2.dispatcher.StrutsResultSupport.execute(StrutsResultSupport.java:186)
    at com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:362)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:266)
    at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:165)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:50)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:122)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:195)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:195)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:179)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:94)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:235)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:89)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:130)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:267)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:126)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:138)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:165)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:179)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:176)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:235)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:176)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.LoggingInterceptor.intercept(LoggingInterceptor.java:56)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at ...struts.interceptors.TermsAndConditionsInterceptor.intercept(TermsAndConditionsInterceptor.java:45)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:165)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:50)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:122)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:195)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:195)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:179)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:235)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:89)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:126)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:138)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:195)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:94)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:165)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:179)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:176)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at ...struts.interceptors.SpringSecurityInterceptor.intercept(SpringSecurityInterceptor.java:27)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:488)
    at org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:395)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:288)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:300)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:95)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:300)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:300)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:300)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:300)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:300)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:300)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:300)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:300)
    at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:109)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:300)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:133)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:113)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Unknown Source)

Any/All replies appreciated! Thanks in advance.


Revised: Added Spring configuration

    <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx" 
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"&gt;

    <!-- Persistence Related Beans here -->
    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName">
            <value>java:comp/env/jdbc/orcl</value>
        </property>
    </bean>  
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource">
            <ref local="dataSource"/>
        </property>
    </bean>
    <!-- the transactional advice (i.e. what 'happens'; see the <aop:advisor/> bean below) -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!-- the transactional semantics... -->
        <tx:attributes>
            <!-- all methods starting with 'get' are read-only -->
            <tx:method name="get*" read-only="true" />
            <tx:method name="find*" read-only="true" />
            <tx:method name="load*" read-only="true" />
            <!-- other methods use the default transaction settings (see below) -->
            <tx:method name="*" propagation="REQUIRED" />
        </tx:attributes>
    </tx:advice>
    <!-- Pointcut Expressions For Transaction Advice -->
    <aop:config proxy-target-class="true">
        <aop:pointcut id="txAdvisor" expression="execution(* com.mycompany.mypackage.service.*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txAdvisor" />
    </aop:config>

    <!-- Dao Classes -->
    <bean id="dealerDao" class="com.mycompany.mypackage.dao.jpa.DealerDaoImpl"/>
    <bean id="vehicleDao" class="com.mycompany.mypackage.dao.jpa.VehicleDaoImpl"/>
    <bean id="manufacturedPartDao" class="com.mycompany.mypackage.dao.jpa.ManufacturedPartDaoImpl"/>

    <!--  Service Beans -->

    <bean id="dealerService" class="com.mycompany.mypackage.service.impl.DealerServiceImpl">
        <property name="dealerDao" ref="dealerDao"/>
    </bean>

    <bean id="vehicleService" class="com.mycompany.mypackage.service.impl.VehicleServiceImpl">
        <property name="vehicleDao" ref="vehicleDao"/>
    </bean>

    <bean id="manufacturedPartService" class="com.mycompany.mypackage.service.impl.ManufacturedPartServiceImpl">
        <property name="manufacturedPartDao" ref="manufacturedPartDao"/>
        <property name="dealerDao" ref="dealerDao"/>
    </bean>

Revised: This is where the dealer object gets set to the permissioned user:

public class PermissionedUserContextMapperImpl implements
    UserDetailsContextMapper, PermissionedUserContextMapper {

private UserDao userDao;
private DealerService dealerService;

public UserDetails mapUserFromContext(DirContextOperations context,
        String userName, Collection<GrantedAuthority> authorites) {

    PermissionedUser user = userDao.getUser(userName);
    if (user != null && (user.getUserId() != null)) {
        user.setAuthorities((List<GrantedAuthority>) authorites);
        userDao.setLastLoginDate(new Long(user.getUserId()));
        // Find if user is a dealer.
        Long userId= new Long(user.getUserId());
        Dealer dealer = userDao.getDealerForUser(userId);
        if (dealer.getId() != null) {
            // this is a temporary hack because the JPA ORM is not tied to
            // the
            // User/Group structure.
            Dealer jpaManagedDealer = dealerService.getDealer(dealer.getId());
            user.setDealer(jpaManagedDealer);
        }
    }

    return user;
}
...

}

Also in the Struts Action...

public class DealerAdminAction extends BaseStrutsAction implements ModelDriven<Dealer>, Preparable {

private static final long serialVersionUID = -5848040074874790864L;
private DealerService dealerService;
private Dealer dealer;
private Integer id;

public Integer getId() {
    return id;
}
public void setId(Integer id) {
    this.id = id;
}

public void prepare() throws Exception {
    if(id == null || id.intValue() == 0){
        dealer= new Dealer();
    }else{
        dealer= dealerService.getDealer(id);
    }
}

@SkipValidation
public String getView() throws Exception {
    PermissionedUser user= getAuthenticatedUser();
    if(! user.isADealer()){
        user.setDealer(dealer);
    }
    return SUCCESS;
}

public Dealer getModel() {
    return dealer;
}
...

}


Re-factored Code solves the LazyInitializationException:

public class DealerAdminAction ... {

    ...        
    @Override
    @SkipValidation
    public String execute() throws Exception {
        return SUCCESS;
    }

    public Dealer getModel() {
        return dealer;
    }

    public void prepare() throws Exception {
        if(id == null || id.intValue() == 0){
            dealer= new Dealer();
        }else{
            dealer= dealerService.getDealer(id);
            PermissionedUser user= getAuthenticatedUser();
            if(! user.isADealer()){
                user.setDealer(dealer);
            }
        }
    }
    ...
}
A: 

This appears to be a problem with your transaction scope. In Hibernate / JPA a one-to-many reference is by default lazy. This means that the entities in the collection are not retrieved until their are accessed. Accessing lazily loaded values is only possible within the same transaction in which you loaded the parent object.

In your case you retrieve an instance of Dealer in the prepare() method, but you access the inventoryParts in a different method of your Action. There is a little too few context here but it is likely that those two things happen in a different transaction, resulting in the LazyInitializationException.

You could take a look at your transaction propagation or take a different approach in accessing the inventoryParts, for instance adding lazy = false like below:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "dealer", lazy = false)
private Set<InventoryPart> inventoryParts;

This might however not be what you want, because it always loads ALL InvertoryParts associated to the Dealer. You can also make sure you access the collection within the same transaction by accessing it in the prepare() method.

Just some different approaches. There is no best answer here, because your performance might be at stake.

Jaap Coomans
This is not totally accurate. Accessing a lazily loaded association only requires an active EntityManager, which is the point of using the OEIV here (and a lazy association can be loaded in another transaction than the one used to load the parent, as long as you have an active EntityManager).
Pascal Thivent
That's what I understood as well. OEIV was meant to address this problem specifically, so I have some sort of config problem...
Griff
You're correct, I overlooked the OEIV part, which is quite essential to the question.... Sorry!
Jaap Coomans
+1  A: 

Is it possible that getAuthenticatedUser() is returning a detached user object? Then when you do user.getDealer() the dealer object will also be detached leading to the lazy load exception.

Pablojim
Maybe. The user object is not a JPA managed object, it is JDBC managed. There are 2 places when the user object has the dealer object set to it. One is in the spring UserDetailsContextMapper, and the other is in a struts action. When the dealer logs in, their dealer object is set into the permissioned user so that it doesn't have to be retrieved, and so that it can be used to limit queries to just their data. When a system admin logs in, the sysadmin person selects a dealer to manage from a list, and I set the dealer object to the user so I can reuse artifacts. See Addl. code above
Griff
Ok, so the LazyInitializationException only happens when the dealer object is set into the PermissionedUser object in the struts action, not when the dealer is set into the PermissionedUser in the UserDetailsContextMapper. So, this is starting to look like the right answer. Why would the object be detached in the struts object? Is it because my struts method is get* and that is a read-only transaction in the applicationContext.xml file?
Griff
Ok, the problem is related somehow to transactions, so I guess I don't understand this as well as I wish I did. In my original code, the problem only showed up in the struts action. By using the struts Prepareable interceptor and the paramsPrepareParamsStack, I was retrieving the dealer in the prepare method, and setting the dealer to the user in a different method. When I moved the method call to set the dealer to the user object in the same transactional method, the LazyInitializationException disappears. Refactored working code posted above.
Griff