I have a class annotated with #Path and in this class I have a method that handles a PUT request. Within this method I am using ActiveMQ to publish a message to a JMS topic every time this method is invoked. Everything works fine.
But now I want to add some clean up code (mainly, just closing the ActiveMQ connection). How can I do this?
#PUT
#Consumes(MediaType.TEXT_PLAIN)
public void putString(String myString) throws JMSException {
if (txtmessage != null && producer != null ){
txtmessage.clearBody();
txtmessage.setText(myString);
producer.send(txtmessage);
}
}
all the initialization is done in a static block.
So I want the connection to be up as long as the server is listening but I want to explicitly close it when the server goes down. Is there a way jersey lets you handle on close events?
Implement the
ServletContextListener: http://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/ServletContextListener.html
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.log4j.Logger;
public class MyContextListener implements ServletContextListener {
public final static String ACTIVE_MQ_SESSION = "ActiveMQSession";
public final static String ACTIVE_MQ_PRODUCER = "ActiveMQProducer";
Logger logger = Logger.getLogger(this.getClass());
private static final int ackMode = Session.AUTO_ACKNOWLEDGE;
private static final boolean transacted = false;
private static final String brokerUrl = "vm://localhost:61616";
private Connection connection;
private Session session;
private MessageProducer producer;
#Override
public void contextDestroyed(ServletContextEvent sce) {
try {
this.producer.close();
this.session.close();
this.connection.close();
} catch (JMSException e) {
logger.warn("tearDown()", e);
}
}
#Override
public void contextInitialized(ServletContextEvent sce) {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
brokerUrl);
try {
connection = connectionFactory.createConnection();
connection.start();
session = connection.createSession(transacted, ackMode);
Destination destination = session.createQueue("queue");
producer = session.createProducer(destination);
ServletContext sc = sce.getServletContext();
sc.setAttribute(ACTIVE_MQ_SESSION, session);
sc.setAttribute(ACTIVE_MQ_PRODUCER, producer);
} catch (JMSException e) {
logger.warn("setup() failed to setup connection brokerUrl="
+ brokerUrl);
}
}
}
Register the listener in web.xml:
<web-app...>
<listener>
<listener-class>package.MyContextListener</listener-class>
</listener>
</web-app>
and then the servlet (from where you use the producer and session):
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.servlet.http.HttpServlet;
import javax.ws.rs.Consumes;
import javax.ws.rs.PUT;
import javax.ws.rs.core.MediaType;
public class MessageServlet extends HttpServlet {
#PUT
#Consumes(MediaType.TEXT_PLAIN)
public void putString(String myString) throws JMSException {
MessageProducer producer = (MessageProducer) getServletContext()
.getAttribute(MyContextListener.ACTIVE_MQ_PRODUCER);
Session session = (Session) getServletContext().getAttribute(
MyContextListener.ACTIVE_MQ_SESSION);
TextMessage txtmessage = session.createTextMessage();
if (txtmessage != null && producer != null) {
txtmessage.clearBody();
txtmessage.setText(myString);
producer.send(txtmessage);
}
}
}
Related
I have requirement to pass HTTPs calls of some specific URL via proxy and rest direct. I have written my own custom proxy implementation using ProxySelector of java.net. It is working fine for HTTP calls ( I can see in proxy access logs in that case) but in case of HTTPS calls it seems it is not using proxy).Am I missing something here.? Proxy server is configured properly and its access log is updating when some HTTPS calls passed from browser with proxy.
package com.blabla.proxy;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.vuclip.pubsub.logging.PubSubUtil;
import com.vuclip.pubsub.logging.client.GooglePubSubClient;
public class CustomProxySelector extends ProxySelector {
private static final Logger LOGGER = LogManager.getLogger(PubSubUtil.class);
private final ProxySelector def;
private final String PUB_SUB_URL = "pubsub.googleapis.com";
List<Proxy> proxyList = new ArrayList<Proxy>();
private Proxy proxy=null;
public CustomProxySelector(ProxySelector aDefault) {
this.def = aDefault;
}
#Override
public void connectFailed(URI arg0, SocketAddress soc, IOException ex) {
LOGGER.error("Error in connecting to proxcy "+soc +" for pubsub :"+ ex);
}
#Override
public List<Proxy> select(URI uri) {
if ("https".equalsIgnoreCase(uri.getScheme()) && uri.getHost().startsWith(PUB_SUB_URL)
&& GooglePubSubClient.isProxyEnabled()) {
synchronized (this) {
if (proxy == null) {
proxy = new Proxy(Proxy.Type.SOCKS,
new InetSocketAddress(GooglePubSubClient.getProxyHost(), GooglePubSubClient.getProxyPort()));
}
}
proxyList.add(proxy);
LOGGER.debug("ProxyList:" + proxyList);
return proxyList;
}
proxyList = def.select(uri);
LOGGER.debug("Default proxy list : " + proxyList);
return proxyList;
}
}
I changed Proxy.Type.SOCKS to Proxy.Type.HTTP and it worked for me.
I am using Akka websockets to push data to some client.
This is what I have done so far:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.http.javadsl.ConnectHttp;
import akka.http.javadsl.Http;
import akka.http.javadsl.ServerBinding;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.model.ws.Message;
import akka.http.javadsl.model.ws.WebSocket;
import akka.japi.Function;
import akka.stream.ActorMaterializer;
import akka.stream.Materializer;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Sink;
import akka.stream.javadsl.Source;
public class Server {
public static HttpResponse handleRequest(HttpRequest request) {
System.out.println("Handling request to " + request.getUri());
if (request.getUri().path().equals("/greeter")) {
final Flow<Message, Message, NotUsed> greeterFlow = greeterHello();
return WebSocket.handleWebSocketRequestWith(request, greeterFlow);
} else {
return HttpResponse.create().withStatus(404);
}
}
public static void main(String[] args) throws Exception {
ActorSystem system = ActorSystem.create();
try {
final Materializer materializer = ActorMaterializer.create(system);
final Function<HttpRequest, HttpResponse> handler = request -> handleRequest(request);
CompletionStage<ServerBinding> serverBindingFuture = Http.get(system).bindAndHandleSync(handler,
ConnectHttp.toHost("localhost", 8080), materializer);
// will throw if binding fails
serverBindingFuture.toCompletableFuture().get(1, TimeUnit.SECONDS);
System.out.println("Press ENTER to stop.");
new BufferedReader(new InputStreamReader(System.in)).readLine();
} finally {
system.terminate();
}
}
public static Flow<Message, Message, NotUsed> greeterHello() {
return Flow.fromSinkAndSource(Sink.ignore(),
Source.single(new akka.http.scaladsl.model.ws.TextMessage.Strict("Hello!")));
}
}
At the client side, I am successfully receiving a 'Hello!' message.
However, now I want to send data dynamically (preferably from an Actor), something like this:
import akka.actor.ActorRef;
import akka.actor.UntypedActor;
public class PushActor extends UntypedActor {
#Override
public void onReceive(Object message) {
if (message instanceof String) {
String statusChangeMessage = (String) message;
// How to push this message to a socket ??
} else {
System.out.println(String.format("'%s':\nReceived unknown message '%s'!", selfActorPath, message));
}
}
}
I am unable to find any example regarding this online.
The following is the software stack being used:
Java 1.8
akka-http 10.0.10
One - not necessarily very elegant - way of doing this is to use Source.actorRef and send the materialized actor somewhere (maybe a router actor?) depending on your requirements.
public static Flow<Message, Message, NotUsed> greeterHello() {
return Flow.fromSinkAndSourceMat(Sink.ignore(),
Source.actorRef(100, OverflowStrategy.fail()),
Keep.right()).mapMaterializedValue( /* send your actorRef to a router? */);
}
Whoever receives the actorRefs of the connected clients must be responsible for routing messages to them.
I'm working on an Web Application in which multiple users work on the same data (source is sql database)
I'm using
Netbeans 8.0.2
Tomcat 8.0.28
Maven 4.0.0
jquery-2.1.4
I want the server to push a message to all clients which have opened a WebSocket Connection to my server.
I found a lot of guides/tutorials on how to implement WebSockets but they all rely on the Client pushing something to the Server.
I just need the server to push a message to the Client.
Can any1 provide a short example on how to to this??
It just needs to be:
Client opens SocketConnection
JavaClass establishes connection
JavaClass method sends message/data to client
EDIT:
My setup right now:
On application startup I do the following:
startup.java
package com.mycompany.ssp;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import javax.servlet.ServletContextEvent;
public class Startup implements javax.servlet.ServletContextListener {
private static WebSocketServer socket_server = null;
// create singleton object Socket
getSocket();
public static WebSocketServer getSocket(){
if(socket_server == null) {
socket_server = new WebSocketServer();
}
return socket_server;
}
}
WebSocketServer.java
package com.mycompany.ssp;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
#ServerEndpoint(value = "/socket")
public class WebSocketServer {
private static final Logger LOGGER = Logger.getLogger(WebSocketServer.class.getName());
private List<Session> session_list = new ArrayList<Session>();
WebSocketServer socket_server = Startup.getSocket();
public WebSocketServer() {
}
#OnOpen
public void onOpen(Session session) {
LOGGER.log(Level.INFO, "New connection with client: {0}",
session.getId());
socket_server.session_list.add(session);
}
#OnMessage
public String onMessage(String message, Session session) {
LOGGER.log(Level.INFO, "New message from Client [{0}]: {1}",
new Object[] {session.getId(), message});
return "Server received [" + message + "]";
}
#OnClose
public void onClose(Session session) {
LOGGER.log(Level.INFO, "Close connection for client: {0}",
session.getId());
socket_server.session_list.remove(session);
}
#OnError
public void onError(Throwable exception, Session session) {
LOGGER.log(Level.INFO, "Error for client: {0}", session.getId());
}
public void send(String message) throws IOException{
for(Session session: socket_server.session_list){
session.getBasicRemote().sendText(message);
}
}
}
I get an Error when trying to start my application.
Why does it happen?
Well, the Method getSocket() loops multiple times and everytime after
socket_server = new WebSocketServer(); the variable socket_server is still null, which should be initialized though.
Netbeans Apache TomcatEE Log:
SEVERE [http-nio-8080-exec-1050] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class com.mycompany.ssp.Startup
java.lang.StackOverflowError
Does any1 have an idea why this is happening??
var websocket=new websocket(websocket_url);
Java Code
#ServerEndpoint(value = "/websocket/one")
public class WebsocketEndPoint {
public static List clients=new ArrayList();
#OnOpen
public void OnOpen(Session session, EndpointConfig config)
throws IOException {
//Save the endpoints session that opened the connection in List
}
#OnMessage
public void OnMessage(Session session, String message) {
}
#OnClose
public void OnClose(Session session, CloseReason reason) {
//remove from list
}
#OnError
public void OnError(Session session, Throwable throwable) {
}
}
}
3.
class Sender{
public void send(String message){
for(Session session:WebsocketEndPoint.clients){
session.getBasicRemote().sendText(message);
}
}
}
Hope this helps
And in Javascript u can use onMessage to get the message
I created a session bean with this code:
package ejb2;
import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
#Stateless(name = "TestEJB", mappedName = "EJB2-Project1-TestEJB")
public class TestEJBBean implements TestEJB, TestEJBLocal {
#Resource
SessionContext sessionContext;
public TestEJBBean() {
}
public String getHello(String who_welcome) {
return "Hello " + who_welcome;
}
}
As you can see, it's almost a default code (except getHello method). Besides this bean I have a client:
package ejb2;
import java.util.Hashtable;
import javax.naming.CommunicationException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class TestEJBClient {
public static void main(String[] args) {
try {
final Context context = getInitialContext();
TestEJB testEJB = (TestEJB) context.lookup("EJB2-Project1-TestEJB#ejb2.TestEJB");
System.out.println(testEJB.getHello("Student"));
} catch (CommunicationException ex) {
System.out.println(ex.getClass().getName());
System.out.println(ex.getRootCause().getLocalizedMessage());
System.out.println("\n*** A CommunicationException was raised. This typically\n*** occurs when the target WebLogic server is not running.\n");
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static Context getInitialContext() throws NamingException {
Hashtable env = new Hashtable();
// WebLogic Server 10.x/12.x connection details
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL, "t3://localhost:7101");
return new InitialContext(env);
}
}
First time it worked like a charm. But then I created another bean:
package ejb2;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.SessionContext;
import javax.naming.Context;
import javax.naming.InitialContext;
#Stateless(name = "ClientEJB", mappedName = "EJB2-Project1-ClientEJB")
public class ClientEJBBean implements ClientEJB, ClientEJBLocal {
#Resource
SessionContext sessionContext;
TestEJB testEJB;
public ClientEJBBean() {
try {
final Context context = new InitialContext();
testEJB = (TestEJB) context.lookup("EJB2-Project1-TestEJB#ejb2.TestEJB");
} catch (Exception ex) {
ex.printStackTrace();
}
}
public String getHelloFromBean(String who) {
return testEJB.getHello(who);
}
}
And now beans aren't working. I get an error like this:
weblogic.application.ModuleException: Unable to bind Business Interface to the JNDI name: EJB2Project1WebApp_warClientEJB_Home, throw exception javax.naming.NameAlreadyBoundException: [EJB:011224]Unable to bind the interface ejb2.ClientEJB to ClientEJB. Another EJB has already bound an interface to that name.; remaining name 'EJB2-Project1-ClientEJB#ejb2'. NestedException Message is :[EJB:011224]Unable to bind the interface ejb2.ClientEJB to ClientEJB. Another EJB has already bound an interface to that name.
What's the problem with these codes?
As far as i can see you try to deploy two stateless EJBs with the same JNDI name
Try to undeploy the current application , check the JNDI tree from Admin Console
and make sure the tree does not have the JNDI name you see as duplicate.
I need to make simple Message Driven Bean that will listen on dynamically added queue locataions. I have tried few ways to implement this, but none of them worked. I have appplication that uses esb and java message queues, and I'm trying to read queue location from config file, during the runtime, and thus tell my message driven bean what is the queue on which to listen. I am not either sure that this is possible.
I also tried to implement message listener, but because I have to use ejb module, and ejb module does not support main method, it requires his own container (like message driven bean), I don't know what to use instead of main method to achive the same goal. I am not able to use session beans because I need to achieve asynchronous communication between client and service.
I also tried to use client application (although it is not one of the options), but maven project does not support debug and run functions for this type of application in netbeans.
Does anyone know any solution for this problem, or at least have some idea?
This may not be the best solution, but it is possible to receive and process JMS messages asynchronously with a Stateful Session Bean doing something like this:
package com.example.statefuljms;
import javax.annotation.Resource;
import javax.ejb.Local;
import javax.ejb.Stateful;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
#Stateful
#Local(MessageReceiverLocal.class)
public class MessageReceiver implements MessageReceiverLocal, MessageListener {
#Resource(mappedName = "ConnectionFactory")
private ConnectionFactory connectionFactory;
private QueueConnection connection;
#Override
public void start(String queueName) throws JMSException, NamingException {
Context initialContext = new InitialContext();
connection = (QueueConnection) connectionFactory.createConnection();
QueueSession session = (QueueSession) connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Queue queue = (Queue) initialContext.lookup(queueName);
QueueReceiver receiver = session.createReceiver(queue);
receiver.setMessageListener(this);
connection.start();
}
#Remove
#Override
public void stop() throws JMSException {
connection.stop();
connection.close();
}
#Override
public void onMessage(Message message) {
// handle message here
}
}
Use a Singleton to test:
package com.example.statefuljms;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.jms.JMSException;
import javax.naming.NamingException;
#Startup
#Singleton
public class Test {
#EJB
private MessageReceiverLocal messageReceiver;
#PostConstruct
public void run() {
messageReceiver.start("/queue/myQueue");
}
#PreDestroy
public void cleanup() {
messageReceiver.stop();
}
}