How to put and get IBM MQ messages without application server - java

I'm a newbie in IBM MQ (https://www.ibm.com/cloud-computing/products/cloud-integration/mq-trial/index.html)
I'd like to know if I could send and get messages from IBM MQ using some code like this:
/*
* Sample program
* © COPYRIGHT International Business Machines Corp. 2009
* All Rights Reserved * Licensed Materials - Property of IBM
*
* This sample program is provided AS IS and may be used, executed,
* copied and modified without royalty payment by customer
*
* (a) for its own instruction and study,
* (b) in order to develop applications designed to run with an IBM
* WebSphere product for the customer's own internal use.
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import com.ibm.websphere.sib.api.jms.JmsConnectionFactory;
import com.ibm.websphere.sib.api.jms.JmsFactoryFactory;
import com.ibm.websphere.sib.api.jms.JmsQueue;
import com.ibm.websphere.sib.api.jms.JmsTopic;
/**
* Sample code to programmatically create a connection to a bus and
* send a text message.
*
* Example command lines:
* SIBusSender topic://my/topic?topicSpace=Default.Topic.Space MyBus localhost:7276
* SIBusSender queue://myQueue MyBus localhost:7286:BootstrapSecureMessaging InboundSecureMessaging
*/
public class SIBusSender {
/**
* #param args DEST_URL,BUS_NAME,PROVIDER_ENDPOINTS,[TRANSPORT_CHAIN]
*/
public static void main(String[] args) throws JMSException, IOException {
// Parse the arguments
if (args.length < 3) {
throw new IllegalArgumentException(
"Usage: SIBusSender <DEST_URL> <BUS_NAME> <PROVIDER_ENDPOINTS> [TARGET_TRANSPORT_CHAIN]");
}
String destUrl = args[0];
String busName = args[1];
String providerEndpoints = args[2];
String targetTransportChain = "InboundBasicMessaging";
if (args.length >= 4) targetTransportChain = args[3];
// Obtain the factory factory
JmsFactoryFactory jmsFact = JmsFactoryFactory.getInstance();
// Create a JMS destination
Destination dest;
if (destUrl.startsWith("topic://")) {
JmsTopic topic = jmsFact.createTopic(destUrl);
// Setter methods could be called here to configure the topic
dest = topic ;
}
else {
JmsQueue queue = jmsFact.createQueue(destUrl);
// Setter methods could be called here to configure the queue
dest = queue;
}
// Create a unified JMS connection factory
JmsConnectionFactory connFact = jmsFact.createConnectionFactory();
// Configure the connection factory
connFact.setBusName(busName);
connFact.setProviderEndpoints(providerEndpoints);
connFact.setTargetTransportChain(targetTransportChain);
// Create the connection
Connection conn = connFact.createConnection();
Session session = null;
MessageProducer producer = null;
try {
// Create a session
session = conn.createSession(false, // Not transactional
Session.AUTO_ACKNOWLEDGE);
// Create a message producer
producer = session.createProducer(dest);
// Loop reading lines of text from the console to send
System.out.println("Ready to send to " + dest + " on bus " + busName);
BufferedReader lineInput = new BufferedReader(new InputStreamReader(System.in));
String line = lineInput.readLine();
while (line != null && line.length() > 0) {
// Create a text message containing the line
TextMessage message = session.createTextMessage();
message.setText(line);
// Send the message
producer.send(message,
Message.DEFAULT_DELIVERY_MODE,
Message.DEFAULT_PRIORITY,
Message.DEFAULT_TIME_TO_LIVE);
// Read the next line
line = lineInput.readLine();
}
}
// Finally block to ensure we close our JMS objects
finally {
// Close the message producer
try {
if (producer != null) producer.close();
}
catch (JMSException e) {
System.err.println("Failed to close message producer: " + e);
}
// Close the session
try {
if (session != null) session.close();
}
catch (JMSException e) {
System.err.println("Failed to close session: " + e);
}
// Close the connection
try {
conn.close();
}
catch (JMSException e) {
System.err.println("Failed to close connection: " + e);
}
}
}
}
I created the queue in the IBM MQ Explorer.
My main doubt is how to do the connection and go on without application server.

Related

Error when import HashMap

Hi I'm using eclips indigo for developing my project and I'm getting error in my package - like this
Multiple markers at this line
- The type java.util.Map$Entry cannot be resolved. It is indirectly referenced from
required .class files
- The type java.util.Map$Entry cannot be resolved. It is indirectly referenced from
required .class files
Does anyone know why I'm getting error when I import Hashmap,util.map,common.collect.map in my java class
package info.sample.project;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.json.JSONException;
import org.json.JSONObject;
import com.google.common.collect.Maps;
#ServerEndpoint("/chat")
public class SocketServer {
// set to store all the live sessions
private static final Set<Session> sessions = Collections
.synchronizedSet(new HashSet<Session>());
// Mapping between session and person name
private static final HashMap<String, String> nameSessionPair = new HashMap<String, String>();
private JSONUtils jsonUtils = new JSONUtils();
// Getting query params
public static Map<String, String> getQueryMap(String query) {
Map<String, String> map = Maps.newHashMap();
if (query != null) {
String[] params = query.split("&");
for (String param : params) {
String[] nameval = param.split("=");
map.put(nameval[0], nameval[1]);
}
}
return map;
}
/**
* Called when a socket connection opened
* */
#OnOpen
public void onOpen(Session session) {
System.out.println(session.getId() + " has opened a connection");
Map<String, String> queryParams = getQueryMap(session.getQueryString());
String name = "";
if (queryParams.containsKey("name")) {
// Getting client name via query param
name = queryParams.get("name");
try {
name = URLDecoder.decode(name, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// Mapping client name and session id
nameSessionPair.put(session.getId(), name);
}
// Adding session to session list
sessions.add(session);
try {
// Sending session id to the client that just connected
session.getBasicRemote().sendText(
jsonUtils.getClientDetailsJson(session.getId(),
"Your session details"));
} catch (IOException e) {
e.printStackTrace();
}
// Notifying all the clients about new person joined
sendMessageToAll(session.getId(), name, " joined conversation!", true,
false);
}
/**
* method called when new message received from any client
*
* #param message
* JSON message from client
* */
#OnMessage
public void onMessage(String message, Session session) {
System.out.println("Message from " + session.getId() + ": " + message);
String msg = null;
// Parsing the json and getting message
try {
JSONObject jObj = new JSONObject(message);
msg = jObj.getString("message");
} catch (JSONException e) {
e.printStackTrace();
}
// Sending the message to all clients
sendMessageToAll(session.getId(), nameSessionPair.get(session.getId()),
msg, false, false);
}
/**
* Method called when a connection is closed
* */
#OnClose
public void onClose(Session session) {
System.out.println("Session " + session.getId() + " has ended");
// Getting the client name that exited
String name = nameSessionPair.get(session.getId());
// removing the session from sessions list
sessions.remove(session);
// Notifying all the clients about person exit
sendMessageToAll(session.getId(), name, " left conversation!", false,
true);
}
/**
* Method to send message to all clients
*
* #param sessionId
* #param message
* message to be sent to clients
* #param isNewClient
* flag to identify that message is about new person joined
* #param isExit
* flag to identify that a person left the conversation
* */
private void sendMessageToAll(String sessionId, String name,
String message, boolean isNewClient, boolean isExit) {
// Looping through all the sessions and sending the message individually
for (Session s : sessions) {
String json = null;
// Checking if the message is about new client joined
if (isNewClient) {
json = jsonUtils.getNewClientJson(sessionId, name, message,
sessions.size());
} else if (isExit) {
// Checking if the person left the conversation
json = jsonUtils.getClientExitJson(sessionId, name, message,
sessions.size());
} else {
// Normal chat conversation message
json = jsonUtils
.getSendAllMessageJson(sessionId, name, message);
}
try {
System.out.println("Sending Message To: " + sessionId + ", "
+ json);
s.getBasicRemote().sendText(json);
} catch (IOException e) {
System.out.println("error in sending. " + s.getId() + ", "
+ e.getMessage());
e.printStackTrace();
}
}
}
}
Try importing java.util.Map.Entry as well.

Posting a message in JMS queue using JAVA

I am new to JMS, after a long re search i googled out a code to connect to JMS and post a msg.
The problem is i need to post the message in a remote queue, But i am not sure how to establish connection to it and post the message.
SERVER TYPE : TIBCO EMS
SERVER HOST : **.*****.net
PORT : *
**USername : user
passsword : user123
Queue : *.*....Order.Management..1
I would like to establish connection, post a simple msg and retrieve it back.
Kindly help! thanks in advance
CODE WHICH I GOT FROM INTERNET
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Hashtable;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class emm {
// Defines the JNDI context factory.
public final static String JNDI_FACTORY="com.tibco.tibjms.naming.TibjmsInitialContextFactory";
// Defines the JMS context factory.
public final static String JMS_FACTORY="jms/TestConnectionFactory";
// Defines the queue.
public final static String QUEUE="CPW.GBR.POR.Public.Request.Order.Management.UpdateProvisioningStatus.1";
private QueueConnectionFactory qconFactory;
private ConnectionFactory conFactory;
private QueueConnection qcon;
private QueueSession qsession;
private QueueSender qsender;
private Queue queue;
private TextMessage msg;
/**
* Creates all the necessary objects for sending
* messages to a JMS queue.
*
* #param ctx JNDI initial context
* #param queueName name of queue
* #exception NamingException if operation cannot be performed
* #exception JMSException if JMS fails to initialize due to internal error
*/
public void init(Context ctx, String queueName)
throws NamingException, JMSException
{
qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
qcon = qconFactory.createQueueConnection();
qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queue = (Queue) ctx.lookup(queueName);
qsender = qsession.createSender(queue);
msg = qsession.createTextMessage();
qcon.start();
}
/**
* Sends a message to a JMS queue.
*
* #param message message to be sent
* #exception JMSException if JMS fails to send message due to internal error
*/
public void send(String message) throws JMSException {
msg.setText(message);
qsender.send(msg);
}
/**
* Closes JMS objects.
* #exception JMSException if JMS fails to close objects due to internal error
*/
public void close() throws JMSException {
qsender.close();
qsession.close();
qcon.close();
}
/** main() method.
*
* #param args WebLogic Server URL
* #exception Exception if operation fails
*/
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.out.println("Usage: java examples.jms.queue.QueueSend WebLogicURL");
return;
}
InitialContext ic = getInitialContext(args[0]);
emm qs = new emm();
qs.init(ic, QUEUE);
readAndSend(qs);
qs.close();
}
private static void readAndSend(emm qs)
throws IOException, JMSException
{
BufferedReader msgStream = new BufferedReader(new InputStreamReader(System.in));
String line=null;
boolean quitNow = false;
do {
System.out.print("Enter message (\"quit\" to quit): \n");
line = msgStream.readLine();
if (line != null && line.trim().length() != 0) {
qs.send(line);
System.out.println("JMS Message Sent: "+line+"\n");
quitNow = line.equalsIgnoreCase("quit");
}
} while (! quitNow);
}
private static InitialContext getInitialContext(String url)
throws NamingException
{
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
env.put(Context.PROVIDER_URL, url);
return new InitialContext(env);
}
}
Finally from different sources i found the best possible to way for this.
This code will definitely work. I have tried this out and is running currently on my machine
import java.util.Properties;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.*;
public class JMSExample {
static String serverUrl = "tcp://10.101.111.101:10001"; // values changed
static String userName = "user";
static String password = "pwd";
static QueueConnection connection;
static QueueReceiver queueReceiver;
static Queue queue;
static TextMessage message;
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);
session = connection.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue(topicName);
msgProducer = session.createProducer(null);
msg = session.createTextMessage();
msg.setStringProperty("SourceId", userName);
msg.setStringProperty("BusinessEvent", password);
msg.setText(messageStr);
msgProducer.send(destination, msg);
System.out.println("Published message: " + messageStr);
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws JMSException {
// TODO Auto-generated method stub
JMSExample.sendTopicMessage("***.***.***.**.**.Order.Management.***.1",
"Hi");
//System.out.println(getMessage());
}
As i mentioned some code for inspiration (SLIGHTLY improved your code. Not something i would want to see in production!)
// Use the domain-agnostic API
private Connection connection;ery
private Session session;
private MessageProducer producer;
private Queue queue;
public void init(Context ctx, String queueName) {
try {
ConnectionFactory cnf = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
queue = (Queue) ctx.lookup(queueName);
connection = cnf.createConnection("user", "user123");
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(queue);
connection.start();
} catch (NamingException e) {
throw new RuntimeException(e);
} catch (JMSException e) {
throw new RuntimeException(e);
}
}
And make your send like this (don't reuse the same Message object, but create a new one for each message you are sending)
public void send(String message) throws JMSException {
TextMessage msg = session.createTextMessage();
msg.setText(message);
producer.send(msg);
}
Put a try..finally around the code in your main method:
try {
readAndSend(qs);
} finally {
qs.close();
}
The code you are using is not very good (understatement). It is programmed too brittle for a production system. You should not use state the way this program does.
Also there is no need to use the domain specific JMS API. You can use the domain (queue/topic) agnostic one.
When you run the program pass in the JNDI URL for your TIBCO server.

How does HttpComponents send a response?

I'm trying to learn how to use Apache HttpComponents to send an HttpResponse. I found some examples on the Apache site but they are very confusing and unclear.
In the code below, I cannot see where the HttpResponse is generated and sent back to the client. After following along in the code, it seems that it must be happening in the HttpFileHandler class's handle() method, but it's not clear where. The class just ends with
...
response.setEntity(body);
System.out.println("File " + file.getPath() + " not found");
...
without actually sending the response. It ends with setting the Entity.
Where does the sending of the response back to the client actually happen in this code?
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.examples;
import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLDecoder;
import java.util.Locale;
import org.apache.http.ConnectionClosedException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.HttpServerConnection;
import org.apache.http.HttpStatus;
import org.apache.http.MethodNotSupportedException;
import org.apache.http.entity.ContentProducer;
import org.apache.http.entity.EntityTemplate;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.params.SyncBasicHttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.HttpRequestHandlerRegistry;
import org.apache.http.protocol.HttpService;
import org.apache.http.protocol.ImmutableHttpProcessor;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
import org.apache.http.util.EntityUtils;
/**
* Basic, yet fully functional and spec compliant, HTTP/1.1 file server.
* <p>
* Please note the purpose of this application is demonstrate the usage of
* HttpCore APIs. It is NOT intended to demonstrate the most efficient way of
* building an HTTP file server.
*
*
*/
public class ElementalHttpServer {
public static void main(String[] args) throws Exception {
args = new String[] { "e:/tutoring/236369/Tutorials/httpCoreExamples/" };
if (args.length < 1) {
System.err.println("Please specify document root directory");
System.exit(1);
}
Thread t = new RequestListenerThread(8080, args[0]);
t.setDaemon(false);
t.start();
}
static class HttpFileHandler implements HttpRequestHandler {
private final String docRoot;
public HttpFileHandler(final String docRoot) {
super();
this.docRoot = docRoot;
}
#Override
public void handle(final HttpRequest request,
final HttpResponse response, final HttpContext context)
throws HttpException, IOException {
String method = request.getRequestLine().getMethod()
.toUpperCase(Locale.ENGLISH);
if (!method.equals("GET") && !method.equals("HEAD")
&& !method.equals("POST")) {
throw new MethodNotSupportedException(method
+ " method not supported");
}
String target = request.getRequestLine().getUri();
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity entity = ((HttpEntityEnclosingRequest) request)
.getEntity();
byte[] entityContent = EntityUtils.toByteArray(entity);
System.out.println("Incoming entity content (bytes): "
+ entityContent.length);
}
final File file = new File(this.docRoot, URLDecoder.decode(target));
if (!file.exists()) {
response.setStatusCode(HttpStatus.SC_NOT_FOUND);
EntityTemplate body = new EntityTemplate(new ContentProducer() {
#Override
public void writeTo(final OutputStream outstream)
throws IOException {
OutputStreamWriter writer = new OutputStreamWriter(
outstream, "UTF-8");
writer.write("<html><body><h1>");
writer.write("File ");
writer.write(file.getPath());
writer.write(" not found");
writer.write("</h1></body></html>");
writer.flush();
}
});
body.setContentType("text/html; charset=UTF-8");
response.setEntity(body);
System.out.println("File " + file.getPath() + " not found");
} else if (!file.canRead() || file.isDirectory()) {
response.setStatusCode(HttpStatus.SC_FORBIDDEN);
EntityTemplate body = new EntityTemplate(new ContentProducer() {
#Override
public void writeTo(final OutputStream outstream)
throws IOException {
OutputStreamWriter writer = new OutputStreamWriter(
outstream, "UTF-8");
writer.write("<html><body><h1>");
writer.write("Access denied");
writer.write("</h1></body></html>");
writer.flush();
}
});
body.setContentType("text/html; charset=UTF-8");
response.setEntity(body);
System.out.println("Cannot read file " + file.getPath());
} else {
response.setStatusCode(HttpStatus.SC_OK);
FileEntity body = new FileEntity(file, "text/html");
response.setEntity(body);
System.out.println("Serving file " + file.getPath());
}
}
}
static class RequestListenerThread extends Thread {
private final ServerSocket serversocket;
private final HttpParams params;
private final HttpService httpService;
public RequestListenerThread(int port, final String docroot)
throws IOException {
this.serversocket = new ServerSocket(port);
this.params = new SyncBasicHttpParams();
this.params
.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE,
8 * 1024)
.setBooleanParameter(
CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
.setParameter(CoreProtocolPNames.ORIGIN_SERVER,
"HttpComponents/1.1");
// Set up the HTTP protocol processor
HttpProcessor httpproc = new ImmutableHttpProcessor(
new HttpResponseInterceptor[] { new ResponseDate(),
new ResponseServer(), new ResponseContent(),
new ResponseConnControl() });
// Set up request handlers
HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry();
reqistry.register("*", new HttpFileHandler(docroot));
// Set up the HTTP service
this.httpService = new HttpService(httpproc,
new DefaultConnectionReuseStrategy(),
new DefaultHttpResponseFactory(), reqistry, this.params);
}
#Override
public void run() {
System.out.println("Listening on port "
+ this.serversocket.getLocalPort());
while (!Thread.interrupted()) {
try {
// Set up HTTP connection
Socket socket = this.serversocket.accept();
DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
System.out.println("Incoming connection from "
+ socket.getInetAddress());
conn.bind(socket, this.params);
// Start worker thread
Thread t = new WorkerThread(this.httpService, conn);
t.setDaemon(true);
t.start();
} catch (InterruptedIOException ex) {
break;
} catch (IOException e) {
System.err
.println("I/O error initialising connection thread: "
+ e.getMessage());
break;
}
}
}
}
static class WorkerThread extends Thread {
private final HttpService httpservice;
private final HttpServerConnection conn;
public WorkerThread(final HttpService httpservice,
final HttpServerConnection conn) {
super();
this.httpservice = httpservice;
this.conn = conn;
}
#Override
public void run() {
System.out.println("New connection thread");
HttpContext context = new BasicHttpContext(null);
try {
while (!Thread.interrupted() && this.conn.isOpen()) {
this.httpservice.handleRequest(this.conn, context);
}
} catch (ConnectionClosedException ex) {
System.err.println("Client closed connection");
} catch (IOException ex) {
System.err.println("I/O error: " + ex.getMessage());
} catch (HttpException ex) {
System.err.println("Unrecoverable HTTP protocol violation: "
+ ex.getMessage());
} finally {
try {
this.conn.shutdown();
} catch (IOException ignore) {
}
}
}
}
}
You are running a server here.
The generic code to "talk HTTP" is already implemented by the library.
You just have to plug in the "business logic" (in the form of an HTTPRequestHandler).
Your "business logic" gets an instance of HTTPResponse as a parameter. This object has already been created for you by the library. You can set parameters and write data to.
When your handler method returns (or even before that as you manipulate the response object), the library takes care of getting the data over the network.
Where does the sending of the response back to the client actually happen in this code?
As the result of method handle the response object now contains an Entity with your inner class that can write out a file. That code will be called to send the data.
It might be instructive (or possibly overwhelming) to put a breakpoint in your code and step through (including the part after handle returns) to see the control flow.

JavaMail - How to set SMTP “RCPT TO:” that will not match “To:” Header in DATA

In my small project, I want to setup the "RCPT TO" and "To" look like this:
RCPT TO: <user-signup-123123123#bounces.example.com>
DATA
354 Go ahead vw9sm7458976pbc.68 - gsmtp
Date: Thu, 02 Mar 2012 14:06:02 +0200 (ICT)
To: +10xxxxxxxxxx
And I tried with the following code
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("HOST");
mailSender.setPort("PORT");
mailSender.setUsername("USERNAME");
mailSender.setPassword("PASSWORD");
MimeMessage mimeMessage = mailSender.createMimeMessage();
try {
mimeMessage.setRecipient(MimeMessage.RecipientType.TO,
new InternetAddress("user-signup-123123123#bounces.example.com"));
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setTo("+10xxxxxxxxxx");
} catch(Exception e) {
System.out.println(e.getMessage());
}
And the log I got
MAIL FROM:<abc#xxxxx.com>
250 2.1.0 OK x5sm16625925pbw.26 - gsmtp
RCPT TO:<user-signup-123123123#bounces.example.com>
250 2.1.5 OK x5sm16625925pbw.26 - gsmtp
RCPT TO:<+10xxxxxxxxxx>
As you see, the program created a new "RCPT TO" value with "+10xxxxxxxxxx".
How can I set "RCPT TO" value that will not match with "To" header in DATA?
I just had a look at the source code of MimeMessageHelper you will see that the setTo() functions all call javax.mail.Message#setRecipient just like you did the command before using the Helper.
I see two solutions using JavaMail:
Extend MimeMessage and override getAllRecipients() as this method is used to determine recipients in JavaMailImpl
// yes you need to use this package as SmartMimeMessage is package-private or you loose spring advantages
package org.springframework.mail.javamail;
import javax.activation.FileTypeMap;
import javax.mail.Address;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
/**
* Created for http://stackoverflow.com/q/22860793/1266906
*/
public class RoutedSmartMimeMessage extends SmartMimeMessage {
private Address[] rcptTo = null;
/**
* Create a new SmartMimeMessage.
*
* #param session
* the JavaMail Session to create the message for
* #param defaultEncoding
* the default encoding, or {#code null} if none
* #param defaultFileTypeMap
* the default FileTypeMap, or {#code null} if none
*/
public RoutedSmartMimeMessage(final Session session,
final String defaultEncoding,
final FileTypeMap defaultFileTypeMap) {
super(session, defaultEncoding, defaultFileTypeMap);
}
public Address[] getRcptTo() {
return rcptTo;
}
public void setRcptTo(final Address... rcptTo) {
this.rcptTo = rcptTo;
}
#Override
public Address[] getAllRecipients() throws MessagingException {
if(rcptTo != null) {
return rcptTo;
} else {
return super.getAllRecipients();
}
}
public static MimeMessage createMesage(final JavaMailSenderImpl javaMailSender) {
return new SmartMimeMessage(javaMailSender.getSession(), javaMailSender.getDefaultEncoding(), javaMailSender.getDefaultFileTypeMap());
}
}
Write your own send method and use Transport#sendMessage(javax.mail.Message, javax.mail.Address[]) directly
Based upon the spring-wrapper around JavaMail:
import org.springframework.mail.MailAuthenticationException;
import org.springframework.mail.MailException;
import org.springframework.mail.MailSendException;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Created for http://stackoverflow.com/q/22860793/1266906
*/
public class Mailing {
public static void main(String[] args) {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("HOST");
mailSender.setPort(25);
mailSender.setUsername("USERNAME");
mailSender.setPassword("PASSWORD");
MimeMessage mimeMessage = mailSender.createMimeMessage();
try {
/*
Not needed
mimeMessage.setRecipient(MimeMessage.RecipientType.TO,
new InternetAddress("user-signup-123123123#bounces.example.com"));
*/
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setTo("+10xxxxxxxxxx");
sendMail(mailSender, mimeMessage, new InternetAddress("user-signup-123123123#bounces.example.com"));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
/**
* Adopted from {#link org.springframework.mail.javamail.JavaMailSenderImpl#doSend(javax.mail.internet.MimeMessage[], Object[])} to be able to call {#link javax.mail.Transport#send(javax.mail.Message, javax.mail.Address[])} with a different second parameter than {#link javax.mail.Message#getAllRecipients() mimeMessage.getAllRecipients()}
*
* #param javaMailSender
* JavaMailSender object holding configuration options
* #param mimeMessage
* MimeMessage object to send
* #param realRecipients
* RCPT TO: sddresses
* #throws org.springframework.mail.MailAuthenticationException
* in case of authentication failure
* #throws org.springframework.mail.MailSendException
* in case of failure when sending a message
*/
private static void sendMail(final JavaMailSenderImpl javaMailSender,
final MimeMessage mimeMessage,
final Address... realRecipients) throws MailException {
final Map<Object, Exception> failedMessages = new LinkedHashMap<Object, Exception>();
final Transport transport;
try {
Session session = javaMailSender.getSession();
String protocol = javaMailSender.getProtocol();
if (protocol == null) {
protocol = session.getProperty("mail.transport.protocol");
if (protocol == null) {
protocol = JavaMailSenderImpl.DEFAULT_PROTOCOL;
}
}
transport = session.getTransport(protocol);
transport.connect(javaMailSender.getHost(),
javaMailSender.getPort(),
javaMailSender.getUsername(),
javaMailSender.getPassword());
} catch (AuthenticationFailedException ex) {
throw new MailAuthenticationException(ex);
} catch (MessagingException ex) {
failedMessages.put(mimeMessage, ex);
throw new MailSendException("Mail server connection failed", ex, failedMessages);
}
try {
try {
if (mimeMessage.getSentDate() == null) {
mimeMessage.setSentDate(new Date());
}
String messageId = mimeMessage.getMessageID();
mimeMessage.saveChanges();
if (messageId != null) {
// Preserve explicitly specified message id...
mimeMessage.setHeader("Message-ID", messageId);
}
transport.sendMessage(mimeMessage, realRecipients);
} catch (MessagingException ex) {
failedMessages.put(mimeMessage, ex);
}
} finally {
try {
transport.close();
} catch (MessagingException ex) {
if (!failedMessages.isEmpty()) {
throw new MailSendException("Failed to close server connection after message failures", ex,
failedMessages);
} else {
throw new MailSendException("Failed to close server connection after message sending", ex);
}
}
}
if (!failedMessages.isEmpty()) {
throw new MailSendException(failedMessages);
}
}
}
The trick to sending mail to a "RCPT To" address and including other "To" addresses in the mail without actually sending the mail to other "To" is to use
message.send(message, InternetAddress) instead of message.send(message)
and set the other "To" in message.setRecipients
Here's the code snippet:
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
InternetAddress[] addresses = new InternetAddress[recipientaddresstoshowinmail];
message.setRecipients(Message.RecipientType.TO, addresses);
message.setSubject(subject);
message.setText(body);
InternetAddress[] toaddress = new InternetAddress[] {new InternetAddress(to)};
**Transport.send(message, actualtoaddress);**

ActiveMQ some consumers not picking up tasks if they arrive after producer

Im just getting starting with ActiveMQ and i seem to have a weird problem. (Source below)
There are 2 scenarios
Consumers connect to broker, waits for tasks on the queue. Producer arrives later, drops the list of tasks and they are rightly taken up by the different consumers and performed. This works fine and i have simulated it as well.
Producer connects first, drops the list of tasks. No consumers are connected at this point. Now when lets say 3 consumers - C1, C2 and C3 connect to the broker (in that order) i see that only C1 picks up and does the tasks that are dropped by the producer. C2 and C3 stay idle. Why does this happen?
I've also noticed 1 more thing in regards to the 2nd scenario -- If the producer keeps on dropping tasks inside the queue, C2 and C3 pick up tasks but if the producer has dropped tasks before (as mentioned) then C2 and C3 dont do anything.
Producer code
package com.activemq.apps;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
import com.commons.helpers.Maths;
public class Publisher implements MessageListener {
private static String _URL;
private static String _TOPIC_PUBLISH;
private static String _TOPIC_CONSUME;
public Publisher (String URL, String TOPIC) {
_URL = URL;
_TOPIC_PUBLISH = TOPIC + "_REQUESTS";
_TOPIC_CONSUME = TOPIC + "_RESPONSES";
}
public void initialize() {
try
{
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(_URL);
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destinationProducer = session.createQueue(_TOPIC_PUBLISH);
Destination destinationConsumers = session.createQueue(_TOPIC_CONSUME);
MessageProducer producer = session.createProducer(destinationProducer);
MessageConsumer consumer = session.createConsumer(destinationConsumers);
consumer.setMessageListener(this);
int count = 0;
System.out.println("Sending requests");
while (true)
{
int randomSleepTime = Maths.rand(1000, 5000);
String messageToSend = count + "_" + randomSleepTime;
TextMessage message = session.createTextMessage(messageToSend);
producer.send(message);
System.out.println("Job #" + count + " | " + (randomSleepTime/1000) + "s");
if (count++%10 == 0)
Thread.sleep(10000);
}
}
catch (JMSException ex)
{
ex.printStackTrace();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void onMessage(Message message) {
if (message instanceof TextMessage)
{
TextMessage msg = (TextMessage) message;
try {
String response = msg.getText();
String[] responseSplit = response.split("_");
String clientId = responseSplit[1];
String count = responseSplit[0];
System.out.println("Got response from " + clientId + " Job #" + count);
}
catch (JMSException e) {
e.printStackTrace();
}
}
}
}
Consumer code
package com.activemq.apps;
import java.util.UUID;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Consumer implements MessageListener {
private static String _URL;
private static String _TOPIC_PUBLISH;
private static String _TOPIC_CONSUME;
private static String _CLIENTID;
private MessageProducer producer;
private Session session;
public Consumer (String URL, String TOPIC) {
_URL = URL;
_TOPIC_PUBLISH = TOPIC + "_RESPONSES";
_TOPIC_CONSUME = TOPIC + "_REQUESTS";
}
public void initialize() {
try
{
_CLIENTID = UUID.randomUUID().toString();
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(_URL);
Connection connection = connectionFactory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destinationProducer = session.createQueue(_TOPIC_PUBLISH);
Destination destinationConsumers = session.createQueue(_TOPIC_CONSUME);
producer = session.createProducer(destinationProducer);
MessageConsumer consumer = session.createConsumer(destinationConsumers);
consumer.setMessageListener(this);
System.out.println("Client: " + _CLIENTID + "\nWaiting to pick up tasks");
}
catch (JMSException ex)
{
ex.printStackTrace();
}
}
#Override
public void onMessage(Message message) {
if (message instanceof TextMessage)
{
TextMessage msg = (TextMessage) message;
try
{
String[] messageSplits = msg.getText().split("_");
String count = messageSplits[0];
String timeString = messageSplits[1];
int sleepFor = Integer.parseInt(timeString);
System.out.println("Job #" + count + " | Sleeping for " + (sleepFor/1000) + "s");
Thread.sleep(sleepFor);
TextMessage sendToProducer = session.createTextMessage(count + "_" + _CLIENTID);
producer.send(sendToProducer);
}
catch (JMSException e) {
e.printStackTrace();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
You have mentioned
Now when lets say 3 consumers - C1, C2 and C3 connect to the broker
(in that order)
Since C1 connects first it starts getting all the messages on the queue immediately after it connects. That is expected. So i dont see any issue here. C2, C3 are not idle but C1 has got hold of the messages before C2 and C3 could.
I am not sure how many messages were sent by the producer. I assume the number of messages are less. To see what you expect try sending many messages from the producer, like thousands or millions and then start the consumers. The high number of messages are subjective and depends on the memory, network and other resources. You might see what you are expecting.
I dont think there is anything weird here. Queues represent P2P mode which is supposed to have only one consumer. In our case we have 3 consumers, it's not forbidden, but there is no guarantee of any specific order in which consumers will receive messages.
I believe you should check prefetchPolicy param for your consumer. By default, prefetch policy has default value 1000. It means that the first consumer fetches up to 1000 messages and other consumers are not able to fetch anything else. If you are trying load balance your messages across consumers consider to modify this param to 0 or 1.

Categories

Resources