2010-03-17 126 views
5

我對Java EE是比較新的,所以這可能是愚蠢的。請耐心等待我請求:D如何將會話Bean注入消息驅動Bean?

我想將無狀態會話bean注入消息驅動bean。基本上,MDB獲取JMS消息,然後使用會話bean執行工作。會話bean擁有業務邏輯。

這裏是我的會話Bean:

@Stateless 
public class TestBean implements TestBeanRemote { 

    public void doSomething() { 
    // business logic goes here 
    } 
} 

匹配接口:

@Remote 
public interface TestBeanRemote { 

    public void doSomething(); 
} 

這裏是我的MDB:

@MessageDriven(mappedName = "jms/mvs.TestController", activationConfig = { 
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), 
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") 
    }) 
public class TestController implements MessageListener { 

@EJB 
private TestBean testBean; 

    public TestController() { 
    } 

    public void onMessage(Message message) { 
     testBean.doSomething(); 
    } 
} 

到目前爲止,不是火箭科學,對吧?

不幸的是,在部署時,這GlassFish的第三版,並且將消息發送到相應的JMS隊列,我得到的錯誤,GlassFish是無法找到testBean這個EJB:

java.lang.IllegalStateException: Exception attempting to inject Remote ejb-ref name=mvs.test.TestController/testBean,Remote 3.x interface =mvs.test.TestBean,ejb-link=null,lookup=null,mappedName=,jndi-name=mvs.test.TestBean,refType=Session into class mvs.test.TestController 
Caused by: com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Remote ejb-ref name=mvs.test.TestController/testBean,Remote 3.x interface =mvs.test.TestBean,ejb-link=null,lookup=null,mappedName=,jndi-name=mvs.test.TestBean,refType=Session into class mvs.test.TestController 
Caused by: javax.naming.NamingException: Lookup failed for 'java:comp/env/mvs.test.TestController/testBean' in SerialContext [Root exception is javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=mvs.test.TestController/testBean,Remote 3.x interface =mvs.test.TestBean,ejb-link=null,lookup=null,mappedName=,jndi-name=mvs.test.TestBean,refType=Session' . Actual (possibly internal) Remote JNDI name used for lookup is 'mvs.test.TestBean#mvs.test.TestBean' [Root exception is javax.naming.NamingException: Lookup failed for 'mvs.test.TestBean#mvs.test.TestBean' in SerialContext [Root exception is javax.naming.NameNotFoundException: mvs.test.TestBean#mvs.test.TestBean not found]]] 

所以我的問題是:

  • 這是將會話bean注入另一個bean(特別是消息驅動bean)的正確方法嗎?
  • 爲什麼命名查找失敗?

回答

3

好的,我發現如果我將註釋@LocalBean添加到會話bean中,它就可以工作。什麼......?

+0

我現在有點遠了。 @LocalBean標識沒有接口的bean。所以這不是我想要的,即使它有效:D – Hank 2010-03-18 07:34:47

+0

您應該使用「@EJB private TestBeanRemote testBean;」 – Dagvadorj 2013-04-13 11:23:53

6

你能嘗試定義這樣的事情:

@Remote 
public interface TestBeanRemote { 

    public void doSomething(); 
} 

@Stateless(name="TestBeanRemote") 
public class TestBean implements TestBeanRemote { 

    public void doSomething() { 
    // business logic goes here 
    } 
} 

然後在MDB:

@MessageDriven(mappedName = "jms/mvs.TestController", activationConfig = { 
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), 
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") 
    }) 
public class TestController implements MessageListener { 

    @EJB(beanName="TestBeanRemote") 
    private TestBeanRemote testBean; 

    public TestController() { 
    } 

    public void onMessage(Message message) { 
     testBean.doSomething(); 
    } 
} 

如果這個工作,我會盡力提供一個解釋:)

+0

對不起,不幸的是,這也不起作用。我想我會跟着我發現的IoC。不管怎麼說,還是要謝謝你! – Hank 2010-03-18 07:46:00

+0

@Hank怪異的,我理解它應該。我很困惑... – 2010-03-18 07:58:53

4

看來我的問題與控制反轉有關,並且由於我缺乏知識和Netbeans對類/接口名稱的建議而導致。

我發現 - 爲了找到合適的bean和正確的界面 - 我應該正確地命名它們。以下是工作原理:

@Remote 
public interface Test { 

    public void doSomething(); 
} 

@Stateless 
public class TestBean implements Test { 

    public void doSomething() { 
    // business logic goes here 
    } 
} 

而在MDB我訪問「測試」 「testBean這個」:

@MessageDriven(mappedName = "jms/mvs.TestController", activationConfig = { 
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), 
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") 
    }) 
public class TestController implements MessageListener { 

    @EJB 
    private Test testBean; 

    public TestController() { 
    } 

    public void onMessage(Message message) { 
     testBean.doSomething(); 
    } 
} 
+0

你能否在你的關於命名約定的發現上添加任何參考? – 2010-03-18 08:05:29

+1

試試這裏:http://java.sun.com/blueprints/code/namingconventions.html – Hank 2010-03-18 08:34:24

+0

好吧,我現在開始越來越明白這一點。我的上面的例子是正確的,如果接口是@Local。 當我注入一個會話bean的東西,我注射。然後容器試圖找到實現類( Bean)以及相應的接口(對於@Local使用: Local,對於@Remote使用:遠程)。 所以這個問題不是JNDI,它不符合命名約定! – Hank 2010-03-18 08:47:15

6

我覺得第一個例子的問題是,你正在試圖注入EJB的實現而不是它的接口。如果您沒有定義任何接口,即使是遠程接口,EJB 3.1的本地無接口視圖也是可能的。因此,改變注入點以下應該制定出:

@EJB 
private TestBeanRemote testBean; 

如果您正在使用非羣集環境中的應用程序,因此單個JVM,你應該考慮改變接口@Local。只要使用遠程接口訪問EJB,就會產生很大的開銷。參數和返回值不能通過引用進行訪問,而是按值進行訪問,因爲它們總是被複制(規範如此說明)。處理更復雜的對象時,這可能會導致性能問題。

希望有所幫助。