Announcement Announcement Module
Collapse
No announcement yet.
OpenEntityManagerInViewFilter unnecessary for images Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • OpenEntityManagerInViewFilter unnecessary for images

    By default Roo uses OpenEntityManagerInViewFilter for /* causing an EntityManager to be instantiated for every HTTP request. EntityManagers are needed for requests to pages (controllers), but not for the images and other static resources contained in a html page.

    Shouldn't Roo only open an EntityManager for HTTP requests to controllers instead of also for static images/resources?

    web.xml:
    Code:
    ...
    <filter>
    	<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
    	<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    </filter>
    
    <filter-mapping>
    	<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
    	<url-pattern>/*</url-pattern>
    </filter-mapping>
    ...

    This happens when requesting a single png image file:
    Code:
    2010-02-24 14:13:28,052 [tomcat-http--10] DEBUG org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter - Using EntityManagerFactory 'entityManagerFactory' for OpenEntityManagerInViewFilter
    2010-02-24 14:13:28,053 [tomcat-http--10] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'entityManagerFactory'
    2010-02-24 14:13:28,053 [tomcat-http--10] DEBUG org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter - Opening JPA EntityManager in OpenEntityManagerInViewFilter
    2010-02-24 14:13:28,053 [tomcat-http--10] DEBUG org.springframework.security.web.FilterChainProxy - Converted URL to lowercase, from: '/static/images/es.png'; to: '/static/images/es.png'
    2010-02-24 14:13:28,054 [tomcat-http--10] DEBUG org.springframework.security.web.FilterChainProxy - Candidate is: '/static/images/es.png'; pattern is /**; matched=true
    2010-02-24 14:13:28,054 [tomcat-http--10] DEBUG org.springframework.security.web.FilterChainProxy - /static/images/es.png at position 1 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.context.SecurityContextPersistenceFilter@44fec1'
    2010-02-24 14:13:28,054 [tomcat-http--10] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
    2010-02-24 14:13:28,054 [tomcat-http--10] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@616f65. A new one will be created.
    2010-02-24 14:13:28,054 [tomcat-http--10] DEBUG org.springframework.security.web.FilterChainProxy - /static/images/es.png at position 2 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.logout.LogoutFilter@e6c33'
    2010-02-24 14:13:28,054 [tomcat-http--10] DEBUG org.springframework.security.web.FilterChainProxy - /static/images/es.png at position 3 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@e1c2c5'
    2010-02-24 14:13:28,054 [tomcat-http--10] DEBUG org.springframework.security.web.FilterChainProxy - /static/images/es.png at position 4 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.www.BasicAuthenticationFilter@1ba1c2b'
    2010-02-24 14:13:28,054 [tomcat-http--10] DEBUG org.springframework.security.web.FilterChainProxy - /static/images/es.png at position 5 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.savedrequest.RequestCacheAwareFilter@18f7705'
    2010-02-24 14:13:28,054 [tomcat-http--10] DEBUG org.springframework.security.web.FilterChainProxy - /static/images/es.png at position 6 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@1cf00a1'
    2010-02-24 14:13:28,054 [tomcat-http--10] DEBUG org.springframework.security.web.FilterChainProxy - /static/images/es.png at position 7 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.AnonymousAuthenticationFilter@4ee63e'
    2010-02-24 14:13:28,055 [tomcat-http--10] DEBUG org.springframework.security.web.authentication.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@6fa90ed4: Principal: anonymousUser; Password: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffc7f0c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: D256AC08E8C791E7D18189804E06AF13; Granted Authorities: ROLE_ANONYMOUS'
    2010-02-24 14:13:28,055 [tomcat-http--10] DEBUG org.springframework.security.web.FilterChainProxy - /static/images/es.png at position 8 of 10 in additional filter chain; firing Filter: '[email protected]1ee2e27'
    2010-02-24 14:13:28,055 [tomcat-http--10] DEBUG org.springframework.security.web.FilterChainProxy - /static/images/es.png at position 9 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.access.ExceptionTranslationFilter@180475'
    2010-02-24 14:13:28,055 [tomcat-http--10] DEBUG org.springframework.security.web.FilterChainProxy - /static/images/es.png at position 10 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.access.intercept.FilterSecurityInterceptor@cca280'
    2010-02-24 14:13:28,055 [tomcat-http--10] DEBUG org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource - Converted URL to lowercase, from: '/static/images/es.png'; to: '/static/images/es.png'
    2010-02-24 14:13:28,055 [tomcat-http--10] DEBUG org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource - Candidate is: '/static/images/es.png'; pattern is /pizza/**; matched=false
    2010-02-24 14:13:28,055 [tomcat-http--10] DEBUG org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource - Candidate is: '/static/images/es.png'; pattern is /topping/**; matched=false
    2010-02-24 14:13:28,055 [tomcat-http--10] DEBUG org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource - Candidate is: '/static/images/es.png'; pattern is /base/**; matched=false
    2010-02-24 14:13:28,056 [tomcat-http--10] DEBUG org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource - Candidate is: '/static/images/es.png'; pattern is /resources/**; matched=false
    2010-02-24 14:13:28,056 [tomcat-http--10] DEBUG org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource - Candidate is: '/static/images/es.png'; pattern is /static/**; matched=true
    2010-02-24 14:13:28,056 [tomcat-http--10] DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /static/images/es.png; Attributes: [permitAll]
    2010-02-24 14:13:28,056 [tomcat-http--10] DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@6fa90ed4: Principal: anonymousUser; Password: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffc7f0c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: D256AC08E8C791E7D18189804E06AF13; Granted Authorities: ROLE_ANONYMOUS
    2010-02-24 14:13:28,056 [tomcat-http--10] DEBUG org.springframework.security.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@1064398, returned: 1
    2010-02-24 14:13:28,056 [tomcat-http--10] DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Authorization successful
    2010-02-24 14:13:28,056 [tomcat-http--10] DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - RunAsManager did not change Authentication object
    2010-02-24 14:13:28,056 [tomcat-http--10] DEBUG org.springframework.security.web.FilterChainProxy - /static/images/es.png reached end of additional filter chain; proceeding with original chain
    2010-02-24 14:13:28,058 [tomcat-http--10] DEBUG org.springframework.security.web.access.ExceptionTranslationFilter - Chain processed normally
    2010-02-24 14:13:28,058 [tomcat-http--10] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - SecurityContext contents are anonymous - context will not be stored in HttpSession. 
    2010-02-24 14:13:28,059 [tomcat-http--10] DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
    2010-02-24 14:13:28,059 [tomcat-http--10] DEBUG org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter - Closing JPA EntityManager in OpenEntityManagerInViewFilter
    2010-02-24 14:13:28,059 [tomcat-http--10] DEBUG org.springframework.orm.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
    2010-02-24 14:13:28,059 [tomcat-http--10] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 12670172080
    Last edited by BlueApple; Feb 24th, 2010, 08:37 AM.

  • #2
    Yes, it should probably be matched to the dispatcher servlet rather than the root URL. Can you open a Jira ticket for this?

    Cheers,
    Stefan

    Comment


    • #3
      What's the workaround?

      If we want to work around this manually in the meantime, is it as simple as changing the filter mapping to this:

      Code:
      <filter-mapping>
          <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
          <url-pattern>/app/*</url-pattern>
      </filter-mapping>
      ?

      Comment


      • #4
        Originally posted by Stefan Schmidt View Post
        Yes, it should probably be matched to the dispatcher servlet rather than the root URL. Can you open a Jira ticket for this?
        I have just created a Jira ticket: http://jira.springframework.org/browse/ROO-655
        Originally posted by andrews View Post
        If we want to work around this manually in the meantime, is it as simple as changing the filter mapping to this:

        Code:
        <filter-mapping>
            <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
            <url-pattern>/app/*</url-pattern>
        </filter-mapping>
        ?
        hmm.... looking at web.xml and urlrewrite.xml, they already seem to use /app/*. hidden from the http client user. So every controller is already mapped to /app/**, BUT when using that URL pattern directly, OpenEntityManagerInViewFilter is bypassed! Which can be considered a bug. (Usually no problem, until lazy loading is used in the view.)

        OpenEntityManagerInViewFilter is bypassed for /app/** because by default, filters only apply to request dispatching instead of forward dispatching. But forwards are used by default for UrlRewrite filter, e.g. in:
        Code:
        <rule>
          <from>/**</from>
          <to>/app/$1</to>
        </rule>
        The problem can be fixed by using this in web.xml by replacing:
        Code:
        <filter-mapping>
            <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        with
        Code:
        <filter-mapping>
          <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
           <url-pattern>/app/*</url-pattern>
           <dispatcher>FORWARD</dispatcher>
        </filter-mapping>
        Using this will fix the whole problem: 1) images no longer use the OpenEntityManagerInViewFilter because they go through /static/**, 2) all controller will use OpenEntityManagerInViewFilter.

        Comment


        • #5
          Sounds good! Have you tested it?

          Comment


          • #6
            yup, is seems to work.
            Now I don't see the OpenEntityManagerInViewFilter in action for static resources, only for direct requests to controllers.

            Comment


            • #7
              Could you please give details of how you verified that, so I can test my app too?

              Comment


              • #8
                1)
                In log4j.properties file, add this line:
                Code:
                log4j.logger.org.springframework.orm.jpa.support=DEBUG
                Which will show when the OSIV filter (OpenEntityManagerInViewFilter) is used for HTTP requests.

                2)
                Start the webapp, and request a static resource in a browser. e.g.: http://localhost:8080/pizzashop/static/images/gb.png

                If you haven't implemented the fix, you will see:
                2010-02-26 01:04:35,134 [tomcat-http--2] DEBUG org.springframework.orm.jpa.support.OpenEntityMana gerInViewFilter - Using EntityManagerFactory 'entityManagerFactory' for OpenEntityManagerInViewFilter
                2010-02-26 01:04:35,152 [tomcat-http--2] DEBUG org.springframework.orm.jpa.support.OpenEntityMana gerInViewFilter - Opening JPA EntityManager in OpenEntityManagerInViewFilter
                2010-02-26 01:04:35,506 [tomcat-http--2] DEBUG org.springframework.orm.jpa.support.OpenEntityMana gerInViewFilter - Closing JPA EntityManager in OpenEntityManagerInViewFilter
                showing that an unwanted EntityManager is opened for a static resource.


                If you do implement the fix, you'll see no output, thus no unwanted EntityManager is opened.

                Comment


                • #9
                  Unfortunately that change breaks lazy-loading for my UserDetailsService. I'll have to do some debugging to find out why.

                  Comment


                  • #10
                    for debugging, do this:
                    web.xml:
                    Code:
                    	<filter>
                    		<filter-name>UrlRewriteFilter</filter-name>
                    		<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
                    		<init-param>
                                <param-name>logLevel</param-name>
                                <param-value>log4j</param-value>
                            </init-param>
                    	</filter>
                    log4j.properties:
                    Code:
                    log4j.logger.org.tuckey=DEBUG
                    You can check live rewritefilter settings at: http://localhost:8080/<context>/rewrite-status
                    (only at localhost)


                    Maybe you should put the OSIV filter as first filter listed in web.xml. Otherwise other filters might run outside the transaction.

                    Comment


                    • #11
                      Correction: as first filter, try UrlRewriteFilter, and then followed by OSIV filter.

                      Comment


                      • #12
                        Code:
                        <filter-mapping>
                           <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
                           <url-pattern>/app/*</url-pattern>
                           <dispatcher>FORWARD</dispatcher>
                        </filter-mapping>
                        should be changed to

                        Code:
                        <filter-mapping>
                           <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
                           <url-pattern>/app/*</url-pattern>
                           <dispatcher>REQUEST</dispatcher>  
                           <dispatcher>FORWARD</dispatcher>
                        </filter-mapping>
                        Otherwise OSIV wil not work for direct requests that go to /app/* without the UrlRewriteFilter.
                        This happens because of this Servlet spec rule:
                        1) The request comes directly from the client.

                        This is indicated by a <dispatcher> element with value REQUEST,
                        or by the absence of any <dispatcher> elements.
                        Which means that REQUEST is used by default, but when another <dispatcher> element exists other than REQUEST, than REQUEST won't be enabled by default.

                        Comment


                        • #13
                          I needed to add FORWARD to my springSecurityFilterChain, too, which is defined after UrlRewriteFilter and OpenEntityManagerInViewFilter.

                          Code:
                              <filter-mapping>
                                  <filter-name>springSecurityFilterChain</filter-name>
                                  <url-pattern>/*</url-pattern>
                          	    <dispatcher>REQUEST</dispatcher>
                          	    <dispatcher>FORWARD</dispatcher>
                              </filter-mapping>
                          Without adding "FORWARD", I believe I was getting NullPointerExceptions when using "authentication" injection in my controller methods. E.g. in the below snippet, "auth" would be null:

                          Code:
                          	@RequestMapping(value = "/appuser/task", method = RequestMethod.POST)    
                              public String create(Authentication auth, @Valid Task task, BindingResult result, ModelMap modelMap) {
                            //auth is null!!!

                          Comment


                          • #14
                            @mikej

                            Can you please add your springSecurityFilterChain setup as a comment to http://jira.springframework.org/browse/ROO-655 as well. This way we won't overlook it once we investigate this further.

                            Thanks for your help.

                            Stefan

                            Comment


                            • #15
                              @Stefan,

                              I apologize but I can't replicate this now. I was responding to a suggestion on the thread that we put UrlRewriteFilter first in our filter-mapping chain. I believe my issue may have been related to a lazily loaded list being called during authentication. But I'm unsure enough that I don't want to muddy the waters.

                              I'll just add a couple of "things to test" on the issue.

                              Comment

                              Working...
                              X