-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi all, I'm new to ZK and I have been looking for hours on how to integrate these three frameworks but have come up empty handed.
The issue is that when my DAO attempts to call
JpaUtil.getEntityManager()
from within a Shiro realm a nullpointerexception is thrown. I believe its due to Executions.getCurrent() returning null inside a Shiro realm. When I remove Shiro from the equation and access DAO from within the application everything works nicely. I'm initializing jpa util inside zk.xml with
<preference> <name>JpaUtil.PersistenceUnitName</name> <value>UserService</value> </preference> <listener> <description>JPA "OpenEntityManagerInView" Listener</description> <listener-class>org.zkoss.zkplus.jpa.OpenEntityManagerInViewListener</listener-class> </listener>
I see a lot on how to configure ZK with Spring Security and copying ThreadLocal items around. Is this the same issue here? Does anyone have any ideas on how to retrieve the EntityManager from within a Shiro realm? Any help is appreciated. thanks!
Yes, this sounds like a ThreadLocal issue. ZK uses ThreadLocals heavily, so if ZK code is executed in another Thread, the ThreadLocals must be copied.
I'm not familiar with Shiro, but I'm guessing it uses ThreadLocals just like Spring Security. Also, if Shiro uses some kind of custom threading, the ZK ThreadLocals have to be copied into Shiro threads.
First of all: are you using the event thread in ZK?
And which ZK version are you using?
The event thread is disabled by default in ZK 5.x but enabled in previous versions (3.x). If you have the event thread enabled, you'll have to do Shiro ThreadLocal copying (just like in ZK + Spring Security tutorials).
In order to better understand your problem, could you please do these steps:
1. Post the full stack trace here (NullPointerException).
2. Tell me what servlet container you're using. Is it Tomcat?
3. Find out the thread name by calling
Thread.currentThread().getName()
gekkio, thank you for your reply, we are using ZK 5.0.5. Just to be sure the event thread is disabled I have added to zk.xml
<system-config> <disable-event-thread/> </system-config>
and confirmed in startup logs
Feb 15, 2011 10:56:08 AM org.zkoss.zk.ui.sys.ConfigParser parseSystemConfig:552 INFO: The event processing thread is disabled Feb 15, 2011 10:56:09 AM org.zkoss.zkex.init.WebAppInit init:29
You are correct in your assumption, we are utilizing Tomcat as our container. The stack trace output you requested is below
java.lang.NullPointerException at org.zkoss.zkplus.jpa.JpaUtil.getEmMap(JpaUtil.java:69) at org.zkoss.zkplus.jpa.JpaUtil.initEntityManger(JpaUtil.java:228) at org.zkoss.zkplus.jpa.JpaUtil.getEntityManager(JpaUtil.java:140) at com.company.dose.DoseUserDAO.currentSession(DoseUserDAO.java:19) at com.company.dose.DoseUserDAO.findByLoginCredential(DoseUserDAO.java:38) at com.company.dose.security.DoseRealm.doGetAuthenticationInfo(DoseRealm.java:37) at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:175) at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:179) at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:264) at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198) at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106) at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:269) at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:247) at org.apache.shiro.web.filter.authc.AuthenticatingFilter.executeLogin(AuthenticatingFilter.java:48) at org.apache.shiro.web.filter.authc.FormAuthenticationFilter.onAccessDenied(FormAuthenticationFilter.java:154) at org.apache.shiro.web.filter.AccessControlFilter.onAccessDenied(AccessControlFilter.java:133) at org.apache.shiro.web.filter.AccessControlFilter.onPreHandle(AccessControlFilter.java:162) at org.apache.shiro.web.filter.PathMatchingFilter.preHandle(PathMatchingFilter.java:177) at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:131) at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:81) at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66) at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:359) at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:275) at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:344) at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:272) at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:81) 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:859) 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(Thread.java:619)
the thread name produced
http-8080-6
and to be thorough the method in our code that produced this was
EntityManager currentSession() { EntityManager em = null; try { System.out.println(Thread.currentThread().getName()); em = JpaUtil.getEntityManager(); } catch (Exception e) { e.printStackTrace(); } return em; }
Thanks again for the extra set of eyes :)
No problem, I'm happy to help :)
And thanks for the additional information. I can now see what the problem is. This isn't a ThreadLocal problem, because the thread that accesses the entity manager is the original HTTP request thread (http-8080-6 is a standard Tomcat thread name). The problem is exactly what you originally mentioned, the Execution is null.
Here's why:
As you might know, the standard request chain with ZK is HTTP->Filters->ZK Servlet->ZUL file.
The problem here is that you are trying to get an EntityManager using ZK-specific code, and you are actually doing this in a filter (= before ZK servlet has even seen the request).
So the Execution is null because ZK hasn't started handling the request yet.
I'm afraid I don't see any solution to this except that you should stop using ZK JpaUtil and move all the EntityManager stuff elsewhere. Personally I like to use Spring for this purpose because it provides everything you'll need to make that work.
It's possible to do everything manually, but you'll basically have to completely reimplement JpaUtil and OpenEntityManagerInViewListener.
Another option would be to remove the Shiro filter and move all access control into ZK Initiators, but I think that would require a lot of work because Shiro is based on the idea of using a filter.
So, to recap your possible solutions:
1. Use Spring (or some other framework that handles EntityManager creation/OpenEntityManagerInView stuff)
or
2. Reimplement JpaUtil/OpenEntityManagerInViewListener yourself without ZK-specific code
Just one more clarification:
You can probably still use Shiro as the web security framework if you like. What I'm recommending is the use of Spring (the core framework), not necessarily Spring Security (which is an addon).
So you'll have to replace JpaUtil with Spring JPA stuff, but can still use Shiro if you like. Or switch to Spring Security which is a good framework and a competitive alternative to Shiro :)
asegner, I'm tryng to use Shiro frame work. Could you post the steps to configure Shiro?
Asked: 2011-02-14 15:32:50 +0800
Seen: 1,062 times
Last updated: May 04 '11