I am trying to implement a web socket through servlet. My app server is tomcat 7.
I could find examples, where WebSocketServlet class is used. But this class is deprecated and removed in tomcat 8.
I see another alternative, which is to annotate the class with the following
#ServerEndpoint(value = "/websocket/test")
I need helpin understanding,
How will I use this annotation in servlets? Are servlets irrelevent in case of web sockets?
If I create a normal class with the above annotation, and other annotation like onOpen,onClose etc, should I need to put the entry for
that class in web.xml? Or are web.xmls are irrelevant too?
Any hello world link will also be very helpful.
Thank you.
============Edited====================
I have tried the chat example found in this link
http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/
But when I try to invoke the socket through javascript, the events are not reaching my server at all....
Finally I figured this out. So I am answering here for others to refer.
1)How will I use this annotation in servlets? Are servlets irrelevent in case of web sockets?
Apparently yes, we don't need servlets for web sockets.
2)If I create a normal class with the above annotation, and other annotation like onOpen,onClose etc, should I need to put the entry for that class in web.xml? Or are web.xmls are irrelevant too?
No entry needed in web.xml either.
Following, is a sample server side code.
#ServerEndpoint(value = "/echo")
public class Echo {
#OnOpen
public void start(Session session) {
//TODO
}
#OnClose
public void end() {
//TODO
}
#OnMessage
public void incoming(String message) {
//TODO
}
#OnError
public void onError(Throwable t) throws Throwable {
//TODO
}
}
For client, either you can use Javascript is you have a HTML5 compatible browser.
Else you write java clients using the tyrus library. Refer here
Related
Question : Is it possible to send data from server to client in spring ,using websocket, without creating another client , in the java app that sustains the server ?
Almost every article on the internet about websocket in spring, shows how to define your methods in the controller for handling requests . All the magic seem to happen when they define a function with the 2 annotations #MessageMapping("/news") , #SendTo("/topic/news") . By having this method alone , as far as I know, you can only catch requests and send them further ( SendTo) . I want to know if it is possible to send data from server to client without having a client requesting something in the first place. And how that code would look like.
you could use SimpMessagingTemplate .
i think you should have this class somewhere
#Configuration
#EnableWebSocketMessageBroker
public class "yournameclass" extends AbstractWebSocketMessageBrokerConfigurer
then this method inside
#Override
public void configureMessageBroker(MessageBrokerRegistry configuration) {
configuration.enableSimpleBroker("/test");
configuration.setApplicationDestinationPrefixes("/someprefix");
}
then you could call this from some method in your code
#Autowired
private SimpMessagingTemplate template;
public void "mymethodsender" ()
{ this.template.convertAndSend("/test/somepathwhereyouregisteredyourclienttoreceivemessages", "messageobject");
}
Problem
Very short: I want to create Spring Shell, but as a web application.
I want to create a web-application (preferably using Spring Boot), where the frontend (ReactJS) looks like a terminal (or shell), and the backend processes inputted commands. Look at https://codepen.io/AndrewBarfield/pen/qEqWMq. I want to build a full web app for something that looks like that.
I want to build a framework, so that I can develop backend commands without knowing anything about the frontend/web application structure. I basically want to instantiate a "Terminal" object, where I give some kind of input-stream and output-stream. This way I can program this Terminal based on my given interfaces and structure, without the need of setting up all kind of front-end stuff.
A good summary of the question would be: how to send all keyboard inputs to the backend, and how to send all output to the frontend?
The reason I want to create a web application, is because I want it to be available online.
What I tried
I think the way of reaching this is using websockets. I have created a small web application using this (https://developer.okta.com/blog/2018/09/25/spring-webflux-websockets-react) tutorial, without the security part. The websocket part is almost suitable, I just cannot get an "input" and "output" stream-like object.
#Controller
public class WebSocketController {
private SimpMessagingTemplate simpMessagingTemplate;
#Autowired
public WebSocketController(SimpMessagingTemplate simpMessagingTemplate) {
this.simpMessagingTemplate = simpMessagingTemplate;
}
#MessageMapping("/queue")
#SendToUser("/topic/greetings")
public Greeting greeting(HelloMessage message, #Header(name = "simpSessionId") String sessionId) throws Exception {
System.out.println(sessionId);
// Do some command parsing or whatever.
String output = "You inputted:" + HtmlUtils.htmlEscape(message.getName());
return new Greeting(output);
}
private MessageHeaders createHeaders(String sessionId) {
SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
headerAccessor.setSessionId(sessionId);
return headerAccessor.getMessageHeaders();
}
Now with this code, you can parse a command. However, it doesn't keep any "state". I don't know how it works with states and websockets.
I saw you had this Spring Sessions + WebSockets (https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot-websocket.html), but this is not really what I want.
I can send a message from the backend to the frontend by using this code:
simpMessagingTemplate.convertAndSendToUser(sessionId, "/topic/greetings", "hey", createHeaders(sessionId));
However, I want my terminal to be able to wait for input commands from the user. Seems like a stretch, but does anybody know how to achieve this?
What I sort of want
I basically want other people to program to this interface:
public interface ITerminal {
void setInputStream(Object someKindOfWrapperForTheInput);
void setOutputStream(Object someWrapperOfSimpMessagingTemplate);
void start();
}
When somebody opens the web application, they get a dedicated terminal object (so a single connection per user). Whever somebody enters a command in the frontend application, I want it to be received by the terminal object, processed, and response outputted to the frontend.
Reasons for doing this
I really like creating command-line applications, and I don't like building frontend stuff. I work as a software engineer for a company where we build a web application, where I mostly program backend stuff. All the frontend part is done by other people (lucky for me!). However, I like doing some projects at home, and this seemed cool.
If you have any thoughts or ideas on how to approach this, just give an answer! I am interested in the solution, using the SpringBoot framework is not a requirement. I ask this question using Spring Boot and ReactJS, because I have already built applications with that. A lot has been figured out already, and I think this probably exists as well.
The only requirement is that I can achieve this with Java on a tomcat-server. The rest is optional :)
Unclear?
I tried my best to make my story clear, but I am not sure if my purpose of what I want to achieve is clear. However, I don't know how to formulate it in such a way you understand. If you have any suggestions or questions, dont hesitate to comment!
If the only thing you want is a Live Spring shell that shows up in the browser it's fairly simple, all you need is to expose a standard WebSocket via the WebSocketConfigurer, then add a WebSocketHandler that executes the command and then returns the resulting String as a TextMessage.
Firstly the Socket configuration that allows clients to connect to the 'cli' endpoint
#Configuration
#EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer {
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(cliHandler(), "/cli").setAllowedOrigins("*");
}
#Bean
public CLIWebSocketHandler cliHandler() {
return new CLIWebSocketHandler();
}
}
Then the WebSocketHandler that executes the command. I recommend that for every #ShellMethod you specify the return type as String, don't use logging or System writes as they won't be returned during the evaluation.
#Component
public class CLIWebSocketHandler extends TextWebSocketHandler {
#Autowired
private Shell shell;
#Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String result = shell.evaluate(() -> message.getPayload()).toString();
session.sendMessage(new TextMessage(result));
}
}
You can use an extension like Simple WebSocket Client to test it, by going to ws://localhost:port/cli
This is the most basic solution, adding features like security should be easy after this. Notice that I don't use STOMP, because you probably want to isolate users. But it can work alongside STOMP based endpoints, so you can have pub-sub functionality for other parts of the project.
From the question I sense that answer you'd like is something that involved Input and OutputStreams. You could possibly look into redirecting the output of Spring Shell to a different stream then have them forwarded to the sessions but it's probably much more complicated and has other trade-offs. It's simpler to just return a String as the result, it looks better in print outs anyway.
I am new to servlets. I have a query processor java program and now, I want to use it in a Web Application. I have an interface(HTML) which generates the query and I want to run the program on a button click in the interface. For this, I want to convert the java program into a java servlet. I am working in Net Beans.
Following is the structure of my Java program :
public class ABC
{
//code
public ABC() //constructor
{
//code
}
public static void main(String[] args)
{
//code
}
}
I want to convert this into a servlet. Following is the structure of a default servlet in Net Beans.
public class Demo extends Httpservlet
{
/*----
----
----
----*/
public void processRequest(HttpServletRequest request, Httpservlet response)
throws ServletException,IOException
{
/*code*/
}
/*HttpServlet methods - doGet(), doSet() etc.*/
}
Is there any alternative for the main function in the servlet? Which method is executed first when the sevlet starts running? Can I run the Java Program on a button click on a HTML page so that I can eliminate the use of servlet?
use get or post method in servlet depend on your action. There are doGet , doPost and so many HTTP methods you need to determine in which you write code
To use your query processor on the web you will have to build a Java Web Application.
Try the tutorial below and then call your ABC class from a Servlet.
Introduction to Developing Web Applications
Create a Dynamic web project, add new servlet usee doGet method or doPost method refer this link for the same.
servlet example
Hope this helps.
Please have in mind that the purpose of use is different in those two cases. While the main method of a class is invoked when you compile and run it as part of an application (run on a machine), the doGet and doPost methods are invoked in a servlet after a GET/POST request is made by client side to the server side, on which the Servlet lives.
On the first case, usually everything occurs on a specified machine, following the logic "do something, then done", and on the second case, you have a Request/Response Model between Clients and a Server (following the logic "do something when asked, then wait for being asked again"). You need to have a Server (e.g. Tomcat) set up to use the servlets.
I think this is more a design specific question, than direct coding issue.
I want to implement a websocket service which serves an updated dataset from a foreign http:// resource to the clients.
but i want to have the data available before the first client connects, so #OnLoad notation won't do.
In HttpServlet world I would
#Override
public void init() throws...
I could not figure out a suitable way for doing so just using JSR-356.
I tried with custom ServerEndpointConfig.Configurator but that does not seem to give me access to method similar to init() from HttpServlet.
So my question is:
Letting the websocket Endpoint class extend HttpServlet gives me access to the init() method and I can place my initial logic there.
Is that a suitable way for solving my problem, or have i missed something in JSR-356 which does the job elegantly and without importing mostly unused servlet packages?
Thank you very much!
A class annotated with #ServerEndpoint("/myEndPoint") is instantiated each time a new connection is created via #OnOpen. It is not a static class nor a singleton (e.g. not behaves as Spring #Service).
I have a similar problem to yours, I need to make a web socket the observer of a Spring web service (don't ask, I'm with you that is a bad architecture the problem). In order to make it an observer, I have to add it to the observable class, but because of the lack of an initialization for the web socket I don't have a clear spot where to add the observer, adding it in the #OnOpen method would repeatedly add it on each new connection.
The only solution I found is a workaround. Usually a web socket class has a static Set of the peers connected to it, you need something similar for your initialization. Either use a static block or a static flag in the constructor. In my case I solved with:
private static boolean observerFlag = false;
private static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());
public MyWebSocket() {
if (!observerFlag) {
observable.addObserver(this);
observerFlag = true;
}
}
And to remove the observer:
#OnClose
public void onClose(Session peer) {
peers.remove(peer);
if (peers.isEmpty()) {
observable.deleteObserver(this);
observerFlag = false;
}
}
I repeat that this is a workaround, I think that there is a more elegant solution.
The question might seem stupid/trivial and might be, but I simply cannot understand how to achieve my goal. (Sorry if the title is misguiding, couldn't think of a better one)
I have a webpage on a App Engine server which uses GWT. I got client code and server code. The client code can call RPC methods without any problem (my problem has nothing to do with the "gwt-client" at all).
I got the following classes:
//MyClassService.java - client package
#RemoteServiceRelativePath("myService")
public interface MyClassService extends RemoteService{
public doSomething();
}
//MyClassServiceAsync.java - client package
public interface MyClassServiceAsync{
public void doSomething(AsyncCallback<Void> callback);
}
//MyClassServiceImpl.java - server package
public class MyClassServiceImpl extends RemoteServiceServlet implements MyClassService{
#Override
public void doSomething()
{
//does something
}
}
A scenario and what I want to do:
I've got a remote client, in other words, a client who's not connecting through the page via the "GWT-interface", it's a client who's simply making GET, POST requests to a path on the server (from elsewhere). This remote client is not "using" GWT at all. The client is connecting through an HttpServlet, inside this servlet I want to reuse the RPC mechanics so that i don't have to rewrite the interfaces, who are on the client side and using client-dependent code (the implementation is already server-side).
To reuse the existing methods on the server-side I could create an instance of MyClassServiceImpl.java and just use those. BUT as you can see above, they are implemented as synchronous methods, since GWT-RPC automatically makes the calls asyncronous when using the GWT-RPC.
How would i go about to reuse the MyClassServiceImpl on the server-side and also get them as asynchronous?
Also if I'm wrong with the approach I'm taking, please suggest some other solution. For example, one solution might be for the remote client to directly communicate with the RemoteServiceServlet instead of creating a HttpServlet which the client connects through, but I don't know if that's possible (and if it is, please tell me how)!
Thank you!
EDIT (thanks to some answers below I got some insight and will try to improve my question):
The server-side implementation of the methods is SYNCHRONOUS. Meaning they will block until results a returned. When invoking these method from the gwt-client code, they are 'automatically' made ASYNCHRONOUS one can call them by doing the following:
MyClassServiceAsync = (MyClassServiceAsync) GWT.create(MyClassService.class);
ServiceDefTarget serviceDef = (ServiceDefTarget) service;
serviceDef.setServiceEntryPoint(GWT.getModuleBaseURL() + "myService");
service.doSomething(new AsyncCallback<Void>() {
#Override
public void onSuccess(Void result) {
//do something when we know server has finished doing stuff
}
#Override
public void onFailure(Throwable caught) {
}
});
As you can see from the above code, there is support for the doSomething method to take an AsyncCallback, without even having the implementation for it. This is what I wanted on the server-side so i didn't have to use threads or create a new implementation for "async-usage". Sorry if I was unclear!
1) Any client can call MyClassServiceImpl.doSomething() with the current configuration. MyClassServiceImpl is a servlet and properly exposed. In order to achieve communication this way, the client must be able to "speak" the GWT dialect for data transportation. Google may provide you with libraries implementing this. I haven't used any, so I cannot make suggestions.
An example, proof-of-concept setup: Check the network communications with Firebug to get an idea of what is going on. Then try calling the service with curl.
2) If you do not want to use the GWT dialect, you can easily expose the same service as REST (JSON) or web services (SOAP). There are plenty of libraries, e.g. for the REST case RestEasy and Jersey. You do not mention any server-side frameworks (Spring? Guice? CDI?), so the example will be simplistic.
I'd suggest implementing your business method in a class independent of transportation method:
public class MyBusinessLogic {
public void doSomething() {
...
}
}
Then, the transport implementations use this business logic class, adding only transport-specific stuff (e.g. annotations):
GWT:
public class MyClassServiceImpl extends RemoteServiceServlet implements MyClassService{
#Override
public void doSomething() {
MyBusinessLogic bean = ... // get it from IoC, new, whatever
bean.doSomething();
}
}
JAX-RS:
#Path("myService")
public class MyResource {
#GET
public void doSomething() {
MyBusinessLogic bean = ... // get it from IoC, new, whatever
bean.doSomething();
}
}
So the transport endpoints are just shells for the real functionality, implemented in one place, the class MyBusinessLogic.
Is this a real example? Your method takes no arguments and returns no data.
Anyhow you can create a new servlet and invoke it via normal HTTP request. The servlet then just invokes the target method:
public class MyNewServlet extends HttpServlet{
protected void doGet(HttpServletRequest request, HttpServletResponse response){
MyBusinessLogic bean = ... // get it from IoC, new, whatever
bean.doSomething();
}
}