Ok, here we go... Step 1: use a RealmIdentifierInterceptor like this (I've removed a few quirks which were specific to our solution):
/** * This incerceptor intercepts calls to SessionBeans which have been annotated * appropriately. It determines the principal issuing the request and identifies * the target realm. It then injects the EntityManager for the chosen realm. * * @author Jörg Henne */ public class RealmIdentifierInterceptor { private static final Logger logger = Logger .getLogger(RealmIdentifierInterceptor.class); private static final String EM_JNDI_PREFIX = "java:/EntityManagers/"; /** * A cache of injectors, indexed by class. */ private Map<Class, Field> fieldCache = new HashMap<Class, Field>(); @Resource javax.ejb.SessionContext sctx; @AroundInvoke public Object identifyRealm(InvocationContext ctx) throws Exception { Field field = getFieldForInjection(ctx.getBean().getClass()); if (null != field) { Principal callerPrincipal = sctx.getCallerPrincipal(); if (null == callerPrincipal) throw new EJBAccessException( "No caller principal to detect the realm name from"); String realmName = getRealmName(callerPrincipal.getName()); try { logger.debug("Injecting EM for realm " + realmName + " during call to " + ctx.getBean()); String emName = EM_JNDI_PREFIX + realmName; EntityManager em = (EntityManager) new InitialContext().lookup(emName); field.set(ctx.getBean(), em); } catch (NamingException e) { throw new EJBAccessException("Realm " + realmName + " not found"); } } return ctx.proceed(); } /** * Extract Realm name from Windows-style realm\\username pattern. * * @param principalName * * @return */ private String getRealmName(String principalName) { int idx = principalName.indexOf('\\'); if (idx <= 0) throw new EJBAccessException("Can't parse the principal name " + principalName); return principalName.substring(0,idx); } /** * Get the injector for the given class. Returns null, if the * class doesn't declare a field annotated with * * @RealmBasedPersistenceContext. * * @param clazz * @return */ private Field getFieldForInjection(Class<? extends Object> clazz) { // a null injector is possible and idicates a class which declared // this interceptor, but doesn't declare a field annotated with // @RealmBasedPersistenceContext. if (fieldCache.containsKey(clazz)) return fieldCache.get(clazz); Field[] fields = clazz.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[ i ]; RealmBasedPersistenceContext annotation = field .getAnnotation(RealmBasedPersistenceContext.class); if (null != annotation) { logger.info("Found field for EntityManager injection: " + field + " on " + field.getDeclaringClass()); field.setAccessible(true); fieldCache.put(clazz, field); return field; } } logger.warn("Class " + clazz + " is annotated with @RealmIdentifierInterceptor bit doesn't " + "declare a field annotated with @RealmBasedPersistenceContext"); // nothing found - put null map entry to indicate invalid class fieldCache.put(clazz, null); return null; } } Step 2: Define the following annotation interface: import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface RealmBasedPersistenceContext { } Step 3: Annotate your session beans with @Interceptors({RealmIdentifierInterceptor.class}) and your EntityManager field with @RealmBasedPersistenceContext A simple bean would thus look like this: @Stateless @Interceptors({RealmIdentifierInterceptor.class}) public class YadaBean implements Yada { private static final Logger logger = Logger .getLogger(AccountAdminDAOBean.class); @RealmBasedPersistenceContext private EntityManager em; ... } Step 4: Implement a custom login module which is able to deal with principal names using the pattern realmName/userName. Our solution is rather complicated in this area, insofar as we subclassed a specialized Principal from SimplePrincipal which parses the compound realmName/userName into its separate parts. The customized LoginModule converts an incoming SimplePrincipal into the specialized one, but clients are preferred to supply the specialized one directly, if possible. The problem with this solution is that that the JBoss login mechanism with ClientLoginModule and the server-side handling silently dump the specialized Principal instance and replace it with a simple one again. Therefore it is easier to just stick with SimplePrincipals and deal with the compound principal name in your LoginModule. Step 5: Implement an EJB which lists the configured realms from JNDI like this: @Stateless public class RealmListServiceBean implements RealmListService { /* * (non-Javadoc) * * @see de.hess.zas.business.RealmListService#listRealmNames() */ public List listRealmNames() throws NamingException { NamingEnumeration name = new InitialContext() .list("java:/EntityManagers"); List results = new ArrayList(); while (name.hasMoreElements()) { results.add(name.next().getName()); } return results; } } In order to make this work, you have to grant access to this bean to unauthenticated users, obviously. There are several ways to do this: Deploy the bean outside the security domain Except the bean from security Allow logon using a special guest user (that's our solution) I hope, this explanation was helpful. Joerg Henne View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3952942#3952942 Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3952942 Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ JBoss-user mailing list JBoss-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jboss-user