当用户登录时,我需要在数据库中插入一条消息(主机名,仅作为示例)。因为它只是一个文本消息,所以将EJB注入到客户机(Servlets、JSP、JSF或其他东西)是非常不必要的。
这里提到的策略很管用。当EJB被强制执行安全约束时,问题就会出现。在这种情况下,它抛出一个关于安全性的异常。
消息驱动bean如下所示。
@MessageDriven(mappedName = "jms/destination", activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class UserStatusMessageBean implements MessageListener
{
@Resource
private MessageDrivenContext messageDrivenContext;
@EJB
private UserStatusBeanRemote userStatusBeanRemote;
public UserStatusMessageBean() {}
@Override
public void onMessage(Message message)
{
TextMessage textMessage;
try
{
if(message instanceof TextMessage)
{
textMessage = (TextMessage) message;
userStatusBeanRemote.addHost(textMessage.getText());
//This EJB method causes the exception as given below.
}
else
{
System.out.println("Message is of wrong type : " +message.getClass().getName());
}
}
catch (JMSException e)
{
messageDrivenContext.setRollbackOnly();
System.out.println(e);
}
catch (Throwable e)
{
System.out.println(e);
}
}
}
到目前为止,无状态EJB只有一个方法负责使用JPA标准API将消息插入数据库:
@Stateless
@DeclareRoles(value={"ROLE_ADMIN", "ROLE_USER"})
@RolesAllowed(value={"ROLE_ADMIN"})
public class UserStatusBean implements UserStatusBeanRemote
{
@Override
public void addHost(String hostName)
{
//Business logic to add the host name to the database.
}
}
@WebFilter(filterName = "SecurityCheck", urlPatterns = {"/jass/*"})
public final class SecurityCheck implements Filter
{
@Resource(mappedName="jms/destinationFactory")
private ConnectionFactory connectionFactory;
@Resource(mappedName="jms/destination")
private Queue queue;
@EJB
private final UserBeanLocal userService=null;
public SecurityCheck() {}
private void sendJMSMessageToDestination(String message) throws JMSException
{
Connection connection = null;
Session session = null;
try
{
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(queue);
TextMessage textMessage = session.createTextMessage();
textMessage.setText(message);
messageProducer.send(textMessage);
}
finally
{
if(session!=null){session.close();}
if(connection!=null){connection.close();}
}
}
private void doBeforeProcessing(ServletRequest request, ServletResponse response) throws IOException, ServletException
{
HttpServletRequest httpServletRequest=(HttpServletRequest)request;
httpServletRequest.login(httpServletRequest.getParameter("userName"), httpServletRequest.getParameter("password"));
}
private void doAfterProcessing(ServletRequest request, ServletResponse response) throws IOException, ServletException, JMSException
{
HttpServletRequest httpServletRequest=(HttpServletRequest)request;
HttpServletResponse httpServletResponse=(HttpServletResponse)response;
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
Map<String, Object> sessionMap = externalContext.getSessionMap();
if(httpServletRequest.isUserInRole("ROLE_USER"))
{
sendJMSMessageToDestination(httpServletRequest.getLocalName());//Send a text message through a message-driven bean.
String userName = httpServletRequest.getParameter("userName");
UserTable userTable = userService.setLastLogin(userName);
userTable.setPassword(null);
sessionMap.put("userName", userTable!=null?userTable.getFirstName():"Unknown");
sessionMap.put("user", userTable);
httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
httpServletResponse.setHeader("Pragma", "no-cache");
httpServletResponse.setDateHeader("Expires", 0);
httpServletResponse.sendRedirect("../user_side/Home.jsf");
}
else if(httpServletRequest.isUserInRole("ROLE_ADMIN"))
{
sendJMSMessageToDestination(httpServletRequest.getLocalName());//Send a text message through a message-driven bean.
String userName = httpServletRequest.getParameter("userName");
UserTable userTable = userService.setLastLogin(userName);
userTable.setPassword(null);
sessionMap.put("adminName", userTable!=null?userTable.getFirstName():"Unknown");
sessionMap.put("user", userTable);
httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
httpServletResponse.setHeader("Pragma", "no-cache");
httpServletResponse.setDateHeader("Expires", 0);
httpServletResponse.sendRedirect("../admin_side/Home.jsf");
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
try
{
doBeforeProcessing(request, response);
}
catch (Exception e)
{
HttpServletResponse httpServletResponse=(HttpServletResponse)response;
//FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "Incorrect user name and/or password. Access denied."));
httpServletResponse.sendRedirect("../utility/Login.jsf");
return;
}
chain.doFilter(request, response);
try
{
doAfterProcessing(request, response);
}
catch (JMSException ex)
{
Logger.getLogger(SecurityCheck.class.getName()).log(Level.SEVERE, null, ex);
}
}
//The rest of this filter.
}
WARNING: EJB5184:A system exception occurred during an invocation on EJB UserStatusBean, method: public void ejb.message.UserStatusBean.addHost(java.lang.String)
WARNING: javax.ejb.AccessLocalException: Client not authorized for this invocation
at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1895)
at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:204)
at com.sun.ejb.containers.EJBObjectInvocationHandlerDelegate.invoke(EJBObjectInvocationHandlerDelegate.java:79)
at $Proxy366.addHost(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.privateInvoke(StubInvocationHandlerImpl.java:239)
at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.invoke(StubInvocationHandlerImpl.java:150)
at com.sun.corba.ee.impl.presentation.rmi.codegen.CodegenStubBase.invoke(CodegenStubBase.java:226)
at ejb.message.__UserStatusBeanRemote_Remote_DynamicStub.addHost(ejb/message/__UserStatusBeanRemote_Remote_DynamicStub.java)
at ejb.message._UserStatusBeanRemote_Wrapper.addHost(ejb/message/_UserStatusBeanRemote_Wrapper.java)
at bean.message.UserStatusMessageBean.onMessage(UserStatusMessageBean.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4695)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:630)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:582)
at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4667)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4655)
at org.glassfish.ejb.mdb.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:1219)
at org.glassfish.ejb.mdb.MessageBeanListenerImpl.deliverMessage(MessageBeanListenerImpl.java:81)
at com.sun.enterprise.connectors.inbound.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:171)
at $Proxy406.onMessage(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:283)
at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:107)
at com.sun.corba.ee.impl.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
at com.sun.corba.ee.impl.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:540)
INFO: javax.ejb.EJBAccessException
at ejb.message._UserStatusBeanRemote_Wrapper.addHost(ejb/message/_UserStatusBeanRemote_Wrapper.java)
at bean.message.UserStatusMessageBean.onMessage(UserStatusMessageBean.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4695)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:630)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:582)
at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4667)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4655)
at org.glassfish.ejb.mdb.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:1219)
at org.glassfish.ejb.mdb.MessageBeanListenerImpl.deliverMessage(MessageBeanListenerImpl.java:81)
at com.sun.enterprise.connectors.inbound.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:171)
at $Proxy406.onMessage(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:283)
at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:107)
at com.sun.corba.ee.impl.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
at com.sun.corba.ee.impl.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:540)
Caused by: java.rmi.AccessException: CORBA NO_PERMISSION 9998 Maybe; nested exception is:
org.omg.CORBA.NO_PERMISSION: vmcid: 0x2000 minor code: 1806 completed: Maybe
at com.sun.corba.ee.impl.javax.rmi.CORBA.Util.mapSystemException(Util.java:264)
at com.sun.corba.ee.impl.javax.rmi.CORBA.Util.wrapException(Util.java:695)
at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.privateInvoke(StubInvocationHandlerImpl.java:249)
at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.invoke(StubInvocationHandlerImpl.java:150)
at com.sun.corba.ee.impl.presentation.rmi.codegen.CodegenStubBase.invoke(CodegenStubBase.java:226)
at ejb.message.__UserStatusBeanRemote_Remote_DynamicStub.addHost(ejb/message/__UserStatusBeanRemote_Remote_DynamicStub.java)
... 30 more
Caused by: org.omg.CORBA.NO_PERMISSION: vmcid: 0x2000 minor code: 1806 completed: Maybe
Caused by: javax.ejb.AccessLocalException: Client not authorized for this invocation
at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1895)
at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:204)
at com.sun.ejb.containers.EJBObjectInvocationHandlerDelegate.invoke(EJBObjectInvocationHandlerDelegate.java:79)
at $Proxy366.addHost(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.privateInvoke(StubInvocationHandlerImpl.java:239)
at com.sun.corba.ee.impl.presentation.rmi.StubInvocationHandlerImpl.invoke(StubInvocationHandlerImpl.java:150)
at com.sun.corba.ee.impl.presentation.rmi.codegen.CodegenStubBase.invoke(CodegenStubBase.java:226)
at ejb.message.__UserStatusBeanRemote_Remote_DynamicStub.addHost(ejb/message/__UserStatusBeanRemote_Remote_DynamicStub.java)
at ejb.message._UserStatusBeanRemote_Wrapper.addHost(ejb/message/_UserStatusBeanRemote_Wrapper.java)
at bean.message.UserStatusMessageBean.onMessage(UserStatusMessageBean.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4695)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:630)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:582)
at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4667)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4655)
at org.glassfish.ejb.mdb.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:1219)
at org.glassfish.ejb.mdb.MessageBeanListenerImpl.deliverMessage(MessageBeanListenerImpl.java:81)
at com.sun.enterprise.connectors.inbound.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:171)
at $Proxy406.onMessage(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:283)
at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:107)
at com.sun.corba.ee.impl.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
at com.sun.corba.ee.impl.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:540)
是否可以通过消息驱动的bean调用这样的方法?
我用的是GlassFish 4.0。
您可以对MDB使用@runas注释。
EJB规范规定:
Bean提供程序可以使用RunAs元数据注释,或者Bean提供程序或应用程序汇编程序可以使用run-as部署描述符元素为部署描述符中的企业Bean定义run-as标识。run-as标识应用于企业bean作为一个整体,即应用于企业bean的业务、主接口和组件接口、无接口视图和/或web服务endpoint的所有方法;消息驱动bean的消息侦听器方法;和企业bean的超时回调方法;以及它们可能反过来调用的bean的所有内部方法。
在这种情况下,调用方主体传播并不重要。谁调用了该方法以及标识是否被传播并不相关,将使用run-as标识,并将进一步传播该标识。
不过,必须正确设置run-as标识。基本上,如果使用默认主体到角色映射,则需要创建一个用户,例如runasadmin
,并为他分配role_admin
角色。然后用@runas(“runasadmin”)
注释MDB。
在一个无状态bean中,我正在查找队列,这是正确的,并且发送没有抛出异常: 但不调用消息驱动bean的onMessage方法。 我错过了什么? 我的消息驱动bean有以下代码:
[警告]:由于激活规范不可用,因此无法激活消息驱动bean的消息endpoint。在激活规范可用之前,消息endpoint将不会接收消息。 MDB必须有激活规范吗?我希望它只是被激活,而不需要添加进一步的配置到服务器。
我对JMS编码是新手。我试图从独立的java客户端创建消息,该客户端创建并将消息发送到队列,消息驱动bean用于进一步处理消息。 我使用的是Glassfish应用服务器(3.1)。并设置从独立java客户机创建消息的所有内容。 下面是我的代码:客户端 消息驱动bean: 问题是:没有被调用。我错过什么了吗?请帮帮我.
是否可以在MDB(消息驱动Bean)中为“目的地”动态分配运行时值? 我还尝试了ejb-jar.xml方法,但是“activation-config-property-name”=“destination”的值被理解为队列的文字物理名称。因此我无法对资源进行JNDI查找。 从属性读取和分配目标或使用-d参数传递值的正确方法是什么?
在企业应用程序中,我试图使用netBeans 8.1将MessageDriven beans注入Web应用程序(到REST服务)。我在IDE中没有得到任何警告,但是,在部署时,我得到以下错误: 严重:加载应用程序时出现异常:CDI部署失败:Weld-001408:未满足类型StatisticsBean的依赖关系,其限定符@Default在注入点[BackedAnnotatedField]@Inje
消息驱动Bean是一种企业bean,当EJB容器从队列或主题接收消息时由EJB容器调用。 消息驱动的bean是一个无状态bean,用于异步执行任务。 为了演示消息驱动bean的使用,我们将使用EJB-persistence章节,我们需要执行以下任务 - Step 1 - 在数据库中创建表(请参阅EJB-Persistence章节)。 Step 2 - 创建与表对应的实体类(请参阅EJB-Persi