smack connection using servlets - java

Here I am connecting to facebook using smack and servlets ,I can able to send and receive chat messages.
But here connection object is instance variable(not thread-safe),so all the users are getting same connection object.
If we declare XMPPConnection object inside doGet() method we have to take connection every time
when the user send chat message.
provide some solution for my problem.
public class Home_page_action extends HttpServlet implements MessageListener{
public XMPPConnection connection;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if(connection!=null)
{connection.connect("uname","password");}
else{
//send message code to target user
}
}
}

Make some class to maintain pool of your connection and every time you have to just call getInstance of that class..

Related

Are there any possibilities to call some code after the Spring-WS endpoint operation result sending to the client has been finished?

We have the situation in the Spring-WS we want to perform some specific action after the sending of the data produced by the Spring-Ws-Endpoint has been finished and sent to the client.
Of course even better would be if we could call some code after the data are received by the client calling the request to our WS...
Are there any possibilities to, for example, register somewhere some callback, which would be called after the TCP connection realizing the WS-transport has been successfully closed? Of course, here could be the problem if the connections are kept alive over multiple SOAP requests, no idea it this can happen and how to prevent/evaluate it... Or any other way having similar effect we can be reasonably sure, the data have successfully arrived to the client (or at least have been sent back by the server completely)
Or, is there, at least some possibility to replace the standard spring ws http servlet connection implementation
org.springframework.ws.transport.http.HttpServletConnection
by some our own implementation? Then we could override the onClose() method...
Finally, we used following solution:
There has been implemented the custom http connection
public class MyHttpServletConnection extends HttpServletConnection {
/**
* Constructs a new servlet connection with the given {#code HttpServletRequest} and {#code HttpServletResponse}.
*
* #param httpServletRequest
* #param httpServletResponse
*/
protected MyHttpServletConnection(
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) {
super(httpServletRequest, httpServletResponse);
}
#Override
protected void onSendAfterWrite(WebServiceMessage aMessage) throws IOException {
super.onSendAfterWrite(aMessage);
// some specific code for notification about the send data event
}
#Override
public void onClose() throws IOException {
super.onClose();
// some specific code for notification about the close connection event
}
and then the default WebServiceMessageReceiverHandlerAdapter has been redefined in the following way:
public class MyMessageReceiverHandlerAdapter extends WebServiceMessageReceiverHandlerAdapter {
#Override
public void afterPropertiesSet() {
DefaultStrategiesHelper defaultStrategiesHelper = new DefaultStrategiesHelper(MessageDispatcherServlet.class);
WebServiceMessageFactory factory = defaultStrategiesHelper
.getDefaultStrategy(WebServiceMessageFactory.class);
setMessageFactory(factory);
}
#Override
public ModelAndView handle(
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object handler) throws Exception {
if (HttpTransportConstants.METHOD_POST.equals(httpServletRequest.getMethod())) {
WebServiceConnection connection = new MyHttpServletConnection(httpServletRequest, httpServletResponse);
try {
handleConnection(connection, (WebServiceMessageReceiver) handler);
}
catch (InvalidXmlException ex) {
handleInvalidXmlException(httpServletRequest, httpServletResponse, handler, ex);
}
}
else {
handleNonPostMethod(httpServletRequest, httpServletResponse, handler);
}
return null;
}
}
and finally, the spring bean definitions have been extended to use MyMessageReceiverHandlerAdapter in this way:
<bean name="messageReceiverHandlerAdapter" class="somepackage.MyMessageReceiverHandlerAdapter" />
<bean name="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory" />
Now the own connection is used and the notifications about the data departure or connection close is performed correctly.

WebSocket closed before HttpSessionListener.sessionDestroyed is called

I am implementing a Spring Boot + WebSocket + SockJS application and have a doubt about how to handle the HTTP session/ Websocket relation.
Basically I would like to be able to inform the user that his session has been invalidated (because of a timeout or because of having logged in from another location). For that I wanted to put in his own socket a certain message just before the framework closes it.
I turned to an http listener but the problem I have is that by the time HttpSessionListener.sessionDestroyed() is called I can see the socket has been already closed by the framework (not due to some other event like the user closing the browser).
Has anybody any idea about how to achieve this?
I have a really simple Websocket config and am running with Spring Boot defaults.
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setMessageSizeLimit(10000000);
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app/");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/myEndPoint").withSockJS();
}
}
Security part:
#Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
#Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
applySecurity(messages);
}
#Override
protected boolean sameOriginDisabled() {
return true;
}
private static void applySecurity(MessageSecurityMetadataSourceRegistry messages) {
messages.nullDestMatcher().authenticated() //
.simpDestMatchers("/app/**").authenticated().simpSubscribeDestMatchers("/user/reply").authenticated()
.simpTypeMatchers(MESSAGE, SUBSCRIBE).denyAll().anyMessage().denyAll();
}
}
My Http listener would be like this:
return new HttpSessionListener() {
#Override
public void sessionDestroyed(HttpSessionEvent se) {
simpMessagingTemplate.convertAndSendToUser(....);
}
#Override
public void sessionCreated(HttpSessionEvent se) {
// no need to do anything when a session is created
}
};
UPDATE:
Spring-session handles issues like this one and many others.
HttpSession and Websocket session are two different kind of sessions. HttpSession is created when client accesses the url and completes Handshake whereas Websocket session is created when client sends subscribe request.
Websocket session is wrapped under HttpSession. If HttpSession gets timed out or invalidated then underlying Websocket session also gets disconnected, however, vice versa is not true.
Coming to your point of configuring listener for Websocket session, HttpSession listener won't be able to listen for Websocket session events. For such events, we need to define a class which extends org.springframework.web.socket.messaging.SubProtocolWebSocketHandler class and override afterConnectionEstablished and afterConnectionClosed methods. Have a look at Javadoc here.
Also, here is an example that listens for Spring websocket disconnect events. You need to configure something similar to this.
An HTTP session is supposed to survive the connection. That's what it's for. Multiple connections, same session. The session should not expire while there are active connections.

Jetty: Find out which connector was used for incoming Request

When handling a Jetty response I want to know on which port the request originated on?
public static void main(String[] args) {
Server server = new Server();
server.setConnectors(new Connector[] {connectorUnsecure, connectorSecure});
ServletContextHandler handler = new ServletContextHandler();
handler.setContextPath("/");
handler.addServlet(MyServlet.class, "/*");
server.setHandler(handler);
server.start();
server.join();
}
public abstract class MyServlet extends HttpServlet {
#Override
protected final void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Find out on which connector port the request came from.
// (The request.getRequestURL() does not contain the port at all times.)
}
}
When using a custom Handler, I could use something like:
public class CustomHandler extends AbstractHandler {
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// baseRequest.getConnection().getConnector().getPort()
}
}
However, I don't want to use a custom handler.
Is it possible to obtain the connector and its port when using a plain HttpServlet?
Thanks!
There's 5 methods on javax.servlet.http.HttpServletRequest that might be of use for you.
.getLocalAddr() - the server address the request is being processed on (could be IPv4 or IPv6)
.getLocalPort() - the server port the request is being processed on
.getRemoteAddr() - the client address the request is being processed on (could be IPv4 or IPv6)
.getRemotePort() - the client port the request is being processed on
.getHeader("Host") - the requested HTTP Host (and port) that the client thinks its talking to. (part of the HTTP spec, and especially useful for virtual hosts)
Note: the HTTP Request Host header can also be obtained via the .getRequestURI() method.
String serverAddr = URI.create(request.getRequestURI()).getHost();

deploy servlet on simple java server

I have been playing around with java servers and servlets. However one question still remains.
Lets say I write a server like this:
class server {
public static void main(String[] args){
int port = 8080;
try{
ServerSocket ss = new ServerSocket(port);
Socket s = ss.accept();
}catch(Exception e){
System.out.println("Something went wrong");
}
}
}
this will listen for httprequest on port 8080.
Now lets say I have a servlet that looks like this:
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<HTML>");
out.println("<HEAD><TITLE>Hello World</TITLE></HEAD>");
out.println("<BODY>");
out.println("<BIG>Hello World</BIG>");
out.println("</BODY></HTML>");
}
}
I can easily use an already existing server like tomcat or glassfish to deploy this servlet. But is it possible to deploy this from the simple server here above?
No, you need a Servlet implementation or if you want to re-invent the wheel create your own. For instance Catalina is the Tomcat servlet implementation.
No. You need java implementation that handle servlet's code and return html. Basically glassfish or tomcat is a server which listens to your request, run java code at back end and return result. On superficial level, tomcat and glassfish use basic server to capture requests. However there are a lot more things to do.
In your simple server, there is nothing to handle java code written in servlet.
Your server will return text of servelet instead of running it.
not a easy way.
servlet need a java container implementation,like tomcat or glassfish。 if you think tomcat or glassfish is too heavy, can try jetty.
public class HelloHandler extends AbstractHandler
{
public void handle(String target,Request baseRequest,
HttpServletRequest request,HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/html;charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
response.getWriter().println("<h1>Hello World</h1>");
}
}
public static void main(String[] args) throws Exception
{
Server server = new Server(8080);
server.setHandler(new HelloHandler());
server.start();
server.join();
}
you also can write a simple Servlet implementation by netty.

Servlets and synchronization

Servlets runs in several threads, so my question is:
If I have a lot of servlets which call some utility class (DbUtils, for example
Connection c = DbUtils.getConnection();
//....some action with db here
should I assume additional actions for synchronization inside DbUtils?
Actually I'd like to inherit HttpServlet into something like DatabaseInvokerServlet:
public abstract class DatabaseInvokerServlet extends HttpServlet
with methods:
public abstract void getResultSets(Connection connection) throws SQLException;
private AbstractUser currentUser;
private HttpServletRequest request;
private HttpServletResponse response;
protected void processData() {}
protected void afterRequestProcessed() throws ServletException, IOException {}
protected void beforeRequestProcessed() throws ServletException, IOException {}
protected void execute() {
Connection c = null;
try {
c = DbUtils.getConnection();
getResultSets(c);
processData();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (c != null) {
c.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public HttpServletRequest getRequest() {
return request;
}
public HttpServletResponse getResponse() {
return response;
}
public AbstractUser getCurrentUser() {
return currentUser;
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
this.request = request;
this.response = response;
this.currentUser = (AbstractUser) request.getSession().getAttribute("currentUser");
}
Then I'd just inherit my DatabaseInvokerServlet to new servlets to do custom stuff. The reason is not to copy-paste database invoke block with try-catch-finally in a lot of places.
But as I can see such approach won't work because of synchronization issues. Am I right?
If the DbUtils creates the connection in the same thread, like as:
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
Then it's threadsafe.
But if the connection is a class variable, like as:
private static Connection connection = DriverManager.getConnection(url, username, password);
public static Connection getConnection() throws SQLException {
return connection;
}
Then it is definitely not threadsafe because the same connection will be shared among all threads. Also when it's closed in a thread, all subsequent threads won't be able to use the connection because it's not open anymore. Also when it's never closed, the DB will timeout the connection sooner or later, usually after a few hours, and your application won't work anymore because the connection is not open anymore.
As to the servlet,
public abstract class DatabaseInvokerServlet extends HttpServlet {
private AbstractUser currentUser;
private HttpServletRequest request;
private HttpServletResponse response;
// ...
}
it's definitely not threadsafe. You're assigning the current user, request and response as instance variables. From each servlet class, there is only one instance during the application's lifetime. This instance is shared among all visitors/sessions throughout the entire application's lifetime. Each HTTP request operates in a separate thread and uses the same instance.
Imagine two simultaneous visitors: visitor A will set the current user, request and response. The DB process however takes a long time. Before the response of visitor A has returned, visitor B calls the same servlet and thus the current user, request and response will be overriden. Then, the query of visitor A finishes and wants to write to the response, it is instead writing to the response of visitor B! Visitor B sees the result of the query of visitor A and visitor A sees nothing on his screen!
You should never assign request/session-specific data as instance variable of the servlet. You should keep them method (thread) local.
public abstract class DatabaseInvokerServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
AbstractUser currentUser = request.getSession().getAttribute("user");
// Keep the variables in the method block!
// Do not assign them as instance variable!
}
}
As to the complete picture, this approach is clumsy. The database access layer should have nothing to do with servlets. It should operate in its own standalone classes which you could just construct/invoke in every other Java class, any servlet class, or a normal application with main(), or whatever. You should not have any single line of java.sql.* imports in your servlet classes (expect of maybe SQLException if it is not abstracted away). You should not have any single line of javax.servlet.* imports in your database classes.
See also:
Servlet instantiation and (session) variables
Basic DAO tutorial
If the utility class has state (example: class or instance variables) most probably yes.
If I guess right the DBUtils is returning new instance for each call of getConnection(). And as the DBUtils class is a utility class so it shouldn't be maintaining any state. In this scenario no you dont need any addition efforts for synchronization.
Servlets runs in several threads.
The J2EE spec says there is only one instance per servlet class running in one web container for non single thread servlet.
Servlet 2.3 specs
A servlet container may send
concurrent requests through the
service method of the servlet. To
handle the requests the developer of
the servlet must make adequate
provisions for concurrent processing
with multiple threads in the service
method.
Synchronisation in servlet.
Never have an member variable in a servlet, it is not thread safe.

Categories

Resources