Search code examples
ejboracle-adfinject

How to inject EJB Session to ADF ManagedBean


I'm researching about Oracle ADF and EJB. I'm using ADF faces as View and Controller, EJB as service. I don't want to use ADF model to bind EJB Session to interact with ADF faces. So, I have create a managed bean to interact with ADF faces

ManagedBean

public class EmployeeManagementController {
    private List<Jobs> jobList;
    private RichTable jobTable;
    private RichPanelGroupLayout panelGroup;

    //@EJB(mappedName = "HRSysDemo.JobBean",name = "jobBean")
    @EJB
    private JobBeanLocal jobBean; 
    /*...*/

    public void initPage() {
        System.out.println("TESTING . . .");
        jobList = jobBean.getJobsFindAll();
    }
}

Session Bean

@Stateless(mappedName = "HRSysDemo/JobBean")
public class JobBean implements JobBeanRemote, JobBeanLocal {
    @Resource
    SessionContext sessionContext;
    @PersistenceContext(unitName = "Model")
    private EntityManager em;
    /*...*/
    public List<Jobs> getJobsFindAll() {
        return em.createNamedQuery("Jobs.findAll").getResultList();
    }
}

My problem is "jobBean" always get "null", it means EJB Session can not inject to ManagedBean. I have tried some ways, such as change interface injection (Remote interface), specify name and mappedName, but it's still not working. So, how can I inject a EJB SessionBean into a ADF ManagedBean?

Thank in advance!


Solution

  • I have made it by following some step in here, It's not working well but I have fixed them. I hope this will be helpful for someone else:

    Here my code:

    ELResolverWithInjectEJB.java

    import java.lang.reflect.AccessibleObject;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    import java.util.Hashtable;
    import java.util.List;
    import java.util.Map;
    
    import com.google.common.collect.Maps;
    import com.google.common.collect.Lists;
    
    import java.util.concurrent.ConcurrentHashMap;
    import javax.el.ELContext;
    import javax.el.MapELResolver;
    
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    import oracle.adf.controller.metadata.model.beans.ManagedBean;
    import oracle.adf.controller.metadata.model.beans.ManagedBeanScopeType;
    
    /* Illegal internal package import. Please use public API */
    import oracle.adfinternal.controller.beans.AnnotationUtils;
    import oracle.adfinternal.controller.beans.ManagedBeanFactory;
    import oracle.adfinternal.controller.state.ScopeMap;
    
    public class ELResolverWithInjectEJB extends MapELResolver {
        private static Method getManagedBeanScopeType = null;
        private static Method shouldIncludeHigherScopes = null;
        private static Method newInstance = null;
        static {
            try {
                getManagedBeanScopeType = ScopeMap.class.getDeclaredMethod("getManagedBeanScopeType", null);
                getManagedBeanScopeType.setAccessible(true);
                shouldIncludeHigherScopes = ScopeMap.class.getDeclaredMethod("shouldIncludeHigherScopes", null);
                shouldIncludeHigherScopes.setAccessible(true);
                newInstance = ManagedBeanFactory.class.getDeclaredMethod("newInstance", ManagedBean.class);
                newInstance.setAccessible(true);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        public ELResolverWithInjectEJB() {
            super();
        }
    
        @SuppressWarnings("oracle.jdeveloper.java.semantic-warning")
        public Object getValue(ELContext elContext, Object base, Object var) {
            ScopeMap scope = (ScopeMap) (base instanceof ScopeMap ? base : null);
            if (scope == null || scope.containsKey(var))
                return super.getValue(elContext, base, var);
            Object bean = null;
            try {
                ManagedBeanFactory mbf = ManagedBeanFactory.getInstance();
                ManagedBean managedBean = mbf.getManagedBeanInCurrentPageFlow((String) var);
                ManagedBeanScopeType expectedScope = (ManagedBeanScopeType) getManagedBeanScopeType.invoke(scope, null);
                if (((Boolean) shouldIncludeHigherScopes.invoke(scope, null)) &&
                    (managedBean == null || !managedBean.getScope().equals(expectedScope))) {
                    managedBean = mbf.getManagedBeanInAdfPageFlow((String) var);
                    }
                if (managedBean != null && managedBean.getScope().equals(expectedScope)) {
                    bean = newInstance.invoke(mbf, managedBean);
                    if (bean != null) {
                        scope.put((String) var, bean);
                        EJBInjector.inject(bean);
                        AnnotationUtils.runPostConstructIfSpecified(bean, managedBean.getName(), managedBean.getScope());
                        elContext.setPropertyResolved(true);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return bean;
        }
    
        static class EJBInjector {
            private static Map<String, List> processed = Maps.newConcurrentMap();
            private static Map<String, String> mappedBean = Maps.newConcurrentMap();
            private static Context ctx = null;
            static {
                try {
                    ctx = getInitialContext();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
            @SuppressWarnings("unchecked")
            public static void inject(Object o) throws IllegalAccessException, InvocationTargetException, NamingException {
                List<AccessibleObject> inj = null;
                if (!processed.containsKey(o.getClass().getName())) {
                    inj = Lists.newArrayList();
                    for (Field field : o.getClass().getDeclaredFields()) {
                        if (field.getAnnotation(Autoinjector.class) != null) {
                            field.setAccessible(true);
                            inj.add(field);
                            Autoinjector rm = field.getAnnotation(Autoinjector.class);
                            mappedBean.put(convertKey(o, field), rm.ejbMappedName());
                        }
                    }
                    processed.put(o.getClass().getName(), inj.isEmpty() ? null : inj);
                }
                inj = inj != null ? inj : processed.get(o.getClass().getName());
                if (inj != null) {
                    for (AccessibleObject i : inj) {
                        ((Field) i).set(o,ctx.lookup(mappedBean.get(convertKey(o, (Field) i)) + "#" +
                                                       ((Field) i).getType().getName()));
                    }
                }
            }
    
            private static String convertKey(Object o, Field f) {
                return o != null && f != null ? o.getClass().getName() + "_" + f.getType().getName() + "_" + f.getName() :
                           "";
            }
    
            @SuppressWarnings("unchecked")
            public static Context getInitialContext() throws NamingException {
                Hashtable env = new Hashtable();
                env.put(Context.INITIAL_CONTEXT_FACTORY,[your_provide]);
                env.put(Context.PROVIDER_URL, [your_url_server]);
                return new InitialContext(env);
                }
            }
        }
    

    Autoinjector.java

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Autoinjector {
        String ejbMappedName() default "";
    }
    

    faces-config.xml

    <application>
        <default-render-kit-id>oracle.adf.rich</default-render-kit-id>
        <el-resolver>[your_package].ELResolverWithInjectEJB</el-resolver>
    </application>
    

    In controller

    public class DicOrgDetailPageController extends BaseController {
    
        private static final long serialVersionUID = 2332665929048532518L;
    
        /* -- Services -- */
        @Autoinjector(ejbMappedName = "mytest")
        private SB_DicOrgService sbDicOrgService; 
    }