Very little documentation, above what exists in the sample code is currently available for Grizzly 2.2 and I have found this to be most difficult to navigate as it relates to SSL implementation. I am desperately in need of some guidance in this area. After reviewing my code to determine what I need to post in order to pose a complete question, I realized it might be most beneficial to first cement the basics.
Below are three classes provided by the Grizzly project in order to demonstrate a sample implementation of Grizzly's SSL capabilities. Besides the removal of comments, the code is identical to the 2.2.19 released code base as maintained in git at git://java.net/grizzly~git and also available here.
The git repository also provides the referenced truststore and keystore.
EchoFilter:
public class EchoFilter extends BaseFilter{
#Override
public NextAction handleRead(FilterChainContext ctx)throws IOException {
//|Peer address is used for non-connected UDP Connection
final Object peerAddress = ctx.getAddress();
final Object message = ctx.getMessage();
ctx.write(peerAddress, message, null);
return ctx.getStopAction();
}
}
SSLEchoServer:
public class SSLEchoServer{
public static final String HOST = "localhost";
public static final int PORT = 7777;
public static void main(String[] args) throws IOException{
//|Create a FilterChain using FilterChainBuilder
FilterChainBuilder filterChainBuilder = FilterChainBuilder.stateless();
//|Add TransportFilter, which is responsible for reading and writing data to the connection
filterChainBuilder.add(new TransportFilter());
//|Initialize and add SSLFilter
final SSLEngineConfigurator serverConfig = initializeSSL();
final SSLEngineConfigurator clientConfig = serverConfig.copy().setClientMode(true);
filterChainBuilder.add(new SSLFilter(serverConfig, clientConfig));
//|Add StringFilter, which will be responsible for Buffer <-> String transformation
filterChainBuilder.add(new StringFilter(Charset.forName("UTF-8")));
//|Use the plain EchoFilter
filterChainBuilder.add(new EchoFilter());
//|Create TCP transport
final TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build();
//|Set filterchain as a Transport Processor
transport.setProcessor(filterChainBuilder.build());
try{
//|Binding transport to start listen on certain host and port
transport.bind(HOST, PORT);
//|Start the transport
transport.start();
System.out.println("Press any key to stop the server...");
System.in.read();
}finally{
System.out.println("Stopping transport...");
//|Stop the transport
transport.stop();
System.out.println("Stopped transport...");
}
}
private static SSLEngineConfigurator initializeSSL(){
//|Initialize SSLContext configuration
SSLContextConfigurator sslContextConfig = new SSLContextConfigurator();
//|Set key store
ClassLoader cl = SSLEchoServer.class.getClassLoader();
URL cacertsUrl = cl.getResource("ssltest-cacerts.jks");
if(cacertsUrl != null){
sslContextConfig.setTrustStoreFile(cacertsUrl.getFile());
sslContextConfig.setTrustStorePass("changeit");
}
//|Set trust store
URL keystoreUrl = cl.getResource("ssltest-keystore.jks");
if(keystoreUrl != null){
sslContextConfig.setKeyStoreFile(keystoreUrl.getFile());
sslContextConfig.setKeyStorePass("changeit");
}
//|Create SSLEngine configurator
return new SSLEngineConfigurator(sslContextConfig.createSSLContext(), false, false, false);
}
}
SSLEchoClient:
public class SSLEchoClient{
private static final String MESSAGE = "Hello World!";
public static void main(String[] args) throws IOException{
//|Create a FilterChain using FilterChainBuilder
FilterChainBuilder filterChainBuilder = FilterChainBuilder.stateless();
//|Add TransportFilter, which is responsible for reading and writing data to the connection
filterChainBuilder.add(new TransportFilter());
//|Initialize and add SSLFilter
final SSLEngineConfigurator serverConfig = initializeSSL();
final SSLEngineConfigurator clientConfig = serverConfig.copy().setClientMode(true);
final SSLFilter sslFilter = new SSLFilter(serverConfig, clientConfig);
filterChainBuilder.add(sslFilter);
//|Add StringFilter, which will be responsible for Buffer <-> String transformation
filterChainBuilder.add(new StringFilter(Charset.forName("UTF-8")));
//|Add Filter, which will send a greeting message and check the result
filterChainBuilder.add(new SendMessageFilter(sslFilter));
//|Create TCP transport
final TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build();
//|Set filterchain as a Transport Processor
transport.setProcessor(filterChainBuilder.build());
try{
//|Start the transport
transport.start();
//|Perform async. connect to the server
transport.connect(SSLEchoServer.HOST, SSLEchoServer.PORT);
System.out.println("Press any key to stop the client...");
System.in.read();
}finally{
System.out.println("Stopping transport...");
//|Stop the transport
transport.stop();
System.out.println("Stopped transport...");
}
}
private static class SendMessageFilter extends BaseFilter{
private final SSLFilter sslFilter;
public SendMessageFilter(SSLFilter sslFilter){
this.sslFilter = sslFilter;
}
#Override
#SuppressWarnings("unchecked")
public NextAction handleConnect(FilterChainContext ctx) throws IOException{
final Connection connection = ctx.getConnection();
//|Execute async SSL handshake
sslFilter.handshake(connection, new EmptyCompletionHandler<SSLEngine>(){
//|Once SSL handshake will be completed - send greeting message
#Override
public void completed(SSLEngine result){
//|Here we send String directly
connection.write(MESSAGE);
}
});
return ctx.getInvokeAction();
}
#Override
public NextAction handleRead(FilterChainContext ctx) throws IOException{
//|The received message is String
final String message = (String) ctx.getMessage();
//|Check the message
if(MESSAGE.equals(message)){
System.out.println("Got echo message: \"" + message + "\"");
}else{
System.out.println("Got unexpected echo message: \"" + message + "\"");
}
return ctx.getStopAction();
}
}
private static SSLEngineConfigurator initializeSSL(){
//|Initialize SSLContext configuration
SSLContextConfigurator sslContextConfig = new SSLContextConfigurator();
//|Set key store
ClassLoader cl = SSLEchoClient.class.getClassLoader();
URL cacertsUrl = cl.getResource("ssltest-cacerts.jks");
if(cacertsUrl != null){
sslContextConfig.setTrustStoreFile(cacertsUrl.getFile());
sslContextConfig.setTrustStorePass("changeit");
}
//|Set trust store
URL keystoreUrl = cl.getResource("ssltest-keystore.jks");
if(keystoreUrl != null){
sslContextConfig.setKeyStoreFile(keystoreUrl.getFile());
sslContextConfig.setKeyStorePass("changeit");
}
//|Create SSLEngine configurator
return new SSLEngineConfigurator(sslContextConfig.createSSLContext(), false, false, false);
}
}
When executing:
Run SSLEchoServer:
Press any key to stop the server...
Run SSLEchoClient:
Press any key to stop the client...
Question:
What is this code supposed to accomplish or demonstrate? Beyond the console output you see above, this code does nothing on my end.
In reviewing the code, my expectation was that the client was supposed start its TCP transport and connect it to the server. In the process of that connection being made, the SendMessageFilter previously added to the filter stream will execute its handleConnect() method, which I confirmed does execute. But, this code never executes the connection.write(MESSAGE) statement.
It's clear the intention here is to execute the write() method after the handshake thread completes, but it doesn't appear to do so, and in examining the handshake() method in SSLFilter class in grizzly-framework-2.2.19, I was also unable to determine where the overridden parent completed() method is even defined.
Can anyone lend some insight to whether this disconnect is due to my lack of understanding something here or if it is potentially a bug in the sample implementation provided by Grizzly? I believe clearing this up will go a long way to further my understanding here. Thank you in advance!
Related
I am trying to establish a connection with twitter client and getting the following exception:
This exception appears while establishing the base connection whereas zookeepers and Kafka server are running.
Exception in thread "main" java.lang.IllegalStateException: There is already a connection thread running for Hosebird-Client-01, endpoint: /1.1/statuses/filter.json?delimited=length&stall_warnings=true
at com.twitter.hbc.httpclient.BasicClient.connect(BasicClient.java:92)
at com.github.simpleProject.kafka.simpleProject.twitter.TwitterProducer.run(TwitterProducer.java:37)
at com.github.simpleProject.kafka.simpleProject.twitter.TwitterProducer.main(TwitterProducer.java:28)
Here is my code
public class TwitterProducer {
Logger logger = LoggerFactory.getLogger(TwitterProducer.class.getName());
String consumerKey ="sbkOd*********tMJQUpU4Iz4j";
String consumerSecret="eZZPa788***********TR6hx39MlkvWylO6rF";
String token = "758284333996277763-*************D6f5CanCsre2qPgviv";
String secret="jJRbC9cMOaacHEHEd7y6po********1VwsS5x0ZmDG";
public TwitterProducer(){}
public static void main(String[] args){
new TwitterProducer().run();
}
public void run(){
/** Set up your blocking queues: Be sure to size these properly based on expected TPS of your stream */
BlockingQueue<String> msgQueue = new LinkedBlockingQueue<String>(1000);
// create a twitter client
Client client = createTwitterClient(msgQueue);
// Attempts to establish a connection.
client.connect();
// create a kafka producer
// loops to send tweets to kafka
// on a different thread, or multiple different threads....
while (!client.isDone()) {
String msg =null;
try{
msg = msgQueue.poll(5, TimeUnit.SECONDS);
} catch (InterruptedException e){
e.printStackTrace();
client.stop();
}
if(msg!=null){
logger.info(msg);
}
logger.info("End of application");
}
}
public Client createTwitterClient(BlockingQueue<String> msgQueue){
/** Declare the host you want to connect to, the endpoint, and authentication (basic auth or oauth) */
Hosts hosebirdHosts = new HttpHosts(Constants.STREAM_HOST);
StatusesFilterEndpoint hosebirdEndpoint = new StatusesFilterEndpoint();
List<String> terms = Lists.newArrayList("bitcoin");
hosebirdEndpoint.trackTerms(terms);
// These secrets should be read from a config file
Authentication hosebirdAuth = new OAuth1(consumerKey, consumerSecret, token, secret);
ClientBuilder builder = new ClientBuilder()
.name("Hosebird-Client-01") // optional: mainly for the log
.hosts(hosebirdHosts)
.authentication(hosebirdAuth)
.endpoint(hosebirdEndpoint)
.processor(new StringDelimitedProcessor(msgQueue));
Client hosebirdClient = builder.build();
// Attempts to establish a connection.
hosebirdClient.connect();
return hosebirdClient;
}
}
I have implemented the XMPP server as described in the google api.
The main function that was written is sending a downstream message. I used while(true) loop to keep the server running.
I was wondering what is the best practice for keeping the server app awake and process messages.
public static void main(String[] args) throws Exception {
final long senderId = ***; // your GCM sender id
final String password = "***";
SmackCcsClient ccsClient = new SmackCcsClient();
ccsClient.connect(senderId, password);
while(true){}
}
I am seeking insights into this strange problem we are having with a Java software application. The application is downloaded from a web site and communicates
with a server on the internet using a JMS/JBOSS in a publish/subscribe model. At a high level, the problem is that on many of our Windows 7 PCs (64-Bit Win7 OS with JRE 1.7.0_51-b13 32 bit), the client application does not receive the messages sent from the server. The onMessage() method appears to not get invoked.
The frustrating bit is that on some of our PCs (which were deployed using Ghost hard drive image so theoretically should have identical configurations), the application does receive the messages - We can see onMessage() method is working as expected.
I am able to examine the TCP/IP traffic coming in to the PC and I can see the messages arriving from the server to the client's TCP/IP stack. But somehow there is something keeping the messages from triggering the Java onMessage handler.
Another really strange twist is that if we leave the client application running for maybe 20 minutes, suddenly it starts to receive messages (that is the onMessage() method gets triggered). Again we know it is getting messages all along from looking at the TCP/IP traffic.
The basic outline of the code we are using is shown below. I think it pretty much follows the example here1 and has most of the similar elements. Any suggestions for further debugging or exploration would be appreciated.
public class MyPubSub {
private static final String CONN_FACTORY_QUEUE = "jms/RemoteConnectionFactory";
private static final String QUEUE_A = "jms/queue/QueueA";
private static final String CONN_FACTORY_TOPIC = "jms/RemoteConnectionFactory";
private static final String USERNAME = "xyz";
private static final String PWD = "xyz123";
public static void main(String[] args)
{
String hostURL = "some_host_string_thing_here";
String remotingURL = "remote://"+hostURL+":4447";
// Establish context
Context ctx;
QueueConnectionFactory qcf = null;
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
p.put(Context.PROVIDER_URL, remotingURL);
p.put(Context.SECURITY_PRINCIPAL, USERNAME);
p.put(Context.SECURITY_CREDENTIALS, PWD);
ctx = new InitialContext(p);
// Set up Queue
QueueConnectionFactory qcf = null;
QueueConnection qconn = null;
QueueSession qsession = null;
Queue queueA = null;
QueueReceiver qrecv = null;
qcf = (QueueConnectionFactory)ctx.lookup(CONN_FACTORY_QUEUE);
qconn = qcf.createQueueConnection(USERNAME, PWD);
qsession = qconn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
messageProducer = qsession.createProducer(queueA);
// Set up Topic
TopicConnectionFactory tcf;
TopicConnection connA = null;
TopicSession sessionA = null;
Topic topicA = null;
TopicSubscriber recvA;
tcf = (TopicConnectionFactory)ctx.lookup(CONN_FACTORY_TOPIC);
topicA = (Topic)ctx.lookup(TOPICA);
connA = tcf.createTopicConnection(USERNAME, PWD);
connA.setExceptionListener(new ExceptionListenerImpl());
sessionA = connA.createTopicSession(false, TopicSession.AUTO_ACKNOWLEDGE);
messageProducerA = sessionA.createProducer(getJmsDestination(TOPICA));
recvA = sessionA.createSubscriber(topicA);
// Associate the MessageListener ExListenerA()
recvA.setMessageListener(new ExListenerA());
// Start
connA.start();
}
public class ExListenerA implements MessageListener {
public void onMessage(Message msg) {
TextMessage oo = (TextMessage) msg;
System.out.println("Got message" + oo.getText());
}
}
}
After setting the message listener the connection is not started. That could have caused the problem.
I am trying to listen for new messages using the POP3 protocol. I am aware that Pop3 doesn't allow new messages to appear in the Inbox while the folder is open. Below is the code that I have implemented:
import javax.mail.event.MessageCountAdapter;
import javax.mail.event.MessageCountEvent;
public class EmailListener extends MessageCountAdapter {
public EmailListener() {
}
public void messagesAdded(MessageCountEvent e) {
System.out.println("I");
}
public void messagesRemoved(MessageCountEvent e) {
System.out.println("J");
}
}
public class POPReceiver {
public POPReceiver() {
}
public void listen() throws Exception {
Properties properties = new Properties();
Session session = null;
POP3Store pop3Store = null;
String host = "NB-EX101.example.com";
String user = "user2";
properties.put(mail.pop3.host, host);
session = Session.getDefaultInstance(properties);
pop3Store = (POP3Store) session.getStore("pop3");
pop3Store.connect(user, "password");
Folder folder = pop3Store.getFolder("INBOX");
folder.addMessageCountListener(new EmailListener());
sendEmail();
}
public void sendEmail() {
// not added code, but the email sends
}
}
public static void main(String[] args) throws Exception {
POPReceiver i = new POPReceiver();
i.listen();
}
I am using Microsoft Exchange Server. Any ideas why it is not listening?
I have looked on http://www.coderanch.com/t/597347/java/java/Email-Listener but still does not listen.
From Javamail FAQ (http://www.oracle.com/technetwork/java/javamail/faq/index.html):
Q: I set up a MessageCountListener (as demonstrated in the monitor program) but I'm never notified of new mail in my POP3 INBOX.
A: The POP3 protocol does not allow the client to see new messages delivered to the INBOX while the INBOX is open. The application must close the INBOX and reopen it in order to see any new messages. You will never be notified of new mail using the MessageCountListener interface with POP3. See the com.sun.mail.pop3 package documentation for more information.
So, MessageCountListener will not work for POP3. You'll need to implement polling to get information about new messages for POP3.
However, you can try using IMAP instead.
But even in the case of IMAP you should be using this in another way. See idle() method in IMAPStore class (e.g. being called in a loop in a separate thread etc - see https://javamail.java.net/nonav/docs/api/com/sun/mail/imap/IMAPStore.html#idle() ).
I successfully managed to send the message to queue name ReceiverQueue on my localhost Jboss server, how can I retrieve message I sent to it or how do I check if there is any messages in the queue if any retrieve them. or can I get an explanation of some sort what is the best way to do this. Thank you
A working send/receive tutorial would be accept as well. Anything that will get me to just send to the queue and receive message from that queue will get accepted answer.
I'm using Spring.
I want a solution that does it using application context with bean injection ..
Standard JMS API steps:
1. Create a javax.naming.Context with the access details of the server
context = new InitialContext(environment)
2. Look up javax.jms.QueueConnectionFactory in the context. Factory name is specific to the JMS server
factory = (QueueConnectionFactory)context.lookup(factoryName)
3. Create a javax.jms.QueueConnection
connection = factory.createQueueConnection(...)
4. Create a javax.jms.QueueSession
session = connection.createQueueSession(...)
5. Look up your javax.jms.Queue in the context
queue = (Queue) context.lookup(qJndiName)
Till now it is the same as sending....
6. Create a javax.jms.QueueReceiver with the session
receiver = session.createReceiver(queue)
7. JMS API provides 2 ways to retrieve a message:
7.a Wait for a message with one of the receiver.receive() methods
7.b Implement javax.jms.MessageListener in your class and register it as the listener
receiver.setMessageListener(this)
JMS API will call your onMessage() method whenever a new message arrives
8. Don't forget to start the listener:
connection.start()
9. Close the context (very important, when you access multiple JMS servers from the same program):
context.close()
The above is a typical solution from a stand-alone application. In EJB environment you should use message driven beans. You can find ino on them on http://java.sun.com/javaee/6/docs/tutorial/doc/gipko.html and a tutorial on http://schuchert.wikispaces.com/EJB3+Tutorial+5+-+Message+Driven+Beans
Here is the working example you've asked for:
import java.util.Hashtable;
import javax.naming.*;
import javax.jms.*;
public class JMSJNDISample implements MessageListener {
public static final String JNDI_URL = "jnp://localhost:1099";
public static final String JNDI_CONTEXT_FACTORY = "org.jnp.interfaces.NamingContextFactory";
public static final String JMS_USER = null;
public static final String JMS_PASSWORD = null;
public static final String JMS_CONNECTION_FACTORY = "MyConnectionFactory";
public static final String QUEUE_JNDI_NAME = "ReceiverQueue";
QueueConnection qConn = null;
QueueSession qSession = null;
QueueSender qSender = null;
QueueReceiver qReceiver = null;
public JMSJNDISample () {
}
public void init() throws JMSException, NamingException {
// Set up JNDI Context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_CONTEXT_FACTORY);
env.put(Context.PROVIDER_URL, JNDI_URL);
if (JMS_USER != null)
env.put(Context.SECURITY_PRINCIPAL, JMS_USER);
if (JMS_PASSWORD != null)
env.put(Context.SECURITY_CREDENTIALS, JMS_PASSWORD);
Context jndiContext = new InitialContext(env);
// Lookup queue connection factory
QueueConnectionFactory cFactory = (QueueConnectionFactory)jndiContext.lookup(JMS_CONNECTION_FACTORY);
// Create Connection
if (JMS_USER == null || JMS_PASSWORD == null)
qConn = cFactory.createQueueConnection();
else {
qConn = cFactory.createQueueConnection(JMS_USER, JMS_PASSWORD);
}
// Create Session
qSession = qConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
// Lookup Queue
Queue queue = (Queue) jndiContext.lookup(QUEUE_JNDI_NAME);
// Create Queue Sender
qSender = qSession.createSender(queue);
// Create Queue Receiver
qReceiver = qSession.createReceiver(queue);
qReceiver.setMessageListener(this);
// Start receiving messages
qConn.start();
// Close JNDI context
jndiContext.close();
}
public void sendMessage (String str) throws JMSException {
TextMessage msg = qSession.createTextMessage(str);
qSender.send(msg);
}
public void onMessage (Message message) {
try {
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage)message;
System.out.println("Text Message Received: "+textMessage.getText());
} else {
System.out.println(message.getJMSType()+" Message Received");
}
} catch (JMSException je) {
je.printStackTrace();
}
}
public void destroy() throws JMSException {
if (qSender != null) qSender.close();
if (qReceiver != null) qReceiver.close();
if (qSession != null) qSession.close();
if (qConn != null) qConn.close();
}
public static void main(String args[]) {
try {
JMSJNDISample sample = new JMSJNDISample();
// Initialize connetion
sample.init();
// Send Message
sample.sendMessage("Hello World");
// Wait 2 sec for answer
Thread.sleep(2000);
// Disconnect
sample.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Other than having a MessageDrivenBean listening to that queue?
EDIT:
You are using spring just to create the payload, right? JMS is a JavaEE spec. You don't need to use Spring for actually sending/receiving messages. You don't have to manually check whether there are messages in the queue etc., either. All you need to do is have an MDB(MessageDrivenBean) set up like this,
#MessageDriven(activationConfig = {
#ActivationConfigProperty(
propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(
propertyName = "destination", propertyValue = "queue/myqueue")
})
public class MyMessageDrivenBean implements MessageListener {
public void onMessage(Message message) {
ObjectMessage objMsg = (ObjectMessage) message;
Payload payload = (Payload)objMsg.getObject();
//do stuff
}
}
And then send some JMS messages.
#Stateless
public class QueuerBean implements QueuerLocal {
#Resource(mappedName = "java:/JmsXA")
private ConnectionFactory jmsConnectionFactory;
#Resource(mappedName = "queue/myqueue")
private Queue queue;
private void queue(MyPayload payload) {
try {
Connection connect = jmsConnectionFactory.createConnection();
Session session = connect.createSession(false,
Session.DUPS_OK_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(queue);
// create a JMS message and send it
ObjectMessage objMsg = session.createObjectMessage(payload);
producer.send(objMsg);
producer.close();
session.close();
connect.close();
} catch (JMSException e) {
log.error("Bad thing happened", e);
}
}
}
The queue is configured by the annotation. When a message is sent, JBoss will automatically trigger the MDB.
Here's an example showing how to set up a message-driven POJO in Spring. I'd recommend following this idiom if you're already using Spring.
As for the part about seeing how many messages are on the queue, I'd say you should be using the admin console for JBOSS, not your code.
I would recommend also using a tool like HermesJMS (http://www.hermesjms.com/confluence/display/HJMS/Home) to inspect the queue manager and queues. It's a great debugging tool.