0

ZK / JPA / Shiro Security

asked 2011-02-14 15:32:50 +0800

asegner gravatar image asegner
51 1

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!

delete flag offensive retag edit

7 Replies

Sort by ยป oldest newest

answered 2011-02-15 05:40:21 +0800

gekkio gravatar image gekkio flag of Finland
899 1
http://gekkio.fi/blog

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()
Just log that before accessing the EntityManager and post it here.

link publish delete flag offensive edit

answered 2011-02-15 10:17:36 +0800

asegner gravatar image asegner
51 1

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 :)

link publish delete flag offensive edit

answered 2011-02-15 11:12:17 +0800

gekkio gravatar image gekkio flag of Finland
899 1
http://gekkio.fi/blog

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

link publish delete flag offensive edit

answered 2011-02-15 11:38:07 +0800

asegner gravatar image asegner
51 1

Thanks for the recommendations, I guess we will have to take a look into Spring instead of Shiro

link publish delete flag offensive edit

answered 2011-02-16 08:18:39 +0800

gekkio gravatar image gekkio flag of Finland
899 1
http://gekkio.fi/blog

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 :)

link publish delete flag offensive edit

answered 2011-02-23 07:05:03 +0800

acirasa gravatar image acirasa
48 1

I have shiro and zk in my project

I use another EntityMangerfactory for read authentication information.

Shirorealm access authentication informations only in readonly mode, so this is not an issue

link publish delete flag offensive edit

answered 2011-05-04 12:14:41 +0800

marcelomourasouza gravatar image marcelomourasouza
24

asegner, I'm tryng to use Shiro frame work. Could you post the steps to configure Shiro?

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2011-02-14 15:32:50 +0800

Seen: 1,062 times

Last updated: May 04 '11

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More