Page 2 of 2 FirstFirst 12
Results 11 to 18 of 18

Thread: Using Bean Factory on 2nd attempt causes errors

  1. #11
    Join Date
    Jan 2006
    Location
    Huddersfield/Coventry
    Posts
    28

    Unhappy

    Thanks for your help. I am at the stage of giving up. Dont seem to be making much progress. I have tried different combinations but the same null pointer exception is being thrown.

    Using the classloader (looking at the javadoc getInstance() uses this to look for the xml file) i have looked at what resources it is able to see and it does find the xml file.

    "jar:file:/C:/Program Files/jboss-4.0.5.GA/server/default/tmp/deploy/tmp32554AztekApplication.ear!/applicationContext.xml"

    I even passed this into the constructor of

    setBeanFactoryLocator(SingletonBeanFactoryLocator. getInstance(loader.getResource("applicationContext .xml").toString()));

    If you have any other ideas please let me know as i am out of them right now. The only work around is to pass the manager in via the service layer. Something which i would like to avoid as it couples the business code into the service layer rather then into the EJB layer

  2. #12
    Join Date
    Dec 2006
    Location
    Normal, Illinois
    Posts
    277

    Default

    Quote Originally Posted by akhtara7 View Post
    "jar:file:/C:/Program Files/jboss-4.0.5.GA/server/default/tmp/deploy/tmp32554AztekApplication.ear!/applicationContext.xml"
    Looks like the file you are pointing at is in the root of your deployed EAR. This would not be on the classpath by default. Try placing this in the root of a jar file (your ejb jar file). As this should get the xml file on the classpath of your session bean so that you can load an application context from this .xml file.

    I don't believe the syntax you have above is valid for Spring as it expects a valid URL when loading resources. You can always start simple by dropping this file in the root of your c: drive - "file:/C:/applicationContext.xml" to see if you can get that working and then work towards a file that is included with your EAR/Jar(s).
    Caleb Washburn

  3. #13
    Join Date
    Jan 2006
    Location
    Huddersfield/Coventry
    Posts
    28

    Default

    The xml file was initially under the ejb jar file but resulted in the same error. So i moved it into the ear file to see if that helped.

    I have already tried moving the file to my c:\ to see if i can get it working that way but the same error is still being thrown.

    Below is the class and full error trace.

    java.lang.NullPointerException
    at org.springframework.ejb.support.AbstractEnterprise Bean.getBeanFactory(AbstractEnterpriseBean.java:15 4)
    at uk.co.aztekSolutions.server.ejb.expenses.ExpensesE JBBean.init(ExpensesEJBBean.java:47)
    at uk.co.aztekSolutions.server.ejb.expenses.ExpensesE JBBean.getExpensesManager(ExpensesEJBBean.java:78)
    at uk.co.aztekSolutions.server.ejb.expenses.ExpensesE JBBean.getAllRecords(ExpensesEJBBean.java:93)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNex t(MethodInvocation.java:112)
    at org.jboss.ejb3.interceptor.InvocationContextImpl.p roceed(InvocationContextImpl.java:166)
    at org.jboss.ejb3.interceptor.EJB3InterceptorsInterce ptor.invoke(EJB3InterceptorsInterceptor.java:63)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNex t(MethodInvocation.java:101)
    at org.jboss.ejb3.entity.TransactionScopedEntityManag erInterceptor.invoke(TransactionScopedEntityManage rInterceptor.java:54)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNex t(MethodInvocation.java:101)
    at org.jboss.ejb3.AllowedOperationsInterceptor.invoke (AllowedOperationsInterceptor.java:46)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNex t(MethodInvocation.java:101)
    at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPoli cy.java:79)
    at org.jboss.aspects.tx.TxInterceptor$Required.invoke (TxInterceptor.java:191)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNex t(MethodInvocation.java:101)
    at org.jboss.aspects.tx.TxPropagationInterceptor.invo ke(TxPropagationInterceptor.java:76)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNex t(MethodInvocation.java:101)
    at org.jboss.ejb3.stateless.StatelessInstanceIntercep tor.invoke(StatelessInstanceInterceptor.java:62)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNex t(MethodInvocation.java:101)
    at org.jboss.aspects.security.AuthenticationIntercept or.invoke(AuthenticationInterceptor.java:77)
    at org.jboss.ejb3.security.Ejb3AuthenticationIntercep tor.invoke(Ejb3AuthenticationInterceptor.java:102)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNex t(MethodInvocation.java:101)
    at org.jboss.ejb3.ENCPropagationInterceptor.invoke(EN CPropagationInterceptor.java:47)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNex t(MethodInvocation.java:101)
    at org.jboss.ejb3.asynchronous.AsynchronousIntercepto r.invoke(AsynchronousInterceptor.java:106)
    at org.jboss.aop.joinpoint.MethodInvocation.invokeNex t(MethodInvocation.java:101)
    at org.jboss.ejb3.stateless.StatelessContainer.localI nvoke(StatelessContainer.java:211)
    at org.jboss.ejb3.stateless.StatelessLocalProxy.invok e(StatelessLocalProxy.java:79)
    at $Proxy87.getAllRecords(Unknown Source)


    The EJBBean

    public class ExpensesEJBBean extends AbstractStatelessSessionBean implements ExpensesEJBLocal, ExpensesEJB {
    private ExpensesManager expensesManager = null;
    private Object manualExpensesManager = null;

    public ExpensesEJBBean() {
    super();
    init();
    }


    private void init() {
    try {
    BeanFactory factory = null;
    System.out.println("####SETTING LOCATOR");
    setBeanFactoryLocator(SingletonBeanFactoryLocator. getInstance("file:/C:/applicationContext.xml"));

    factory = getBeanFactory();

    System.out.println("FACTORY IS = " + factory);
    expensesManager = (ExpensesManager) factory.getBean("expensesManager");
    } catch (Exception e) {
    System.out.println("Spring Expenses Manager load ERROR - " + e.getMessage());
    e.printStackTrace();
    } finally {
    System.out.println("OBJECT IS = " + expensesManager);
    }
    }

    protected void onEjbCreate() throws CreateException {
    }

    public ExpensesManager getExpensesManager() throws DomainLayerException {
    if (expensesManager == null) {
    init();
    }

    if (expensesManager == null)
    System.out.println("expensesManager NULL");
    else
    System.out.println("expensesManager VALID");
    return expensesManager;
    }

    public List getAllRecords(String month) throws EJBException {
    System.out.println("getAllRecords");
    try {
    System.out.println("expensesManager= " + expensesManager);

    return getExpensesManager().getAllRecords(month).getList( );
    } catch (DomainLayerException e) {
    e.printStackTrace();
    throw new EJBException(e);
    }
    }
    }


    Not sure if the error is being caused because it cant find the xml file or if i have missed something else out.

  4. #14
    Join Date
    Dec 2006
    Location
    Normal, Illinois
    Posts
    277

    Default

    I see the problem. You need to move your call to the init() method that you have created to the onEjbCreate() method. The problem is Spring does not create the application Context until after the ejb create method runs. Therefore, calling it in the constructor is why you are getting a null pointer exception.

    Code:
    public class ExpensesEJBBean extends AbstractStatelessSessionBean implements ExpensesEJBLocal, ExpensesEJB {
        private ExpensesManager expensesManager = null;
        private Object manualExpensesManager = null;
    
        public ExpensesEJBBean() {
            super();
    //remove call to init()
        }
    
    
        private void init() {
            try {
                BeanFactory factory = null;
                System.out.println("####SETTING LOCATOR");
                setBeanFactoryLocator(SingletonBeanFactoryLocator.  getInstance("file:/C:/applicationContext.xml"));
                
                factory = getBeanFactory();
    
                System.out.println("FACTORY IS = " + factory);
                expensesManager = (ExpensesManager) factory.getBean("expensesManager");
            } catch (Exception e) {
                System.out.println("Spring Expenses Manager load ERROR - " + e.getMessage());
                 e.printStackTrace();
            } finally {
                System.out.println("OBJECT IS = " + expensesManager);
            }
        }
    
        protected void onEjbCreate() throws CreateException {
    init();
        }
    
        public ExpensesManager getExpensesManager() throws DomainLayerException {
    //don't need all the checks for the expenseManager == null
    return expensesManager;
        }
    
        public List getAllRecords(String month) throws EJBException {
            System.out.println("getAllRecords");
            try {
                System.out.println("expensesManager= " + expensesManager);
    
                return getExpensesManager().getAllRecords(month).getList(  );
            } catch (DomainLayerException e) {
                e.printStackTrace();
                throw new EJBException(e);
            }
        }
    }
    That should get you past the null pointer exception that you are seeing.
    Caleb Washburn

  5. #15
    Join Date
    Jan 2006
    Location
    Huddersfield/Coventry
    Posts
    28

    Default

    Just given that a try i moved the init call into onEjbCreate, got a nullpointer exception but this time on

    return getExpensesManager().getAllRecords(month).getList( );

    The object returned by getExpensesManager() is null, this should have been set by the call to init.

    I put some debug statements into create method but nothing is getting displayed. Thinking back to the whole EJB lifecyle the onEJBCreate call is done after the container calls ejbCreate. So i dont think this call is being made

    I am starting to think whether the container is interpreting the bean as an EJB (oh just remebered on the jboss startup does actually say the bean has been deployed).

    Coud be a Spring thing???

    The EJB is being called via service object using

    org.springframework.jndi.JndiObjectFactoryBean

    From what i have read of the docs this should return an EJB Bean

  6. #16
    Join Date
    Dec 2006
    Location
    Normal, Illinois
    Posts
    277

    Default

    The onEjbCreate() method should be called when the EJB is put into the "ready pool". This occurs before a bean instance can be returned from a jndi lookup. Are you saying the the onEjbCreate() method is never being called?

    I noticed that you don't have the @Stateless on the class.

    Code:
    @Stateless
    public class ExpensesEJBBean extends AbstractStatelessSessionBean implements ExpensesEJBLocal, ExpensesEJB {
    }
    
    If the onEjbCreate() method is not being called then there is no way the Spring initialization is done. Code from the AbstractStatelessSessionBean

    Code:
    public void ejbCreate() throws CreateException {
       loadBeanFactory();
       onEjbCreate();
    }
    This would lead me to believe that the session bean is not setup correctly in JBoss as the EJB lifecycle methods (ejbCreate(), etc) are not being called.
    Caleb Washburn

  7. #17
    Join Date
    Jan 2006
    Location
    Huddersfield/Coventry
    Posts
    28

    Default

    Quote Originally Posted by cwash5 View Post
    The onEjbCreate() method should be called when the EJB is put into the "ready pool". This occurs before a bean instance can be returned from a jndi lookup. Are you saying the the onEjbCreate() method is never being called?

    I noticed that you don't have the @Stateless on the class.

    I have used
    Code:
    @Stateless(name = "ExpensesEJBBean", mappedName = "ExpensesEJBBean")


    Code:
    @Stateless
    public class ExpensesEJBBean extends AbstractStatelessSessionBean implements ExpensesEJBLocal, ExpensesEJB {
    }
    
    If the onEjbCreate() method is not being called then there is no way the Spring initialization is done. Code from the AbstractStatelessSessionBean

    Code:
    public void ejbCreate() throws CreateException {
       loadBeanFactory();
       onEjbCreate();
    }
    This would lead me to believe that the session bean is not setup correctly in JBoss as the EJB lifecycle methods (ejbCreate(), etc) are not being called.
    According to the JBoss server logs it does state that the "xxx EJB has been deployed". From which i can use InitialContext to get at it.

    Unfortunately most of experience was in EJB2 (though not touched it in over a year). From what i remeber of an EJB lifecylce was that because a stateless bean is being used the container would normally pre create a series of beans and then initalise it when called by the application.

    The constructor of my bean is being called by the spring framework, as i never directly initialize it myself, it happens via DI.

    I have a strong feeling that when Spring DI the EJB into the service object it actually injects it as a standard bean and not an EJB (explains why the container methods are not being called)

    Code:
    ctx.getBean("expensesService") //returns an ServiceObject containing DI EJB
    The service object returned from the call above I invoke the EJB, on invoking the EJB the call to onEJBCreate should be made(after ejbCreate)

    [CODE]
    <bean id="expensesService" class="uk.co.aztekSolutions.expensesApp.services.c ore.expenses.ExpensesServiceImpl">
    <property name="expensesEJB" ref="expensesEJB"/>
    </bean>

    <bean id="expensesEJB" class="org.springframework.jndi.JndiObjectFactoryB ean">
    <property name="jndiEnvironment">
    <props>
    <prop key="java.naming.factory.initial">org.jnp.interfac es.NamingContextFactory</prop>
    <prop key="java.naming.factory.url.pkgs">org.jboss.namin g:org.jnp.interfaces</prop>
    <prop key="java.naming.provider.url">jnp://localhost:1099</prop>
    </props>
    </property>
    <property name="jndiName" value="AztekApplication/ExpensesEJBBean/local"/>
    </bean>
    [/I]

  8. #18
    Join Date
    Jan 2006
    Location
    Huddersfield/Coventry
    Posts
    28

    Default Solution Found

    In case anyone is interested I have finally managed to get my App (Struts+spring+EJB3+iBatis/Hibernate) to work. Having so many problems initially I took some drastic steps to get everything to work

    1. Completely removed Spring from the App and got it working without it.
    2. Added the spring libs to the root of the ear file only, allowing both EJB and Web app to access them
    3. Added a context listener to the web.xml and added an EJB bean to the applicationContext.xml and accessed it via the configured service beans also injected by Spring
    4. Web app is now able to access EJB3 using Spring.
    5. Finally in the EJB jar file added another applicationContext.xml and defined the domain layer beans to it, using the ClassPathXmlApplicationContext to access the resources.


    I believe my overall problem was I had two separate spring libs inside web war and ear root.

    This approach also meant there are no direct dependencies on Spring, so if tomorrow I decide to drop Spring the application will still work as if nothing has changed.

    (Whole point of this app was to decouple the domain/persistence layer from the web app and use the EJB layer, though in my instance there was any real benefit of the EJB layer but I would be in the position where I could completely drop the EJB layer and use Spring alone. This way I have more options available to me.)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •