How to use Kerberos in ConnectionFactory for Oracle database? - oracle

How to change to following code to attain the connection factory.
ConnectionFactory connectionFactory = ConnectionFactories.get(
"r2dbc:oracle://db.example.com:1521/db.service.name");

Related

Quarkus access to remote resources

everyone,
I have an application that we're switching to quarkus.
So far I could do a remote lookup via JNDI to a JMS queue in a weblogic. But it seems that Quarkus does not support JNDI anymore.
So my question is, how can I do the lookup on the remote queue in WLS?
My old code was like that
Hashtable<String, String> env = new Hashtable();
env.put("java.naming.factory.initial", "weblogic.jndi.WLInitialContextFactory");
env.put("java.naming.provider.url", url);
InitialContext context = new InitialContext(env);
ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup(jmsConnectionFactory);
Destination destination = (Destination) context.lookup(jmsDestination);
connection = connectionFactory.createConnection();
session = connection.createSession(true, 1);
sender = session.createProducer(destination);
Quarkus indeed does not support JNDI.
JMS can be used via the Quarkus QPid extension.
You can read the documentation here and view a quickstart application here.

How to configure HermesJMS to use a specific client certificate when connecting via SSL?

I have a Spring Boot Application that I've created instantiates an instance of ActiveMqSslBroker. I am attempting to connect to this broker using HermesJMS as a client.
I've configured the connection factory in Hermes as follows:
Class: org.apache.activemq.ActiveMQSslConnectionFactory
brokerURL: ssl://localhost:61616
keyStore: /path/to/client-keystore-containing-client-cert.ks
keyStoreKeyPassword: *****
keyStoreType: PKCS12
trustStore: /path/to/trust-store-containing-broker-cert.ts
trustStorePassword: ****
trustStoreType: PKCS12
The broker is configured in my spring-boot application as follows:
SSL Connector:
brokerUrl: ssl://localhost:61616
KeyManagers:
returned from KeyManagerFactory.getKeyManagers()
KeyStore: /path/to/key-store-containing-broker-cert.ks
TrustManagers:
returned from TrustManagerFactory.getTrustManagers()
TrustStore: /path/to/trust-store-containing-client-cert.ks
The broker is rejecting the connection requests from Hermes with the following error:
javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
So apparently HermesJMS is not sending the client certificate that is contained in its configured keyStore. Does the key have to have a specific alias to be picked up and used by Hermes? Is there a property I can set to specify the alias from the keyStore to use?
Turns out it was user error. I had a couple of different session configured, and while flipping back and forth between my IDE and Hermes, I somehow ended up testing on a session that was using the wrong connection factory.
After switching to the right session, things started to work.
For completeness here is how I got things working:
In my Spring-Boot application I defined my BrokerService bean as follows:
#Bean
public BrokerService broker(
#Value("${spring.activemq.broker-url}") String brokerUrl,
#Qualifier("brokerTrustManagerFactory") TrustManagerFactory trustManagerFactory,
#Qualifier("brokerKeyManagerFactory") KeyManagerFactory keyManagerFactory,
#Qualifier("secureRandom") SecureRandom secureRandom
){
SslBrokerService brokerService = new SslBrokerService();
brokerService.addSslConnector(
brokerUrl,
keyManagerFactory.getKeyManagers(),
trustManagerFactory.getTrustManagers(),
secureRandom
);
return brokerService;
}
Here is how a connection factory could be configured in a client application:
#Bean
ConnectionFactory connectionFactory(
#Value("${spring.activemq.broker-url}") String brokerUrl,
#Value("${spring.activemq.trustStorePath}") String trustStorePath,
#Value("${spring.activemq.trustStorePass}") String trustStorePass,
#Value("${spring.activemq.keyStorePath}") String keyStorePath,
#Value("${spring.activemq.keyStorePass}") String keyStorePass,
#Value("${client.key.pass}") String clientKeyPass
) {
ActiveMQSslConnectionFactory connectionFactory =
new ActiveMQSslConnectionFactory(brokerUrl);
connectionFactory.setTrustStore(trustStorePath);
connectionFactory.setTrustStorePassword(trustStorePass);
connectionFactory.setTrustStoreType("PKCS12");
connectionFactory.setKeyStore(keyStorePath);
connectionFactory.setKeyStorePassword(keyStorePass);
connectionFactory.setKeyStoreKeyPassword(clientKeyPass);
connectionFactory.setKeyStoreType("PKCS12");
return connectionFactory;
}
Hopefully someone will find this answer useful. Please note, the "spring.activemq.*" property names are not official property names recognized by Spring-Boot. They're just names that seemed to be used by a lot of the spring-boot activemq tutorials on the web.
Thanks,
Dave

Setup of spring-boot application with JMS, Artemis and JGroups with jdbc_ping

I have setup an Artemis HA-Custer example locally on my computer to learn how it's basically working. Now I want to prepare it to be pushed in a kubernetes cluster. Therefore I want to change the way of the initial membership discovery for the broker nodes, so I can use it in cloud, too. I want to use JMS and JGroups with "jdbc_ping". Actually I am not sure, if I am doing it right, so maybe you can tell me if not.
So far the brokers have successfully put their infos in the db-table and are apparently connected. When I try the following connectionFactory from my java application, it starts without errors and connects with the brokers. But in some points I am not sure, if it acts correctly.
#Bean
public ConnectionFactory connectionFactory() {
TransportConfiguration transportConfiguration = new TransportConfiguration(NettyConnectorFactory.class.getName());
ConnectionFactory cf = ActiveMQJMSClient.createConnectionFactoryWithHA(JMSFactoryType.CF, transportConfiguration);
return cf;
}
So the single point of question is now, how to setup the connectionFactory for the use of JGroups correctly.
UPDATE:
INFO 24528 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer : JMS message listener invoker needs to establish shared Connection
ERROR 24528 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer : Could not refresh JMS Connection for destination 'TestA' - retrying using FixedBackOff{interval=5000, currentAttempts=0, maxAttempts=unlimited}. Cause: Failed to create session factory; nested exception is ActiveMQInternalErrorException[errorType=INTERNAL_ERROR message=AMQ219004: Failed to initialise session factory]
The ActiveMQ Artemis documentation covers this:
Lastly, the jgroups scheme is supported which provides an alternative to the udp scheme for server discovery. The URL pattern is either jgroups://channelName?file=jgroups-xml-conf-filename where jgroups-xml-conf-filename refers to an XML file on the classpath that contains the JGroups configuration or it can be jgroups://channelName?properties=some-jgroups-properties. In both instance the channelName is the name given to the jgroups channel created.
In your code you can do something like this:
#Bean
public ConnectionFactory connectionFactory() {
return new ActiveMQConnectionFactory("jgroups://channelName?file=jgroups-xml-conf-filename");
}
In your case the client will need access to the same database that the broker's are using in order to use that information for discovery.

Solace Client JMS : Operation Not supported on Router: Router doesn't support transacted sessions

I am trying to listen to a Solace End Point using Sping Boot and when ran my app i am getting the Error:
2018-09-28 03:16:57.446 WARN 27305 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer : Setup of JMS message listener invoker failed for destination 'TEST1.OUT' - trying to recover. Cause: Error creating session - operation not supported on router (Capability Mismatch: Router does not support transacted sessions.)
Is there a config argument that i can set to not to use transaction sessions.
Thanks
You will need to create a JmsListenerContainerFactory that does not make use of transactions. For example:
#Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(
ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory listenerFactory =
new DefaultJmsListenerContainerFactory();
configurer.configure(listenerFactory, connectionFactory);
listenerFactory.setTransactionManager(null);
listenerFactory.setSessionTransacted(false);
return listenerFactory;
}
Full details can be found in the spring boot docs.
Do note that the Solace message broker supports transactions(local and XA).
To enable local transactions:
Enable allow‑transacted‑sessions in the client-profile used by your username.
Disable direct transport in your JMS connection factory.
Full details can be found in the Solace documentation.
Excellent answer.
To complement Russell answer, in the method which will handle the consume, in the annotation, we must specify the container factory bean created in the last step.
#JmsListener(destination = "TOPIC.TRX_PAYMENT", containerFactory = "jmsListenerContainerFactory")

Losing JMS Messages with Spring JMS and ActiveMQ when application server is suddenly stopped

I have a Spring JMS application that has a JMS Listener that connects to an Active MQ queue on application startup. This JMS listener is a part of the an application that takes a message, enriches it with content, and then delivers it to a topic on the same ActiveMQ broker.
The sessionTransacted is set to True. I'm not performing any database transactions, so I do not have #Transactional set anywhere. From what I've read, the sessionTransacted property sets a local transaction around the JMS Listener's receive method and therefore it will not pull the message off the queue until the transaction is complete. I've tested this using a local ActiveMQ instance, and on my local tomcat container, and it worked as expected.
However, when I deploy to our PERF environment and retry the same test, I notice that the message that was currently in-flight when the server was shutdown, is pulled from queue prior to completing the receive method.
What I would like to know is if there is anything obvious that I should be looking for? Are there certain JMS headers that would cause this behaviour to occur? Please let me know if there is anymore information that I can provide.
I'm using Spring 4.1.2.RELEASE with Apache ActiveMQ 5.8.0, on a Tomcat 7 container running Java 8.
UPDATE - Adding my Java JMS Configurations. Please note that I substituted what I had in my PERF properties file into the relevant areas for clarity.
#Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() throws Throwable {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setMaxMessagesPerTask(-1);
factory.setConcurrency(1);
factory.setSessionTransacted(Boolean.TRUE);
return factory;
}
#Bean
public CachingConnectionFactory connectionFactory(){
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
redeliveryPolicy.setInitialRedeliveryDelay(1000);
redeliveryPolicy.setRedeliveryDelay(1000);
redeliveryPolicy.setMaximumRedeliveries(6);
redeliveryPolicy.setUseExponentialBackOff(Boolean.TRUE);
redeliveryPolicy.setBackOffMultiplier(5);
ActiveMQConnectionFactory activeMQ = new ActiveMQConnectionFactory(environment.getProperty("queue.username"), environment.getProperty("queue.password"), environment.getProperty("jms.broker.endpoint"));
activeMQ.setRedeliveryPolicy(redeliveryPolicy);
activeMQ.setPrefetchPolicy(prefetchPolicy());
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(activeMQ);
cachingConnectionFactory.setCacheConsumers(Boolean.FALSE);
cachingConnectionFactory.setSessionCacheSize(1);
return cachingConnectionFactory;
}
#Bean
public JmsMessagingTemplate jmsMessagingTemplate(){
ActiveMQTopic activeMQ = new ActiveMQTopic(environment.getProperty("queue.out"));
JmsMessagingTemplate jmsMessagingTemplate = new JmsMessagingTemplate(connectionFactory());
jmsMessagingTemplate.setDefaultDestination(activeMQ);
return jmsMessagingTemplate;
}
protected ActiveMQPrefetchPolicy prefetchPolicy(){
ActiveMQPrefetchPolicy prefetchPolicy = new ActiveMQPrefetchPolicy();
int prefetchValue = 0;
prefetchPolicy.setQueuePrefetch(prefetchValue);
return prefetchPolicy;
}
Thanks,
Juan
It turns out that there were different versions of our application deployed on our PERF environment. Once the application was updated, then it worked as expected.

Resources