When the user logs in, I need to insert a message into the database (host name, as an example). Since this is just a text message, EJB injection to the client (servlets, JSP, JSF or something else) is completely unnecessary.
The client, in this case, is an authentication filter through which I send the host name to the message-driven bean. Using a message-driven bean, the message is stored in a queue (not in the subject), which is then sent to the EJB by inserting the EJB into this bean.
The strategy described here works great. A problem occurs when an EJB is forced to restrict security. In this case, it throws a security exception.
A message-driven bean is as follows.
@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());
There is still no one method in stateless EJB that is responsible for inserting a message into the database using the JPA criteria API:
@Stateless @DeclareRoles(value={"ROLE_ADMIN", "ROLE_USER"}) @RolesAllowed(value={"ROLE_ADMIN"}) public class UserStatusBean implements UserStatusBeanRemote { @Override public void addHost(String hostName) {
And the filter that authenticates the user is shown below (in case it needs to be reviewed).
@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());
The protection used here works great elsewhere. The @RolesAllowed(value={"ROLE_ADMIN"}) before the UserStatusBean EJB raises the following exception.
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)
It works when this annotation @RolesAllowed(value={"ROLE_ADMIN"}) before removing the EJB.
Can such methods be called using message-driven bean?
I am using GlassFish 4.0.