I have read the article http://techtots.blogspot.com/2010/01/connecting-to-mq-using-spring-without.html about configuring QueueConnectionFactories and have that side of things working nicely.
# MQ related values
mq.jms.qcf=QM_Epsilon
mq.jms.request.queue=TEST.REQUEST.QUEUE
# Connection details
mq.host.url=localhost:1414/SYSTEM.DEF.SVRCONN
mq.factoryclass=com.ibm.mq.jms.context.WMQInitialContextFactory
# Authentication details
mq.auth=simple
mq.user=******
mq.password=********
<bean id="queueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${mq.jms.qcf}" />
<property name="resourceRef" value="false" />
<property name="jndiEnvironment">
<props>
<prop key="java.naming.factory.initial">${mq.factoryclass}</prop>
<prop key="java.naming.provider.url">${mq.host.url}</prop>
<prop key="java.naming.security.authentication">${mq.auth}</prop>
<prop key="java.naming.security.principal">${mq.user}</prop>
<prop key="java.naming.security.credentials">${mq.password}</prop>
</props>
</property>
</bean>
Using this configuration the queueConnectionFactory bean is easily injected into my classes as an MQQueueConnectionFactory.
But I am wanting to use the publish/subscribe model and, as I understand it, I need to get an MQTopicConnectionFactory for this. I have searched everywhere and tried numerous things but I cannot find any information on how to modify this configuration, or the MQ installation so that I get an MQTopicConnectionFactory instead of an MQQueueConnectionFactory.
The WMQInitialContextFactory is a class that implements a JNDI provider over a WebSphere MQ queue. Instead of the managed objects being stored in a .bindings file or LDAP, they are serialized and stored in a queue and this class allows you to treat that queue as just another JNDI store. This class was only ever intended to be a JNDI provider and not a replacement for the actual IBM JMS implementation. Since storing managed objects on a topic would not work, these classes have no topic factories in them. This is as expected.
In my opinion, the problem with WMQInitialContextFactory is that it must first connect to WebSphere MQ in order to to obtain a connection factory which then tells the app - you guessed it - how to connect to WebSphere MQ. This makes the article that was linked confusing because it appears that all that configuration, the WMQ connection details and so forth, are for the benefit of the application when in fact they just bootstrap a JNDI provider which is expected to have defined connection factory objects with all this same information.
What is missing from the article is that the author would have had to use IBM's JMSAdmin tool to connect to the MQInitialContext and define the ConnectionFactory and other administered objects before connecting the application to that same Initial Context in order to access them.
For the record, the WebSphere MQ JMS classes have supported JMS 1.1 ConnectionFactory and Destination classes for quite some time now. Prior to that they supported both queues and topics as per the JMS 1.0 spec.
You can download the IBM WMQ JMS implementation as SupportPac MQC7. There is a lot more there than just the jar files. For example, you get lots of sample code, diagnostic and trace utilities, documentation, etc. You also get the correct jar files.
If you want to use a .bindings file (File-system initial context) instead of the WMQInitialContextFactory, download the latest WebSphere MQ Explorer tool as SupportPac MS0T. You can create a directory, point WMQ Explorer to it and define all your connection factories and destinations. (Or go with domain-specific QueueConnectionFactory and TopicConnectionFactory if you rock it old school.) More information on using WMQ Explorer to define your managed objects may be found at: Creating and configuring JMS administered objects
If you want a tutorial that includes a demonstration of how to use IBM's JMSAdmin tool to create the .bindings file, look at Running a standalone Java application on WebSphere MQ V6.0. (The JMSAdmin tool is installed with the WMQ Server and I believe it also comes with the free MS0T WMQ Client install linked above.) The documentation for the JMSAdmin tool is here: Using the WebSphere MQ JMS administration tool
Whichever method you choose to create managed objects, you can look up all the possible properties supported in IBM's implementation at: Properties of WebSphere MQ classes for JMS objects
Related
I would like to create a JMS connection from a Java SE application in a broker-agnostic way.
I'm comparing to JDBC with its URL scheme for database connections. This creates independence from the actual implementation.
For JMS I haven't found something similar. I'm aware that in Java EE the JNDI will fulfill this role, but this is Java SE.
I don't want to tie my code to any particular queue broker as my needs are pretty simple JMS 1.1 send/receive of text messages.
I've looked at Spring Boot too because it is usually good at providing some level of agnosticism. But even with Spring Boot, I do not see such possibility.
JNDI is the way you write your JMS application to connect in a broker-agnostic way. JNDI client classes are part of Java SE. Both Spring and non-Spring Java SE applications use JNDI for this kind of integration.
Any JMS implementation should also provide a JNDI implementation that can be plugged into your application. Typically this is done by placing a file named jndi.properties on your classpath and putting the proper configuration for whatever JNDI implementation you're using into that file. When you create an empty InitialContext the jndi.properties file on your classpath is read automatically. The key=value pairs in jndi.properties are put into the InitialContext so that when you perform a lookup everything works with the implementation you've chosen. You can also configure this programmatically if you like by supplying the implementation specific details to the InitialContext via a constructor.
By using both the JMS and JNDI APIs in your Java SE application and externalizing broker-specific connection details to your jndi.properties file you can effectively isolate your applications from broker-specific code so you can deploy your app and work with different brokers with a few simple changes in a properties file.
The JNDI client implementation will come from whoever is providing the JMS implementation. The JNDI client essentially comes in the form of an javax.naming.spi.InitialContextFactory implementation packaged in a jar and there is usually documentation describing the available properties.
Here are a few examples:
The ActiveMQ 5.x broker provides org.apache.activemq.jndi.ActiveMQInitialContextFactory available in their activemq-client-<version>.jar. Documentation is available here.
The ActiveMQ Artemis broker provides org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory available in their artemis-jms-client-<version>.jar. Documentation is available here.
To be clear, the JMS specification doesn't require the use of JNDI to look-up admin objects, but it establishes the convention and expectation that JMS providers will do so. Section 4.2 of the JMS 1.1 specification states:
Although the interfaces for administered objects do not explicitly depend on JNDI, JMS establishes the convention that JMS clients find them by looking them up in a namespace using JNDI.
and later it says:
It is expected that JMS providers will provide the tools an administrator needs to create and configure administered objects in a JNDI namespace. JMS
provider implementations of administered objects should be both javax.naming.Referenceable and java.io.Serializable so that they can be stored in all JNDI naming contexts.
In my experience, JMS providers are usually eager to provide a JNDI implementation because they won't be as competitive without it since any alternative solution will not be standards compliant and will force users to implement non-portable code.
If you run into a provider that doesn't provide a JNDI implementation you could implement your own following the same pattern used by ActiveMQ 5.x, ActiveMQ Artemis, and Qpid JMS. These 3 implementations are client-side only and simply instantiate the admin objects based on the configuration provided to the InitialContext. Most of the code is boiler plate, and what isn't is very straight-forward.
Setting up an HTTP proxy for Java JVM 6.x isn't working for me; I'm hoping someone can spot what I'm missing.
I have a Java application deployed on JBOSS 5.1.2 that makes several calls to external web services. I'd like to be able to intercept these calls using a proxy: Fiddler version 4.4.8.0.
After doing an SO search I added the following flags to my JBOSS VM parameters at startup:
-DproxySet=true -Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888 -Dhttps.proxyHost=localhost -Dhttps.proxyPort=8888
I'm running JBOSS in IntelliJ 14.
I can see traffic from the browser to the application if I start JBOSS, Fiddler, and open the UI in Chrome. I do not see any calls from JBOSS to external services being intercepted. I thought I would see all the calls from JBOSS to external services in addition to those from the browser to JBOSS.
Update:
I tried adding these to properties-service.xml per this SO answer - no joy.
I'm running Spring 3, using Apache HttpClient as my web service client. I'm going to look into configuring proxy just for it.
Thanks to bmargulies and anyone else who looked at this. I have a solution that I hope will help someone else.
Adding -Dhttp.proxyHost parameters to my JVM startup options did nothing.
Adding those same parameters to JBOSS 5.1.2 configuration in my deployment properties-services.xml did nothing.
I believe that using Spring 3.x is a factor in explaining this behavior. I had to tell the Spring web service clients to use a proxy.
I added some Spring beans to wire in a Fiddler proxy HttpClient and injected that into the web service client, replacing the non-proxied version.
It failed the first time I tried it. It took me a while to figure out that the Apache Commons HttpConfiguration class didn’t follow the Java bean standard, so Spring blew up when it tried to wire it. I had to use the Spring MethodInvokingFactoryBean to get around it.
Here's the pertinent Spring configuration XML:
<!-- New beans for Fiddler proxy -->
<bean id="fiddlerProxyHost" class="org.apache.commons.httpclient.ProxyHost">
<constructor-arg name="hostname" value="localhost"/>
<constructor-arg name="port" value="8888"/>
</bean>
<bean id="fiddlerProxyHostConfiguration" class="org.apache.commons.httpclient.HostConfiguration"/>
<bean id="fiddlerProxyHostSetter" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="fiddlerProxyHostConfiguration"/>
<property name="targetMethod" value="setProxyHost"/>
<property name="arguments" ref="fiddlerProxyHost"/>
</bean>
<bean id="fiddlerProxyClient" class="org.apache.commons.httpclient.HttpClient">
<property name="hostConfiguration" ref="fiddlerProxyHostConfiguration"/>
</bean>
Now I can see the calls from the application to the web service in Fiddler. Joy!
Those parameters, first and foremost, are read by HttpURLConnection. They are specific to HTTP, of course, and so any other means of connecting to the outside world will necessarily ignore them.
There are many good reasons for code to avoid HttpURLConnection and just open a TCP connection through a plain old socket, even if that code plans to talk HTTP. HttpURLConnection has several 'browser emulation features' that get in the way. For example, it's broken for CORS and rejects some legitimate HTTP verbs.
Code that does that and in turn happens to do HTTP might choose to respect those parameters, and it might not. For example, I'm reasonably sure that the Apache Commons HTTP library gives the caller a choice.
If you put JBoss in a debugger and break on the socket connection primitives, I think you'll find out what's happening to you pretty quick in this respect.
I am using simplejmx to publish my JMX Resources.
I have got jmx-config.xml
<bean id="beanPublisher" class="com.j256.simplejmx.spring.BeanPublisher">
<property name="jmxServer" ref="jmxServer" />
</bean>
<bean id="jmxServer" class="com.j256.simplejmx.server.JmxServer"
init-method="start" destroy-method="stop">
<property name="registryPort" value="8123" />
</bean>
I am starting my JBoss application, everything is ok:
15:20:11,860 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] (MSC service thread 1-8) Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#1be30160: defining beans [...,beanPublisher,jmxServer,...]; root of factory hierarchy
I created a simply class.
package com.mypckg.jmx;
import com.j256.simplejmx.common.JmxAttributeField;
import com.j256.simplejmx.common.JmxResource;
#JmxResource(description = "Blah1", domainName = "Blah2", beanName = "Blah3")
public class DummyJMX {
#JmxAttributeField(description = "Blah4")
private int var = 3;
}
I am starting JConsole, I am choosing JBoss application and I am going to MBeans. That is what I see:
*
Probably, my DummyJMX class has not been published (or I just cannot find it).
About which step I forgot?
Thank you in advance
EDIT :
EDIT :
#Andrei Stefan
An error which I got using your link:
#Gray
An error which I got using localhost:8123:
Try the following url in JConsole, with Remote Process option: service:jmx:rmi:///jndi/rmi://localhost:8123/jmxrmi
It's a bit different than what I provided in the comments.
Finally, I am connected to my JMX Beans using JConsole.
Probably, I did something wrong in the beginning of my work with simplejmx.
I have not changed a lot of things. I kept jmx-config file and I still use version 1.8 of simplejmx.
I can easily connect to this bean locally - I have no idea why I was not able to do that earlier. Could you tell me, why in your opinion it should not be a local process?
Below, you can see that my JMX Bean appears in JConsole:
Probably, my DummyJMX class has not been published (or I just cannot find it).
When you are using the registryPort configuration for JmxServer then it will not show up in the "Local Process" list under Jconsole. It will be able to be accessed as a "Remote Process" with localhost:8123. If you are on a Linux box, you might use netstat -an | grep LISTEN to see what ports your application is listening on. If you don't see 8123 in the list then maybe it already has a RMI server configured?
If you want to use the platform mbean-server which does show up as a local process then use the new setter or constructor in version 1.9 which was released recently (4/2014). Unfortunately, SimpleJMX cannot programmatically register itself so it shows up in the process list -- that's not code that the JVM exports.
<bean id="jmxServer" class="com.j256.simplejmx.server.JmxServer"
init-method="start" destroy-method="stop">
<property name="usePlatformMBeanServer" value="true" />
</bean>
Using Spring:
can jta-transaction-manager use id as name so that I can pass it as REF to my service layer like below?
is tx:jta-transaction-manager can only be used for je22 container? I mean for Tomcat, I need to do it manually, like below:
<tx:jta-transaction-manager id="name_transactionmanager"/>
<bean id="projectService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"
ref="name_transactionmanager"/>
<property name="target">
<bean
class="com.company.project.company.services.ServiceImpl"
init-method="init">
<property
name="HRappsdao"
ref="HRappsdao"/>
<property
name="projectdao"
ref="projectdao"/>
</bean>
</property>
<property name="transactionAttributes">
<props>
<prop key="store*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="bulkUpdate*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
</props>
</property>
</bean>
For question 2
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction">
<bean class="org.springframework.transaction.jta.JotmFactoryBean"/>
</property>
</bean>
Can tx:jta-transaction-manager use id as name so that I can pass it as REF to my service layer like below?
The <tx:jta-transaction-manager> exposes the transaction manager as a Bean in the Spring context with the name "transactionManager".
Can tx:jta-transaction-manager only be used with a J2EE container?
Quoting the Chapter 9. Transaction management from the Spring documentation:
Is an application server needed for transaction management?
The Spring Framework's transaction
management support significantly
changes traditional thinking as to
when a J2EE application requires an
application server.
In particular, you don't need an
application server just to have
declarative transactions via EJB. In
fact, even if you have an application
server with powerful JTA capabilities,
you may well decide that the Spring
Framework's declarative transactions
offer more power and a much more
productive programming model than EJB
CMT.
Typically you need an application
server's JTA capability only if you
need to enlist multiple transactional
resources, and for many applications
being able to handle transactions
across multiple resources isn't a
requirement. For example, many
high-end applications use a single,
highly scalable database (such as
Oracle 9i RAC). Standalone transaction
managers such as Atomikos Transactions
and JOTM are other options. (Of course
you may need other application server
capabilities such as JMS and JCA.)
The most important point is that with
the Spring Framework you can choose
when to scale your application up to a
full-blown application server. Gone
are the days when the only alternative
to using EJB CMT or JTA was to write
code using local transactions such as
those on JDBC connections, and face a
hefty rework if you ever needed that
code to run within global,
container-managed transactions. With
the Spring Framework, only
configuration needs to change so that
your code doesn't have to.
So, as explained in the third paragraph, if you want to work with multiple transactional resources, you'll need global transactions which involve a JTA capable application server. And JTA capable application server means a real J2EE container or a non J2EE container (like Tomcat) with a standalone transaction manager like Atomikos, JOTM, Bitronix, SimpleJTA, JBossTS or GeronimoTM/Jencks.
FWIW, I've seen lots of complains about JOTM, I think that GeronimoTM/Jencks lacks of documentation, I can't really say anything about JBossTSArjunaTS (except that it's a rock solid product), SimpleJTA and Bitronix have both good documentation and Atomikos is an impressive product greatly documented too. Personally, I'd choose Bitronix or Atomikos.
PS: Honestly, if this sounds like Chinese to you, you should maybe consider using a single database (if this is an option, go for it!) or consider using a real J2EE container like JBoss or GlassFish as I wrote in a previous answer. No offense but all this JTA stuff is not trivial and taking the JOTM path is not that simple if you don't really understand why you need it.
I would like to configure a DataSource using JNDI in a Java SE app. What is the best way to do this?
So far, I've come across 2 projects:
Apache Naming. The project page has a specific example for configuring a data source, but it looks like the project is super old and no longer active.
JBossNS. It looks like it's easy to configure a local-only JNDI using LocalOnlyContextFactory, but I haven't found any docs on how to actually configure a data source.
If possible, I would like to also configure the data source with a JTA transaction manager (using JOTM?).
Why are you using JNDI for this? It's not that it's a bad solution if you have a provider but there are alternatives such as dependency injection (IoC: via Spring or Guice).
The Spring JDBC data access is described here. The great thing is that you can use Spring to inject a DataSource into your code:
<bean class="com.my.Persister">
<property name="dataSource" ref="dataSource" />
</bean>
The data source can be defined using a JNDI-lookup:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyDataSource" />
In a test environment, you could inject the data source directly:
<bean id="dataSource" class="apache.db.PoolingDataSource">
<!-- config goes here -->
</bean>
These references are pretty old but may help to use jnpserver (JBoss Naming Service provider):
Working With JNDI In A J2SE Application
Standalone JNDI server using jnpserver.jar
A very easy to use solution for stand-alone JNDI is simple-jndi. It works like a charm as long as you only need it within a single JVM, since it's a library no network server.
The Simple-JNDI version, referenced by klenkes74, is not under active development any more. Because I encountered some issues with it I forked it, did some bug fixes and implemented some new features. I already used the old version not only for testing but in production too because I prefer a Service Locator pattern over Dependency Injection although the latter one is more trendy nowadays.
You can easily use Simple-JNDI to define a DataSource or a connection pool declaratively and get it bound to a JNDI Context.
Define a jndi.properties file in your classpath:
java.naming.factory.initial=org.osjava.sj.SimpleContextFactory
org.osjava.sj.root=[absolute_or_relative_path_to_a_property_file]
The property file looks like:
type=javax.sql.DataSource
driver=org.gjt.mm.mysql.Driver
url=jdbc:mysql://localhost/testdb
user=testuser
password=testing
Now you can access your DataSource from inside your code this way:
InitialContext ctxt = new InitialContext();
DataSource ds = (DataSource) ctxt.lookup("name_of_your_datasource");
For more information see https://github.com/h-thurow/Simple-JNDI