我有一个java EE应用程序,它有一个消息驱动的bean,它在JBoss 4上运行正常,但是当我为JBoss 6配置项目并在其上部署时,我收到此错误;
WARN [org.jboss.ejb.deployers.EjbDeployer.verifier] EJB spec violation:
...
The message driven bean must declare one onMessage() method.
...
org.jboss.deployers.spi.DeploymentException: Verification of Enterprise Beans failed, see above for error messages.
但我的bean有onMessage方法!那时它不会对jboss 4起作用。
为什么我会收到此错误!?
修改
有问题的课程看起来像这样
package ...
imports ...
public class MyMDB implements MessageDrivenBean, MessageListener {
AnotherSessionBean a;
OneMoreSessionBean b;
public MyMDB() {}
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
//Lookup sessionBeans by jndi, create them
lookupABean();
// check message-type, then invokie
a.handle(message);
// else
b.handle(message);
} catch (SomeException e) {
//handling it
}
}
}
public void lookupABean() {
try {
// code to lookup session beans and create.
} catch (CreateException e) { // handling it and catching NamingException too }
}
}
编辑2: 这是jboss.xml的相关部分
<message-driven>
<ejb-name>MyMDB</ejb-name>
<destination-jndi-name>topic/A_Topic</destination-jndi-name>
<local-jndi-name>A_Topic</local-jndi-name>
<mdb-user>user</mdb-user>
<mdb-passwd>pass</mdb-passwd>
<mdb-client-id>MyMessageBean</mdb-client-id>
<mdb-subscription-id>subid</mdb-subscription-id>
<resource-ref>
<res-ref-name>jms/TopicFactory</res-ref-name>
<jndi-name>jms/TopicFactory</jndi-name>
</resource-ref>
</message-driven>
编辑3:
我刚刚从项目中删除了所有的jar,只重新添加了相关的(也来自新版本)以消除NoClassDefFound错误。 问题仍然存在。
修改 任何方向,我应该看哪个区域?我的项目,还是jboss-configration,还是部署设置?
答案 0 :(得分:2)
org.jboss.ejb.deployers.EjbDeployer.verifier
寻找
public void onMessage(javax.jms.Message)
通过这样的代码(这是来自JBoss5):
/**
* Check if the given message is the onMessage() method
*/
public boolean isOnMessageMethod(Method m)
{
if ("onMessage".equals(m.getName()))
{
Class[] paramTypes = m.getParameterTypes();
if (paramTypes.length == 1)
{
if (Message.class.equals(paramTypes[0]))
return true;
}
}
return false;
}
重要的是参数类型是javax.jms.Message
而不是其他内容,例如某些子类或超类或某些实现类。
您的签名是public void onMessage(Message message)
,第一眼就看起来不错了。
Class
仅在其ClassLoader
中相等。如果由于某些原因javax.jms.Message
在同一JVM中的不同类加载器中可用,则可能会发生奇怪的事情,具体取决于EjbDeployer.verifier的ClassLoader。也许EjbDeployer.verifer可以访问另一个ClassLoader中的javax.jms.Message
MyMDB
。结果,两个javax.jms.Message
彼此不相等,尽管它们是相同的字节码并且确实存在。 EjbVerifier将警告错过onMessage
,因为ClassLoader A上的javax.jms.Message
在ClassLoader B上不等于javax.jms.Message
。
当具有javax.jms.Message
的库被复制到JBoss AS上的错误位置时,可能会发生这种情况。所以我想 - 从远处看 - 在JBoss或EAR的错误位置有一些包含javax.jms.Message
的罐子。例如,EAR中的一些错误的jbossallclient.jar。
答案 1 :(得分:1)
确保您的EAR不包含自己的javax.ejb
类(或任何javax
类的副本)(就此而言)。 JBoss 4和6具有相当不同的类加载语义,并且在一个上工作的东西可能在另一个上不起作用。例如,如果您的EAR lib
包含自己的Message
或MessageListener
副本,则可能不再有效。
答案 2 :(得分:1)
我尝试了“JBossAS [6.0.0.20100911-M5”Neo“]”和Eclipse Helios
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.jms.Message;
import javax.jms.MessageListener;
@MessageDriven(
activationConfig = { @ActivationConfigProperty(
propertyName = "destinationType", propertyValue = "javax.jms.Topic"
) },
mappedName = "topic/A_Topic",
messageListenerInterface = MessageListener.class)
public class MyMDB implements MessageListener, MessageDrivenBean {
private static final long serialVersionUID = -4923389997501209506L;
public MyMDB() {
// TODO Auto-generated constructor stub
}
@Override
public void ejbRemove() {
// TODO Auto-generated method stub
}
@Override
public void setMessageDrivenContext(MessageDrivenContext arg0) {
// TODO Auto-generated method stub
}
@Override
public void onMessage(Message message) {
// TODO Auto-generated method stub
}
}
此设置有效。您的bean有相同的导入(可能是自动导入出错了吗?)