Format to send and receive data using wss (websocket) - java

I am working on Websocket currently. So do I send and receive data using wss protocol? I am already using HTTP post and get but need to upgrade to wss. Please help. Thanks in advance

if you are using standalone applications (console app) I recommend you to use java-websocket or if it's a JavaEE WebApp, Example:
package org.hectorvent.gpstracking.websocket;
import org.hectorvent.gpstracking.restful.model.PdaGeoData;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Singleton;
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;
#Singleton
#ServerEndpoint("/geodata")
public class WebSocketGmap {
private final Set<Session> clients = new HashSet();
#OnOpen
public void open(Session session) {
clients.add(session);
}
#OnMessage
public void onMessage(String message, Session session) {
// here you're going to received client messages.
}
#OnClose
public void close(Session session) {
clients.remove(session);
}
#OnError
public void onError(Throwable error) {
}
public void sendMessage(PdaGeoData pgd) {
for (Session client : clients) {
Future fu = client.getAsyncRemote()
.sendText(GsonUtils.toJson(pgd));
}
}
}

Related

How should I persist a PanacheEntity with data coming from a Websocket message?

I'm trying to persist the following entity when receiving a message from the client via Websocket:
import javax.persistence.Column;
import javax.persistence.Entity;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
#Entity
public class Penguin extends PanacheEntity{
#Column(name="penguin_name")
public String name;
}
The following persist works, when receiving a POST request:
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.transaction.Transactional;
import com.penguins.demo.pojos.Penguin;
#Path("/api")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class PenguinResource {
#GET
public List<Penguin> getPenguins(){
return Penguin.listAll();
}
#POST
#Transactional
public Response addPenguin(Penguin penguin){
penguin.persist();
return Response.ok(penguin).status(201).build();
}
}
However, the following code freezes when it reaches the persist line. The message.getPenguin() method is returning an actual Penguin reference (the MessageDecoder.class is doing it's part):
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import com.penguins.demo.pojos.Message;
import com.penguins.demo.pojos.Penguin;
#ServerEndpoint(value = "/waddle/{user}", decoders = MessageDecoder.class, encoders = MessageEncoder.class)
public class PenguinHub {
#OnMessage
#Transactional
public void onMessage(Session session, Message message) throws IOException {
// Handle new messages
message.setFrom(users.get(session.getId()));
// it freezes on persist :(
message.getPenguin().persist();
broadcast(message);
}
}
I'm new to Panache/Hibernate, any help would be apreciated, thank you.
It worked like this:
#Inject
ManagedExecutor managedExecutor;
#Inject
TransactionManager transactionManager;
#OnMessage
public void onMessage(Session session, Message message) throws IOException {
message.setFrom(users.get(session.getId()));
managedExecutor.submit(() -> {
try{
transactionManager.begin();
parseMessage(message); // persist the entity here
transactionManager.commit();
}catch(Exception e){
e.printStackTrace();
}
});
}

Need help implementing WebSocket in java

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

Subject no longer authenticated in session after logging in with Shiro

I am using Guice + Jersey + Shiro to login via a REST API and then use the same HTTP session under which I logged in to and have my permissions work for that resource.
Below is my code.
Firstly, my servlet configuration:-
public class ServletConfiguration extends GuiceServletContextListener
{
private ServletContext mServletContext;
#Override
public void contextInitialized(ServletContextEvent inEvent)
{
mServletContext = inEvent.getServletContext();
super.contextInitialized(inEvent);
}
#Override
protected Injector getInjector()
{
mServletContext.addListener(new au.com.tt.agora.configuration.CbiCleanupHttpSessionListener());
return Guice.createInjector(new JerseyServletModule() {
#Override
protected void configureServlets()
{
install(new TTShiroWebModule(mServletContext));
install(new ShiroAopModule());
filter("/*").through(GuiceShiroFilter.class);
bind(ShiroLoginResource.class);
bind(ShiroResource.class);
filter("/*").through(GuiceContainer.class);
}
});
}
}
Now, this is my test realm:-
package au.com.tt.agora.configuration.shiro;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
public class TestRealm extends AuthorizingRealm
{
#Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken inToken) throws AuthenticationException
{
UsernamePasswordToken upToken = (UsernamePasswordToken) inToken;
if (upToken.getUsername().equals("Kamal") || upToken.getUsername().equals("NotKamal"))
return new SimpleAuthenticationInfo(upToken.getUsername(), upToken.getPassword(), getName());
return null;
}
#Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection inPrincipals)
{
String username = (String) inPrincipals.fromRealm(getName()).iterator().next();
SimpleAuthorizationInfo authzInfo = new SimpleAuthorizationInfo();
if (username.equals("Kamal"))
{
authzInfo.addStringPermission("PRODMA:READ:AU");
authzInfo.addStringPermission("PRODMA:WRITE:KB");
authzInfo.addStringPermission("SUPPMA:READ:KB");
}
else
{
authzInfo.addStringPermission("PRODMA:READ:AU");
authzInfo.addStringPermission("PRODMA:WRITE:KB");
}
return authzInfo;
}
}
This is the web module
package au.com.tt.agora.configuration.shiro;
import javax.servlet.ServletContext;
import org.apache.shiro.guice.web.ShiroWebModule;
public class TTShiroWebModule extends ShiroWebModule
{
public TTShiroWebModule(ServletContext inServletContext)
{
super(inServletContext);
}
#SuppressWarnings("unchecked")
#Override
protected void configureShiroWeb()
{
bindRealm().to(TestRealm.class);
addFilterChain("**/shiroResource/*", ANON);
}
}
Here is the resource I use to login:-
package au.com.tt.agora.configuration.jaxrs.resources;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import com.google.inject.Inject;
import au.com.tt.agora.configuration.option.ClientProvider;
import au.com.tt.agora.configuration.option.ConfigurationProvider;
import au.com.tt.agora.login.web.request.LoginRequest;
import au.com.tt.agora.login.web.request.LoginResponse;
import au.com.tt.agora.login.web.service.LoginHandler;
import au.com.tt.calypso.cbi.CalypsoException;
#Path("/{client}/shiroLogin")
public class ShiroLoginResource
{
private static final String ROUTING_TOKEN_HEADER = "proxy-jroute";
#POST
#Path("/standard")
#Produces(MediaType.TEXT_PLAIN)
#Consumes(MediaType.APPLICATION_JSON)
public String login(#Context HttpServletRequest inServletRequest) throws CalypsoException
{
Subject subject = SecurityUtils.getSubject();
subject.login(new UsernamePasswordToken("Kamal", "Password", false));
return getSessionIdWithRouting(inServletRequest);
}
private String getSessionIdWithRouting(HttpServletRequest inRequest)
{
String sessionId = inRequest.getSession().getId();
return(sessionId);
}
}
And here is the resource I am calling:-
package au.com.tt.agora.configuration.jaxrs.resources;
import javax.servlet.http.HttpSession;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
#Path("/{client}/shiroResource")
public class ShiroResource
{
private static final Logger LOG = LoggerFactory.getLogger(ShiroResource.class);
#Inject
public ShiroResource()
{
}
#POST
#Path("requiresProdma.do")
#Produces(MediaType.TEXT_PLAIN)
#RequiresPermissions({ "PRODMA:*:*" })
public String prodmaRequired()
{
return "Success";
}
#POST
#Path("requiresSuppma.do")
#Produces(MediaType.TEXT_PLAIN)
#RequiresPermissions({ "SUPPMA:*:*" })
public String suppmaRequired()
{
Subject subject = SecurityUtils.getSubject();
subject.getPrincipal();
return "Success";
}
}
If I put a breakpoint into suppmaRequired and call this resource, I can see that subject is not authenticated.
My understanding on how Shiro works is obviously faulty, but I don't know what I am not doing. Can anyone point me in the right direction?
Not sure if it makes a difference, but I am using URL rewriting to access the web session.
Basically, I am using the fetch API to test this. Here is an example:-
fetch("http://localhost/app/tt/shiroLogin/standard", {
method: "POST",
headers: {
"Content-Type" : "application/json"
} ,
body: '{"username":"myName","password":"myPassword"}'
})
.then(function(res) {
return res.text();
})
.then(function(sessionId) {
return fetch("http://localhost/app/tt/shiroResource/requiresSuppma.do;JSESSIONID=" + sessionId,
{
method: "POST"
});
})
.then(function(res) {
return res.text();
})
.then(function(res) {
console.log(res);
});
I am also deploying to glassfish.
OK, this was not a Shiro problem in the end. I was using two different sessions going from the ShiroLoginResource to ShiroResource.
I forgot that you actually needed to inject with a session level object in Guice to force Guice to create a session. Stupid me.
Once I injected a session scoped dependency into ShiroLoginResource and interacted with it, then everything just worked.
I will keep this question open because it gives some useful code snippets.

websocket was forcibly closed by the remote host

hi guys im trying implement an example of send file through websocket using sendBinary method . I`m deploying server code in Tomcat 8.0.20 and client code using tyrus 1.8.3 implementation/provider . There are my server and client class :
Server code :
package socket;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.websocket.CloseReason;
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("/chat")
public class Server {
#OnOpen
public void onOpen(Session session) {
}
#OnClose
public void onClose(Session session,CloseReason closeReason) {
}
#OnError
public void onError(Throwable throwable){
throwable.printStackTrace();
}
#OnMessage
public void message(String message, Session session) throws IOException {
}
#OnMessage
public void message(Session session,ByteBuffer byteBuffer) throws IOException {
System.out.println(" Binary received ... ");
}
}
Client code :
package br.com.jslsolucoes.socket.client;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.concurrent.CountDownLatch;
import javax.websocket.ClientEndpoint;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.DeploymentException;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
import org.apache.commons.io.IOUtils;
#ClientEndpoint
public class Client {
private static CountDownLatch latch;
#OnOpen
public void onOpen(Session session) throws IOException {
InputStream inputStream = getClass().getResourceAsStream(
"/myvideo.wmv");
byte[] buffer = new byte[8 * 1024];
while (IOUtils.read(inputStream, buffer) != 0) {
session.getBasicRemote().sendBinary(ByteBuffer.wrap(buffer));
}
}
#OnClose
public void onClose(Session session,CloseReason closeReason) throws IOException {
latch.countDown();
}
#OnMessage
public void processMessage(String message) {
}
#OnError
public void onError(Throwable throwable){
throwable.printStackTrace();
}
public static void main(String[] args) throws DeploymentException,
IOException, InterruptedException {
latch = new CountDownLatch(1);
WebSocketContainer container = ContainerProvider
.getWebSocketContainer();
String uri = "ws://localhost:8081/socket/chat";
Client client = new Client();
container.connectToServer(client, URI.create(uri));
latch.await();
}
}
its works ok but while uploading after a time about 30 seconds an exception is launched :
java.io.ioexception : an existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:197)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:379)
at org.apache.tomcat.util.net.NioChannel.read(NioChannel.java:140)
at org.apache.coyote.http11.upgrade.NioServletInputStream.fillReadBuffer(NioServletInputStream.java:136)
at org.apache.coyote.http11.upgrade.NioServletInputStream.doRead(NioServletInputStream.java:80)
at org.apache.coyote.http11.upgrade.AbstractServletInputStream.read(AbstractServletInputStream.java:124)
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:51)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:203)
at org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:198)
at org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:96)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:654)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Someone can help me with this problem ?

How to do websockets in embedded undertow?

According to this: http://undertow.io/ it supports websockets. There is no documentation on how to do so, though. I just want a simple embedded undertow handling web sockets example.
I don't want to grab the whole jboss app server.
Take a look at undertow examples
chat:
https://github.com/undertow-io/undertow/tree/master/examples/src/main/java/io/undertow/examples/chat
and websockets example
https://github.com/undertow-io/undertow/tree/master/examples/src/main/java/io/undertow/examples/websockets
this will help you.
I'm came up with this class. However, I am not an JBoss expert. I'm especially uncertain about the xnio stuff.
import io.undertow.Undertow;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
import org.jboss.logging.Logger;
import org.xnio.OptionMap;
import org.xnio.Xnio;
import org.xnio.XnioWorker;
import javax.servlet.ServletException;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import static io.undertow.servlet.Servlets.defaultContainer;
import static io.undertow.servlet.Servlets.deployment;
import static io.undertow.websockets.jsr.WebSocketDeploymentInfo.ATTRIBUTE_NAME;
public class WebsocketServer {
private static final Logger LOGGER = Logger.getLogger(WebsocketServer.class);
#ServerEndpoint("/")
public static class SocketProxy {
#OnOpen
public void onOpen() {
LOGGER.info("onOpen");
}
#OnClose
public void onClose() {
LOGGER.info("onClose");
}
#OnMessage
public void onMessage(String message) {
LOGGER.info("onMessage:" + message);
}
}
public static void main(String[] args) throws ServletException, IOException {
final Xnio xnio = Xnio.getInstance("nio", Undertow.class.getClassLoader());
final XnioWorker xnioWorker = xnio.createWorker(OptionMap.builder().getMap());
final WebSocketDeploymentInfo webSockets = new WebSocketDeploymentInfo()
.addEndpoint(SocketProxy.class)
.setWorker(xnioWorker);
final DeploymentManager deployment = defaultContainer()
.addDeployment(deployment()
.setClassLoader(WebsocketServer.class.getClassLoader())
.setContextPath("/")
.setDeploymentName("embedded-websockets")
.addServletContextAttribute(ATTRIBUTE_NAME, webSockets));
deployment.deploy();
Undertow.builder().
addListener(8080, "localhost")
.setHandler(deployment.start())
.build()
.start();
}
}

Categories

Resources