I would like to publish a test message to EMS topic and could use some directions. So far I have managed to do this
import com.tibco.tibjms.TibjmsConnectionFactory;
import com.tibco.tibjms.TibjmsTopicConnectionFactory;
public class Connect {
public static void main(String[] args) {
String url = "tcp://host:6600";
TibjmsConnectionFactory cf = new TibjmsTopicConnectionFactory(url);
cf.setUserName("user1");
cf.setUserPassword("");
System.out.println(cf);
}
}
which produces the below. How do I publish a message to topic "topic1" or queue "Q1"
TopicConnectionFactory[URL=tcp://localhost:6600;clientID=null;Properties={com.tibco.tibjms.factory.password=, com.tibco.tibjms.factory.username=user1}]
I created the following code by modifying the "tibjmsMsgProducer.java" from my EMS 8.0 "sample" folder. Look at all the Java example in this folder for further references.
This code publish a simple hard-coded text message to a local EMS with default user and password. The target Topic is "topic1" (on the last line).
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
public class tibjmsMsgTopicProducer {
static String serverUrl = "localhost";
static String userName = "admin";
static String password = "admin";
public static void sendTopicMessage(String topicName, String messageStr) {
Connection connection = null;
Session session = null;
MessageProducer msgProducer = null;
Destination destination = null;
try {
TextMessage msg;
System.out.println("Publishing to destination '" + topicName
+ "'\n");
ConnectionFactory factory = new com.tibco.tibjms.TibjmsConnectionFactory(
serverUrl);
connection = factory.createConnection(userName, password);
/* create the session */
session = connection
.createSession(javax.jms.Session.AUTO_ACKNOWLEDGE);
/* create the destination */
destination = session.createTopic(topicName);
/* create the producer */
msgProducer = session.createProducer(null);
/* publish messages */
/* create text message */
msg = session.createTextMessage();
/* set message text */
msg.setText(messageStr);
/* publish message */
msgProducer.send(destination, msg);
System.out.println("Published message: " + messageStr);
/* close the connection */
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
/*-----------------------------------------------------------------------
* main
*----------------------------------------------------------------------*/
public static void main(String[] args) {
tibjmsMsgTopicProducer.sendTopicMessage("topic1",
"This is the message content !");
}
}
Note : You could also want to use EMS with Spring-JMS for a more "Enterprise grade" solution. The code above is a lot simpler.
Note2: I made the method "static". This is only for demonstration purpose. Connections are costly in JMS, so normally we try to reuse them. See all TIBCO provided example for better setup of the Java classes. Instantiate and reuse connections if you can.
Additionally, J2EE or Spring solutions will have support for connection pools built-in.
I haven't touched EMS for some time - but basically EMS is nothing but a JMS implementation. All implementation specific stuff has been hidden for you. You just use standard JMS way to pub/sub to topics, which you can find good example on Java tutorial and online sources. I would save my ugly sample code here :-)
You can take a look at this test project #gelnyang built. And this is the class for publishing EMS message specifically. Under the project, you can find other EMS related functionalities as well.
Related
I am trying to connect to a QM and send message to one of the queues, using below code:
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.JMSException;
import com.ibm.msg.client.commonservices.*;
import com.ibm.mq.commonservices.internal.trace.*;
import com.ibm.msg.client.jms.JmsConnectionFactory;
import com.ibm.msg.client.jms.JmsFactoryFactory;
import com.ibm.msg.client.wmq.WMQConstants;
public class MQConnect {
public static void main(String[] args) {
Connection connection = null;
Session session = null;
Destination destination = null;
Destination tempDestination = null;
MessageProducer producer = null;
MessageConsumer consumer = null;
try {
System.out.println(WMQConstants.WMQ_PROVIDER);
JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
JmsConnectionFactory cf = ff.createConnectionFactory();
cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, "hostname");
cf.setIntProperty(WMQConstants.WMQ_PORT, port);
cf.setStringProperty(WMQConstants.WMQ_CHANNEL, "channel");
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, "QMName");
connection = cf.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue("test_java_q");
producer = session.createProducer(destination);
long uniqueNumber = System.currentTimeMillis() % 1000;
TextMessage message = session.createTextMessage(" " + uniqueNumber);
connection.start();
producer.send(message);
}catch (JMSException jmsex) {
System.out.println(jmsex.getErrorCode());
System.out.println(jmsex.getLinkedException().getCause());
System.out.println(jmsex.getMessage());
}
}
}
The error I'm getting is :
Exception in thread "main" java.lang.NoClassDefFoundError:
com/ibm/msg/client/commonservices/trace/Trace
at com.ibm.msg.client.jms.JmsFactoryFactory.<clinit>(JmsFactoryFactory.java:54)
at MQConnect.main(MQConnect.java:33)
Caused by: java.lang.ClassNotFoundException: com.ibm.msg.client.commonservices.trace.Trace
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 2 more
I have the required jar files but I believe something is still missing from project references.
I have checked the jars and class specified in error is present in one of the jar files.
These are the jar files I have referenced:
com.ibm.mq.headers.jar
com.ibm.mq.jar
com.ibm.mq.pcf.jar
com.ibm.mq.tools.ras.jar
jms.jar
com.ibm.mqjms.jar
com.ibm.mq.jmqi.jar
com.ibm.mq.commonservices.jar
There are also several other jars which are not com.ibm.*
Any suggestions?
You really shouldn't be picking and choosing MQ JAR files. For IBM MQ v8.0 or higher, you should be using the com.ibm.mq.allclient.jar and jms.jar files. That's it, just 2 files. IBM has posted the com.ibm.mq.allclient.jar file on Maven (and use the most recent one). You can find com.ibm.mq.allclient.jar here and jms.jar from here.
If you are using IBM MQ v7.5 or lower (which all releases are out of support) then the correct JAR files are:
connector.jar
com.ibm.mq.jar
com.ibm.mq.commonservices.jar
com.ibm.mq.headers.jar
com.ibm.mq.jmqi.jar
com.ibm.mq.pcf.jar
com.ibm.mqjms.jar
jms.jar
fscontext.jar
jndi.jar
jta.jar
ldap.jar
Also, do NOT mix and match JAR files between different releases of IBM MQ. It will cause you all kinds of headaches.
Finally, what is this line:
destination = session.createQueue("test_java_q");
It should be:
destination = context.createQueue("queue:///MY.TEST.QUEUE");
where 'MY.TEST.QUEUE' actually exists in the queue manager. All MQ objects are case sensitive and MQ Best Practises says to use uppercase object names. i.e. avoid lowercase names.
Updated Feb. 14, 2022.
You need to add some code to your program so we can see what is going on.
(1) Add the following MQLevel class (taken from my open source project Universal File Mover) to your project:
public class MQLevel extends MQJavaLevel
{
/**
* The constructor
*/
public MQLevel()
{
super();
}
/**
* Get the IBM name for the MQ JAR class.
* #return
*/
public String getName()
{
return queryValue(0);
}
/**
* Get the version of the MQ JAR class.
* #return
*/
public String getVersion()
{
return queryValue(1);
}
}
(2) Next add the following lines of code in your main method or at the very top of your code:
System.out.println(System.getProperty("java.class.path").replace(';','\n'));
try
{
MQLevel mql = new MQLevel();
System.out.println("MQ JAR Version = " + mql.getName()+" V"+mql.getVersion());
}
catch(Exception e)
{
e.printStackTrace();
}
Note: If you are on Linux/Unix rather than Windows then change the ';' (semi-colon) in the replace method to a ':' (colon).
i.e.
System.out.println(System.getProperty("java.class.path").replace(':','\n'));
Run your program with the updates, then update the original posting both with the new output.
Im trying to develop a "Message Driven Bean" to handle all the local ActiveMQ messages, but it's the first time that i try to do something like this.
The most part of the material that i found explain how to write a MDB using JBOSS server, in this case there's a xml file with some queue information, but in all wildfly tutorials there's no mention to any kind of configuration like that.
I have the following scenario:
A simple java project like message producer
An ActiveMQ instance running local
An EJB project deployed into Wildfly 10
My producer project is able to send messages to ActiveMQ queue, this part its working,but my EJB project just have a single class called TestMDBHandle with #MessageDriven annotation. Is this enough to receive my queue messages? Because the MDB isnt working, i imagine must be a kind of configuration or property in EJB to specify the host of the message-broker.
My message producer:
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class MessageSender {
public static void main(String args[]) throws NamingException, JMSException {
MessageSender sender = new MessageSender();
sender.sender();
}
public void sender() throws NamingException, JMSException {
InitialContext jndi = null;
Session session = null;
Connection connection = null;
try {
jndi = new InitialContext();
ConnectionFactory factory = (ConnectionFactory)jndi.lookup("connectionFactory");
connection = factory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = (Destination)jndi.lookup("MyQueue");
MessageProducer producer = session.createProducer(destination);
TextMessage mensagem = session.createTextMessage("Eu enviei uma mensagem!");
producer.send(mensagem);
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
connection.close();
jndi.close();
}
}
}
My jms properties located inside my producer project
java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:61616
connectionFactoryNames = connectionFactory, queueConnectionFactory, topicConnectionFactory
queue.MyQueue=jms/myqueue
Finally, my ejb project have this single class, without any kind of property file or xml.
package br.com.jms.mdb;
import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.EJB;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
#MessageDriven(name = "meuHandler", activationConfig = {
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(propertyName = "destination", propertyValue = "jms/myqueue") })
public class Teste implements MessageListener {
#Resource
private MessageDrivenContext mdctx;
public Teste() {
}
#Override
public void onMessage(Message message) {
TextMessage objectMessage = null;
try {
objectMessage = (TextMessage)message;
System.out.println("Achei a mensagem : " + objectMessage.getText().toString());
}catch(JMSException e) {
e.printStackTrace();
}
}
}
Maybe you can provide a little more information such as the xml file with the queue information and the annotation properties of the MDB? Because it sounds you are heading in the right direction. The two main things:
You have to specify the exact queue that the MDB is listening to, for example through the properties of the #MessageDriven annotation (such as "name", "mappedName", "activationConfig"). And of course override the onMessage() method to process the messages.
You also have to make sure that this specific queue is available as a resource for your application. You have to provide jms configuration for this, which also defines the resource type (Queue or Topic). From your question I can't tell which of these steps you have (partly) completed.
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Producer {
private static String url = ActiveMQConnection.DEFAULT_BROKER_URL;
private static String QUEUE_NAME = "kesaven";
private static final Logger logger = LogManager.getLogger(Producer.class.getName());
public static void main(String[] args) throws JMSException
{
//System.out.println(url);
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue(QUEUE_NAME);
MessageProducer producer = session.createProducer(destination);
//TextMessage message = session.createTextMessage("My first log message to queue");
logger.info("My first log message to queue");
//producer.send(message);
//System.out.println("Sentage '" + message.getText() + "'");
connection.close();
}
}
i am trying to log the message to a queue using log4j2 and activemq. i am using log4j2.3 and for queue i am using activemq 5.9.0 . i am able to see exception message in queue not the message i sent. Following is the error message in queue
javax.jms.JMSException: Failed to build body from content.
Serializable class not available to broker. Reason:
java.lang.ClassNotFoundException:
org.apache.logging.log4j.core.impl.Log4jLogEvent$LogEventProxy
What appender are you using to write the data to ActiveMQ? I would suggest that instead of using Java serialization to write the log event that you serialize it to JSON, use the RFC5424 layout or some other format that doesn't require the Log4j2 jars when reading the events.
Since the Log4event is put on the queue , can you check if you have the log4j2 jars available on the broker end.
I added the following jars from log4j2 to the activeMQ server /lib directory to make this work
log4j-api-2.6.1,
log4j-core-2.6.1
I logged Strings only, if I tried to log ObjectMessages, the queue entry would not open in the Queue manager view, the JSP failed.
When I run the client it's supposed to send an email to my server and then I want my email server to print out the email details (to, from, port, message) to console. For some reason after running the client, nothing apparent happens on the server.
server
package example;
import org.subethamail.smtp.server.SMTPServer;
public class EmailServer {
public static void main(String[] args) {
MyMessageHandlerFactory myFactory = new MyMessageHandlerFactory();
SMTPServer smtpServer = new SMTPServer(myFactory);
smtpServer.setPort(25000);
smtpServer.start();
}
}
server output
run: [main] INFO org.subethamail.smtp.server.SMTPServer - SMTP server
*:25000 starting [org.subethamail.smtp.server.ServerThread *:25000] INFO org.subethamail.smtp.server.ServerThread - SMTP server *:25000
started
client
package example;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.subethamail.smtp.client.*;
public class EmailClient {
public static void main(String[] args) {
try {
SMTPClient sc = new SMTPClient();
sc.close();
sc.connect("localhost", 25000);
sc.sendReceive("test");
} catch (IOException ex) {
Logger.getLogger(EmailClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
client output
run: BUILD SUCCESSFUL (total time: 0 seconds)
Version is 3.1.7 from https://code.google.com/p/subethasmtp/downloads/list
The server requires MyMessageHandlerFactory which I copied from: https://code.google.com/p/subethasmtp/wiki/SimpleExample
OK, let's check the source code (always a good idea) and see what happens.
You send "test" via
SMTPClient sc;
sc.sendReceive("test"); // which is actually sent to your SMTPServer as "test\r\n"
Now, considering that this is a new SMTP conversation (see RFC5321 for everything you always wanted to know but were afraid to ask about such things) and "test" isn't a valid command VERB at this point in the conversation, you would expect to see an error returned by sendReceive().
But since you're ignoring the SMTPClient.Response#75 returned from what should have been
Response resp=SMTPClient.sendReceive()
you're missing out on both
resp.code (which I am sure is 500 - Permanent Negative Completion reply / Syntax - see the RFC above) and
resp.message describing the reason your command could not be fulfulled
both of which are returned from CommandHandler#93.
I'm in the process of making a proof of concept to dissociate the business code from the gui for the ps3 media server (http://www.ps3mediaserver.org/). For this I've got a project hosted at source forge (http://sourceforge.net/projects/pms-remote/). The client should be a simple front end to configure the server from any location within a network having the rights to connect to the server.
On the server side, all service have been exposed using javax.jws and the client proxy has been generated using wsimport.
One of the features of the current features (actually, the only blocking one), is to define the folders that will be shared by the server. As the client and server are now running as a single application on the same machine, it's trivial to browse its file system.
Problem: I'd like to expose the file system of the server machine through web services. This will allow any client (the one I'm currently working on is the same as the original using java swing) to show available folders and to select the ones that will be shown by the media server. In the end the only thing I'm interested in is an absolute folder path (string).
I thought I'd find a library giving me this functionality but couldn't find any.
Browsing the files using a UNC path and accessing a distant machine doesn't seem feasible, as it wouldn't be transparent for the user.
For now I don't want to worry about security issues, I'll figure these out once the rest seems feasible.
I'd be grateful for any input.
Thanks, Philippe
I've ended up creating a pretty simple web service letting either list all root folders or all child folders for a given path.
It's now up to the client to have a (GUI) browser to access this service.
package net.pms.plugin.webservice.filesystem;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import net.pms.plugin.webservice.ServiceBase;
#WebService(serviceName = "FileSystem", targetNamespace = "http://ps3mediaserver.org/filesystem")
public class FileSystemWebService extends ServiceBase {
#WebMethod()
public List<String> getRoots() {
List<String> roots = new ArrayList<String>();
for(File child : File.listRoots()) {
roots.add(child.getAbsolutePath());
}
return roots;
}
#WebMethod()
public List<String> getChildFolders(#WebParam(name="folderPath") String folderPath) throws FileNotFoundException {
List<String> children = new ArrayList<String>();
File d = new File(folderPath);
if(d.isDirectory()) {
for(File child : d.listFiles()) {
if(child.isDirectory() && !child.isHidden()) {
children.add(child.getAbsolutePath());
}
}
} else {
throw new FileNotFoundException();
}
return children;
}
}
For people wanting to use this, here's the ServiceBase class as well
package net.pms.plugin.webservice;
import javax.xml.ws.Endpoint;
import org.apache.log4j.Logger;
public abstract class ServiceBase {
private static final Logger log = Logger.getLogger(ServiceBase.class);
protected boolean isInitialized;
/**
* the published endpoint
*/
private Endpoint endpoint = null;
/**
*
* Start to listen for remote requests
*
* #param host ip or host name
* #param port port to use
* #param path name of the web service
*/
public void bind(String host, int port, String path) {
String endpointURL = "http://" + host + ":" + port + "/" + path;
try {
endpoint = Endpoint.publish(endpointURL, this);
isInitialized = true;
log.info("Sucessfully bound enpoint: " + endpointURL);
} catch (Exception e) {
log.error("Failed to bind enpoint: " + endpointURL, e);
}
}
/**
* Stop the webservice
*/
public void shutdown() {
log.info("Shut down " + getClass().getName());
if (endpoint != null)
endpoint.stop();
endpoint = null;
}
}
From the client, you might be able to leverage the output of smbclient -L. On the server, a suitable servlet might do.