ERROR HQ224018: Failed to create session: HornetQException[errorType=SECURITY_EXCEPTION message=HQ119031: Unable to validate user: null]
When the Jboss EAP 6.3 server is about to receive JMS message. I have the user successfully authenticated by remoting subsystem so why the user is null? How to overcome this error?
EAP documentation encorage you to:
(...) set allowClientLogin to true (...) If you would like HornetQ to
authenticate using the propagated security then set the authoriseOnClientLogin to true also.
But due to HORNETQ-883 bug you have to turn off security for messaging:
<hornetq-server>
<!-- … -->
<security-enabled>false</security-enabled>
<!-- … -->
</hornetq-server>
In short, if your JMS client is connecting from within your JEE container and have no need to supply credentials to connect to JMS (when calling factory.createConnection()), then obtain connections using the InVM Connector. The InVM Connector doesn't require credentials when opening a connection to JMS (since the caller is within the JVM instance, hence the name) but still enforces security for Remote JMS clients. Connectors and ConnectionFactories are configured in the urn:jboss:domain:messaging subsystem of standalone.xml.
Otherwise, if you don't use the InVM Connector with security enabled, you'll probably need to run the add-user script in [jboss-home]/bin to add client credentials to the appilcation-users.properties file and supply those credentials when calling factory.createConnection(username, pwd) for both Remote and InVM clients connecting via Remotely available factories.
Gory Details
In our JBoss EAP 6.4 instance, security needs to remain enabled for remote connections (outside the JVM) so our <security-settings> for HornetQ are specified appropriately. Consequently, the JMS ConnectionFactory dictates the level of security based on which Connector it is configured with.
<hornetq-server>
<connectors>
<!-- additional connectors here -->
...
<in-vm-connector name="in-vm" server-id="0"/>
</connectors>
<jms-connection-factories>
<connection-factory name="InVmConnectionFactory">
<connectors>
<connector-ref connector-name="in-vm"/>
</connectors>
<entries>
<!-- JNDI bindings here -->
<entry name="java:/ConnectionFactory" />
</entries>
</connection-factory>
...
</jms-connection-factories>
So, in the JMS client apply the standard connection boiler-plate:
InitialContext context = new InitialContext();
javax.jms.ConnectionFactory factory = (ConnectionFactory) context.lookup("java:/ConnectionFactory");
and when creating the connection:
javax.jms.Connection connection = factory.createConnection();
Transacted JMS
For Transaction-aware in-container client connections to JMS, our InVM ConnectionFactory is configured like this:
<jms-connection-factories>
...
<pooled-connection-factory name="hornetq-ra">
<transaction mode="xa"/>
<connectors>
<connector-ref connector-name="in-vm"/>
</connectors>
<entries>
<entry name="java:/JmsXA"/>
</entries>
</pooled-connection-factory>
</jms-connection-factories>
Obtain the transacted JMS ConnectionFactory as such:
InitialContext context = new InitialContext();
javax.jms.ConnectionFactory factory = (ConnectionFactory) context.lookup("java:/JmsXA");
Related
We are creating a Mule application which will be running in a container on Kubernetes and will be in a replica set that will be connecting to JMS 2.0 Red Hat AMQ 7 (based on ActiveMQ Artemis).
The pom.xml has been configured to get the jms client:
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client-all</artifactId>
<version>2.10.1</version>
</dependency>
And the JMS config is configured as:
<jms:config name="JMS_Config" doc:name="JMS Config" doc:id="8621b07d-b203-463e-bbbe-76eb03741a61" >
<jms:generic-connection specification="JMS_2_0" username="${mq.user}" password="${mq.password}" clientId="${mq.client.id}">
<reconnection >
<reconnect-forever frequency="${mq.reconnection.frequency}" />
</reconnection>
<jms:connection-factory >
<jms:jndi-connection-factory connectionFactoryJndiName="ConnectionFactory" >
<jms:name-resolver-builder jndiInitialContextFactory="org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory" jndiProviderUrl="${mq.brokerurl}"/>
</jms:jndi-connection-factory>
</jms:connection-factory>
</jms:generic-connection>
<jms:consumer-config>
<jms:consumer-type >
<jms:topic-consumer shared="true" durable="true"/>
</jms:consumer-type>
</jms:consumer-config>
<jms:producer-config persistentDelivery="true"/>
</jms:config>
Then in the JMS listener component:
<jms:listener doc:name="EMS JMS Listener" doc:id="318b4f08-daf6-41f4-944b-3ec1420d5c12" config-ref="JMS_Config" destination="${mq.incoming.queue}" ackMode="AUTO" >
<jms:consumer-type >
<jms:topic-consumer shared="true" subscriptionName="${mq.sub.name}" durable="true"/>
</jms:consumer-type>
<jms:response sendCorrelationId="ALWAYS" />
</jms:listener>
The variables are set as:
mq.client.id=client-id-135a9514-d4d5-4f52-b01c-f6ca34a76b40
mq.sub.name=my-sub
mq.incoming.queue=my-queue
Is this the best way to configure the client? As we have seen errors in the logs when deployed to K8s regarding connections to the AMQ server:
javax.jms.InvalidClientIDException: client-id-135a9514-d4d5-4f52-b01c-f6ca34a76b40 was already set into another connection
In JMS 2.0 you don't have to set the client identifier when creating a shared durable subscription. However, if you do set the client identifier then it must be unique per connection. For whatever reason (e.g. due to Mule or perhaps K8s) multiple connections are being created and since each connection is using the same client identifier you're receiving the javax.jms.InvalidClientIDException.
Remove clientId="${mq.client.id}" from your configuration and the javax.jms.InvalidClientIDException should go away.
Is it possible to configure failover URI for native Artemis server in Wildfly 14? I'd like to create pooled connection factory with url like (tcp://localhost:61616,tcp://localhost:61617). As far as I know wildfly creates connection factory from connector host and port. I use Wildfly 14.0.1.Final and Artemis 2.6.3.
Update
<remote-connector name="remote-artemis-master" socket-binding="remote-artemis-master" />
<remote-connector name="remote-artemis-slave" socket-binding="remote-artemis-slave" />
<pooled-connection-factory
ha="true"
name="activemq-ra"
connectors="remote-artemis-master remote-artemis-slave"
entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory"
transaction="xa"
user="user"
password="password" />
Update
When master node stops the slave becomes live but the jee app is unable to send/consume messages 30 for seconds. After this period everything works fine.
The syntax (tcp://localhost:61616,tcp://localhost:61617) is just a way to configure multiple initial connectors via a URL. You can accomplish the same thing in Wildfly by defining multiple remote-connector elements and referencing those in the connectors attribute of the pooled-connection-factory.
Problem Statement: context.getCallerPrincipal().getName() always gives "anonymous" with following client and server settings
I have done all the settings required. My security domain is using a Custom spring security module for JAAS login. The client acts as an installer for the application. The main application is deployed on wildfly 10.1 and installer launches as a standalone application which access the remote EJBs from the server. The EJB access is successfully but when I access caller principle from context it always gives "anonymous"
Client Side Settings:
jboss-ejb-client.properties:
remote.connections=default
remote.connection.default.port=8080
remote.connection.default.host=127.0.0.1
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.default.username=root
remote.connection.default.password=catch22*
Initial Context Creation:
Properties prop1 = new Properties();
prop1.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
prop1.put("org.jboss.ejb.client.scoped.context", "true");
System.out.println("setup() ################### 1");
context = new InitialContext(prop1);
Used jboss-client.jar
I have used the jboss-client.jar lib provided with in "WILDFLY_HOME/bin/client" directory
Server Side Settings
ejb realm:
Added following ejb realm in standalone-full.xml
<security-realm name="ejb-outbound-realm">
<server-identities>
<secret value="Q29ubmVjdGlvblBhc3N3b3JkMSE="/>
</server-identities>
</security-realm>
remoting subsystem settings:added out bound connection as follows
<outbound-connections>
<remote-outbound-connection name="ejb-outbound-connection" outbound-socket-binding-ref="ejb-outbound" security-realm="ejb-outbound-realm" username="root">
<properties>
<property name="SASL_POLICY_NOANONYMOUS" value="false"/>
<property name="SSL_ENABLED" value="false"/>
</properties>
</remote-outbound-connection>
</outbound-connections>
Against out bound connection I have added following socket binding group
<outbound-socket-binding name="ejb-outbound">
<remote-destination host="localhost" port="8080"/>
</outbound-socket-binding>
application-users.properties:
root=7c5b7db204cb436044a4148094ef152e
application-roles.properties:
No change in this file
Session Bean Changes
#Stateless
#Local(AbstractEnterpriseSessionFacadeLocal.class)
#Remote(AbstractEnterpriseSessionFacadeRemote.class)
#SuppressWarnings({WarningConst.UNCHECKED, "rawtypes"})
#PermitAll
//#org.jboss.ejb3.annotation.SecurityDomain("acegi-simple")
public class AbstractEnterpriseSessionFacadeBean<T, E extends IGeneralObject> implements AbstractEnterpriseSessionFacade {
injection of context in above class
#Resource
private transient SessionContext context;
After above settings, when I am calling context.getCallerPrincipal().getName() it always gives me "anonymous"
Please help!
I am using jboss-5.1 to deploy message driven bean which is used to subscribe messages from a third party queue.
Around 16 messages were posted to that queue but they remained pending in our subscriber queue. I restarted the server and the messages were readily picked.
As much as I have analysed, I think maxsize and maxsession could have affected it, as both are 15. But I do not understand if there was some real issue, how it got solved by just restarting.
The logs were in error mode. I did not get the full stack trace.
This is the snippet of that error log.
[2012-10-30 17:01:00,228] [MQQueueAgent (GQH1_PLANNING_MDM_001)]
[ERROR] STDERR: 2012.10.30 17:01:00 MQJMS1023E rollback failed
[2012-10-30 17:01:00,228] [exceptionDelivery0] [WARN ]
org.jboss.resource.adapter.jms.inflow.JmsActivation: Failure in jms activation
org.jboss.resource.adapter.jms.inflow.JmsActivationSpec#85d0d(ra=org.jboss.resource.adapter.jms.JmsResourceAdapter#b21aae
destination=remotewsmq/NOTIFICATION_PLANNING_MDM_001.SUBQ
destinationType=javax.jms.Queue tx=true durable=false reconnect=10 provider=RemoteWSMQJMSProvider
user=null maxMessages=1 minSession=1 maxSession=5 keepAlive=60000 useDLQ=false)
GQH1_PLANNING_MDM_001: The name of the queue used for subscribing.
The files that I use to configure the properties of the MDBs are as follows.
1.ejb3-interceptors-aop.xml
<domain name="Message Driven Bean" extends="Intercepted Bean" inheritBindings="true">
<bind pointcut="execution(public * *->*(..))">
<interceptor-ref name="org.jboss.ejb3.security.AuthenticationInterceptorFactory"/>
<interceptor-ref name="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory"/>
</bind>
<!-- TODO: Authorization? -->
<bind pointcut="execution(public * *->*(..))">
<interceptor-ref name="org.jboss.ejb3.tx.CMTTxInterceptorFactory"/>
<interceptor-ref name="org.jboss.ejb3.stateless.StatelessInstanceInterceptor"/>
<interceptor-ref name="org.jboss.ejb3.tx.BMTTxInterceptorFactory"/>
<interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/>
<interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/>
<!-- interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/ -->
<stack-ref name="EJBInterceptors"/>
</bind>
<annotation expr="class(*) AND !class(#org.jboss.ejb3.annotation.Pool)">
#org.jboss.ejb3.annotation.Pool (value="StrictMaxPool", maxSize=15, timeout=10000)
</annotation>
</domain>
2.standardjboss.xml
<invoker-proxy-binding>
<name>message-driven-bean</name>
<invoker-mbean>default</invoker-mbean>
<proxy-factory>org.jboss.ejb.plugins.jms.JMSContainerInvoker</proxy-factory>
<proxy-factory-config>
<JMSProviderAdapterJNDI>DefaultJMSProvider</JMSProviderAdapterJNDI>
<ServerSessionPoolFactoryJNDI>StdJMSPool</ServerSessionPoolFactoryJNDI>
<CreateJBossMQDestination>false</CreateJBossMQDestination>
<!-- WARN: Don't set this to zero until a bug in the pooled executor is fixed -->
<MinimumSize>1</MinimumSize>
<MaximumSize>15</MaximumSize>
<KeepAliveMillis>30000</KeepAliveMillis>
<MaxMessages>1</MaxMessages>
<MDBConfig>
<ReconnectIntervalSec>10</ReconnectIntervalSec>
<DLQConfig>
<DestinationQueue>queue/DLQ</DestinationQueue>
<MaxTimesRedelivered>10</MaxTimesRedelivered>
<TimeToLive>0</TimeToLive>
</DLQConfig>
</MDBConfig>
</proxy-factory-config>
</invoker-proxy-binding>
<activation-config-property>
<activation-config-property-name>maxSession</activation-config-property-name>
<activation-config-property-value>15</activation-config-property-value>
</activation-config-property>
3.jms-ds.xml
<?xml version="1.0" encoding="UTF-8"?>
<connection-factories>
<!-- ==================================================================== -->
<!-- JMS Stuff -->
<!-- ==================================================================== -->
<!--
The JMS provider loader. Currently pointing to a non-clustered ConnectionFactory. Need to
be replaced with a clustered non-load-balanced ConnectionFactory when it becomes available.
See http://jira.jboss.org/jira/browse/JBMESSAGING-843.
-->
<mbean code="org.jboss.jms.jndi.JMSProviderLoader"
name="jboss.messaging:service=JMSProviderLoader,name=JMSProvider">
<attribute name="ProviderName">DefaultJMSProvider</attribute>
<attribute name="ProviderAdapterClass">org.jboss.jms.jndi.JNDIProviderAdapter</attribute>
<attribute name="FactoryRef">java:/XAConnectionFactory</attribute>
<attribute name="QueueFactoryRef">java:/XAConnectionFactory</attribute>
<attribute name="TopicFactoryRef">java:/XAConnectionFactory</attribute>
</mbean>
<!-- JMS XA Resource adapter, use this to get transacted JMS in beans -->
<tx-connection-factory>
<jndi-name>JmsXA</jndi-name>
<xa-transaction/>
<rar-name>jms-ra.rar</rar-name>
<connection-definition>org.jboss.resource.adapter.jms.JmsConnectionFactory</connection-definition>
<config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Topic</config-property>
<config-property name="JmsProviderAdapterJNDI" type="java.lang.String">java:/DefaultJMSProvider</config-property>
<max-pool-size>20</max-pool-size>
<security-domain-and-application>JmsXARealm</security-domain-and-application>
<depends>jboss.messaging:service=ServerPeer</depends>
</tx-connection-factory>
</connection-factories>
Please help.
If the listener did not try to reconnect, then it might be the messages pending which caused it to fail.
According to the error, a transaction ROLLBACK call failed. After the failure, the queue manager probably held those messages in an outstanding unit of work. Restarting the server would have closed the connection at which point the queue manager will have rolled back the transaction on behalf of the application. On restart, the application will create a new UOW and retrieve the messages.
Look in WebSphere MQ's queue manager error logs and global error logs to determine whether the error was caused by a resource shortage. It may be necessary to increase the size of the queue manager transaction logs or to tune transaction parameters such as MAXUOW.
You may also need to update the MQ client version or Queue Manager version. According to this Technote, WebSphere MQ JMS classes were updated as of 6.0.2.3 to fix a bug that resulted in MQJMS1023E errors. If you need to update the client version, it is available as a free download as SupportPac MQC75. A new client is able to run with any back level queue manager. After upgrading, the app benefits from the bug fixes and performance enhancements of the new client code and provides API functionality appropriate for the version of Queue Manager to which it connects. What version of WebSphere MQ JMS client is currently installed? What version of WebSphere MQ queue manager is currently installed?
I want to send messages to remote queue ? what steps should i do
i cant find any documentation about that ?
anyone can help ?? ?
Add another "JMSProvider" in your ${JBOSS_CONF}/deploy/messaging/jms-ds.xml. I use the provider name "RemoteJMSProvider" in this example:
<!-- Remote JMS Server-->
<mbean code="org.jboss.jms.jndi.JMSProviderLoader"
name="jboss.mq:service=JMSProviderLoader,name=RemoteJMSProvider,server=your_remote_host">
<attribute name="ProviderName">RemoteJMSProvider</attribute>
<attribute name="ProviderAdapterClass">org.jboss.jms.jndi.JNDIProviderAdapter</attribute>
<!-- The connection factory -->
<attribute name="FactoryRef">XAConnectionFactory</attribute>
<!-- The queue connection factory -->
<attribute name="QueueFactoryRef">XAConnectionFactory</attribute>
<!-- The topic factory -->
<attribute name="TopicFactoryRef">XAConnectionFactory</attribute>
<!-- Connect to JNDI on the host "the-remote-host-name" port 1099-->
<attribute name="Properties">
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jnp.interfaces
java.naming.provider.url=your_remote_host:1099
</attribute>
Next, add a "Remote Connection Factory":
<tx-connection-factory>
<jndi-name>RemoteJMSConnectionFactory</jndi-name>
<xa-transaction/>
<rar-name>jms-ra.rar</rar-name>
<connection-definition>org.jboss.resource.adapter.jms.JmsConnectionFactory</connection-definition>
<config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Queue</config-property>
<config-property name="JmsProviderAdapterJNDI" type="java.lang.String">java:/RemoteJMSProvider</config-property>
<max-pool-size>20</max-pool-size>
<security-domain-and-application>JmsXARealm</security-domain-and-application>
<depends>jboss.messaging:service=ServerPeer</depends>
Now, anytime you create a connection factory reference to "RemoteJMSFactory", any queue you reference will be looked-up on the remote server:
ConnectionFactory factory =(ConnectionFactory)JNDIContext.lookup("java:/RemoteJMSConnectionFactory");
queue = (Destination) JNDIContext.lookup("queue/myqueue");
connection = factory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer sender = session.createProducer(queue);
sender.send(jmsMessage);
See also:
http://community.jboss.org/wiki/HowDoIConfigureAnMDBToTalkToARemoteQueue
Look in docs/examples of your jboss installation. The only change needed to connect to a remote queue is to set up your initial context to refer to the remote appserver's JNDI port.