Weblogic Websocket endpoint not working - java

I'm trying to crete a simple Websocket application based on tutorial here: http://docs.oracle.com/javaee/7/tutorial/doc/websocket004.htm
So the code looks something like this:
#ServerEndpoint("/echo")
public class EchoEndpoint {
#OnMessage
public void onMessage(Session session, String msg) {
try {
session.getBasicRemote().sendText(msg);
} catch (IOException e) { ... }
}
}
I'm running Weblogic 12c. I thought the annotation should be automatically picked up and websocket endpoint created on the address localhost:8888/myApp/echo, but when I try to connect there with this js test: http://www.websocket.org/echo.html, nothing happens. Also when I attach debugger, I see that the EchoEndpoint class was not loaded. What else should I do to make it running? I see nothing else in the Oracle tutorial

The Tyrus library requires a JEE7 container, Weblogic only supports JEE6.
Follow this tutorial to get websockets in Weblogic.
http://docs.oracle.com/middleware/1212/wls/WLPRG/websockets.htm

Related

How to customize HTTP response for WebSocket upgrade request in Spring?

I have a WebSocket endpoint configured like this in my WebSocketConfigurer implementation
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new ExceptionWebSocketHandlerDecorator(myWebSocketHandler), "/ws/")
.setAllowedOrigins("*")
.addInterceptors(myHandshakeInterceptor);
}
There are some checks in myWebSocketHandler#beforeHandshake and I would like to send an error message to the user in case the server decides to refuse to upgrade the connection. I've tried this
response.setStatusCode(HttpStatus.BAD_GATEWAY);
try {
response.getBody().write("Error".getBytes());
response.getBody().flush();
} catch (IOException e) {
log.error("Error writing response", e);
}
return false;
The status code works, but the body is empty. How can I send it?
EDIT: turns out the problem was that I used Firefox console to check for the response and it didn't show me anything. If I use cURL to make the same request then everything works fine and I see the message I write to the response body!
To update response body you need to write your custom RequestUpateStrategy.
As from spring official documentation from AbstractHandshakeHandler it says that:
The actual upgrade is delegated to a server-specific RequestUpgradeStrategy, which will update the response as necessary and initialize the WebSocket.
If you are using Tomcat as servlet container you can extend TomcatRequestUpgradeStrategyclass and provider your own logic how to handle
websocket upgrade.
For each servlet container there is implementation of RequestUpgradeStrategy
documentation

Packaging embedded tomcat server

First time ever using tomcat/setting up a webapp from scratch so please be mercyful. I have created an embedded tomcat server which basically looks like this:
public class Server implements Runnable {
private Tomcat tomcat;
public Server() {
tomcat = new Tomcat();
tomcat.setPort(8080);
tomcat.addWebapp("", new File("src/webapp").getAbsolutePath());
}
#Override
public void run() {
try {
tomcat.start();
tomcat.getServer().await();
} catch (LifecycleException e) {
e.printStackTrace();
}
}
And I run it in a main that looks like this:
public static void main(String[] args) throws Exception {
Thread thread = new Thread(server);
thread.start();
Foo foo = new Foo();
(thread.isAlive()) {
foo.doStuff();
TimeUnit.HOURS.sleep(interval);
}
}
The purpose of the program is to run the http-server on one thread while the class Foo does some stuff in the backend once every so-and-so hours. Probably not the correct way to create a webapp, but it's the best I've managed.
However, now that I'm trying to package it I'm running into issues because once it is packaged (using Maven) the Server doesn't seem to be able to find the webapp-folder. After a couple hours of googling and trying out a a lot of stuff involving war:s and jar:s I've come to the conclusion that there is something about this embedded tomcat stuff that I'm not understanding.
So, my questions are:
Is the way I've implemented my webapp correct? I'm getting the feeling that it's not but I can't really confirm it.
2a. If incorrect, how does one do it correctly?
2b. If correct, how does one package it into a runnable jar/war?
This is a little bit of a non-standard way of going about it. Rather than writing all your own application logic to handle an integrated web server, would you not consider leveraging something that's already there? You can create a Java project in Spring boot which contains its own embedded web server.
There's a sample starter example here that should get you going - https://spring.io/guides/gs/serving-web-content/
I would recommend this approach rather than writing it yourself as Spring Boot is an industry standard that is widely used, proven, and tested.

wildfly have a ever running process run in the background

I'm making a html5/js game that will have online capabilities for my backend I've decided to use a wildfly server. The client will communicate with the server via web sockets.
I intended for my wildfly server to also be in charge of game logic decisions such as moving npc's. My plan was to have a #startup bean that would run a server game loop to handle this logic. The server loop would then talk to the serverEndPoint via HornetQ. My serverEndPoint and server loop look like this:
ServerEndPoint
#ServerEndpoint(value= "/game/{user-id}")
public class GameEndpoint {
#Inject
GameManager gameState;
GameWorld gameWorld;
Player p;
private Logger logger = Logger.getLogger(this.getClass().getName());
#OnOpen
public void onOpen(Session session){
//do stuff
}
#OnMessage
public void onMessage(Session session, String message){
//do stuff
}
#OnClose
public void onClose(CloseReason reason){
//do stuff
}
#OnError
public void error(Throwable t){
//do stuff
}
}
GameWorld
#Startup
#Singleton
public class GameWorld {
#Inject
GameManager gameState;
private Logger logger = Logger.getLogger(this.getClass().getName());
#PostConstruct
public void init(){
gameloop();
}
private void gameloop(){
while(true){
logger.info("This is a test!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#PreDestroy
public void terminate(){
//do stuff
}
}
the issue with this is that the server loop freezes everything as it is a infinite loop(for instance if I try and access the html web page I get a 404). obviously this could be solved if the serverLoop was on its own seperate thread but after doing some research it seems threading in jboss is very difficult as its hard to know what dependencies to inject e.t.c
Can anyone shed some light on how I can solve this issue? any help on the matter would be amazing.
What you have encountered has to do with what Java EE is and what it not is: Java EE is optimized for handling many concurrent, short-lived requests, each of which (usually) handle a single transaction. The containers do that very well, particularly with stateless beans, but also with stateful beans (cluster replication etc). As such, Java EE might be well-suited to process the requests coming from your HTML5/JS clients and feed the requests to the messaging infrastructure. Java EE is not, however, designed for long running, thread-blocking background processes like yours.
FWIW: Another issue that you have not yet encountered is, even if you could get that one fixed: Next you'll encounter the transaction timeout on your #PostConstruct method.
I think you are better of with moving the game engine out of the Java EE stack. You already mentioned you plan to use HornetQ - then why not put the game engine in a simple standalone application that receives messages from HornetQ and feeds replies back into HornetQ.
Another option might be a dedicated Java game server engine, see, e.g., this question and its accepted answer on programmers.stackoverflow.com. (Update: it seems the "RedDwarf Server" project mentioned in that answer was discontinued 3 years ago).
If you absolutely want to use the Java EE environment, I suggest you use a TimerService instead. Note, however, that this also requires that your game loop calculation is quick and guaranteed to finish until the next timeout is scheduled, otherwise the container will skip the scheduled invocation (with a "still running" message or similar).
Finally, let me mention that if I were to start a new game server today, I would definitely take a look at Akka, Node.js or similar projects that support "reactive" programming.

tomcat 8 javax.websockets doesn't work

I have tomcat 8-RC1 installed in order to use javax.websockets to write websocket based applications.
there are examples at http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/ that show exactly the structure of a websocket class so I implemented the following interface:
public interface XpoWebSocket {
#OnOpen
public void onOpen(Session session);
#OnClose
public void onClose();
#OnMessage
public void onTextMessage(String message);
public Session getSession();
}
in the line above the class deceleration I also included the following:
#ServerEndpoint(value = "/ServConnect")
public class ServConnect implements XpoWebSocket {
...
so the ServerEndPoint is to point how to access to websocket, the question is what do i need to set in web.xml ? for now the web socket is still not accessible.
I try to define ServConnect as a regular Servlet in web.xml but that doesn't work. it just time out when I try to access the ServConnect location.
what configuration am I missing to let this ServConnect websocket class work ?
The WebSocket spec says that you have to annotate the concrete class. ServConnect will be treated as a WebSocket endpoint but will not receive any events as the annotations on the interface are ignored.
I'd suggest getting your own version of the Echo example working and then expanding from there.

Getting 2 Tomcat servers comminicating with each other

I have a Java web application I’m developing for a school project. There’s a requirement to have the presentation tier (servlets/jsp) be deployed to one server and business logic be deployed to another.
I need a solution to connecting the 2 servers.
Currently I’ve researching RMI and Axis2.
I’m not able to get RMI successfully working. I’m following official tutorial and keep getting a security exception locally, and imagine that it will get worse when Tomcat is involved.
Axis2 seems like a good solution, but I will need time to ramp up on it.
My question is: there a simple way of connection 2 servers so that I can call my business layer? Maybe Tomcat has something built-in.
If RMI is the de-facto protocol and API I should use, is there any good tutorials on using RMI with Tomcat.
Servers that I’m using are both running Tomcat.
I am not sure how complicated is your data layer but you can implement REST interface on business logic server using Apache CXF, for example. That should be easier than using Axis2.
There are many many options:
Write a file from one side, read it from the other. "the other" has to have an infinite loop to monitor the folder where "one side" writes request files.
Use sockets
Use REST
RMI
If you're on Linux:
Shared memory
Pipes
Given your environment I would go with REST.
I ended up using RMI. Using this tutorial I got it working: http://sacrosanctblood.blogspot.com/2008/11/rmi-tutorial-rmi-and-tomcat.html . The key is: in the start up servlet you have to make sure that the Object that you are stubbing out is class scoped and not method scoped. Also, the Security manager code is not needed.
Here's the code for the startServer servlet that I'm using:
public class startServer extends HttpServlet
{
public static boolean isRegistered = false;
public IRemote service = new RemoteImpl();
#Override
public void init(ServletConfig config) throws ServletException
{
super.init(config);
if (!isRegistered)
{
try
{
IRemote stub = (IRemote) UnicastRemoteObject.exportObject(service, 0);
Registry registry = LocateRegistry.createRegistry(9345);
registry.rebind(IRemote.serviceName, stub);
System.out.println("Remote service bound");
isRegistered = true;
}
catch (Exception e)
{
System.err.println("Remote service exception:");
e.printStackTrace();
}
}
}
}
And here's the client code:
public String getRemoteString()
{
String result = "";
try
{
Registry registry = LocateRegistry.getRegistry(9345);
IRemote serv = (IRemote) registry.lookup(IRemote.serviceName);
result = serv.executeRemote("Test");
}
catch (Exception e)
{
System.err.println("Remoteservice exception:");
e.printStackTrace();
}
return result;
}
Currently it's running all on the same server, but I'm sure that I can get the 2 working at a later time.

Categories