Highlighted
Regular Contributor.
Regular Contributor.
1679 views

Implement a Websocket server using COBOL and Java in Visual Eclipse

Hi

I'm porting a large desktop MicroFocus  application that is currently compiled to gnts  onto the Web. I'm using Eclipse 2.2.2 on Windows 10. The app will deployed on a Windows Server 2010 or later.

The old architecture uses a sockets C program, compiled to a dll that was itself called by a compile Cobol gnt.

Here's an extract from the COBOL program that called the sockets.dll

01 W00SOC-REC PIC X(6144).
01 ws-msg PIC X(6145).

string w00soc-rec x"00" delimited by size into ws-msg
call dynamicNTStdCall "sockets" using ws-msg

 The other side of the socket connection is a Java program that paints a Gui screen using the passed information at run time.

Gnts needing to  use the sockets Cobol program pass W00SOS-REC in linkage.

As far as I can tell there is no native support for sockets on the Web, apparently for security reasons. However there is socket like protocol "Websockets" that is widely supported.

I can install and use Tomcat to deploy a Websockets service on the server side. That part seems fairy straightforward. If anyone is interested please see this link which has very good instructions:

https://examples.javacodegeeks.com/enterprise-java/tomcat/apache-tomcat-websocket-tutorial/

The Java Websockets code  reproduced below.

My question is how to create a new JVM Cobol program that can call the Java program and be callable from my native gnts.

I'm assuming it need to be compiled as managed code so that it can call the Java program. The only data mapping that is required is the COBOL string

01 W00SOC-REC PIC X(6144).

I would really appreciate it if anyone could steer me in the right direction or provide help with:

1) links or instructions to setup the Eclipse project for the managed code

2) an example program that passes and receives strings to and from Java

Please let me know if the whole concept is flawed and not possible 🙂

Thanks in advance

Elliot

 

 

 

Websockets Java code:

package server.ws;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/websocketendpoint")
public class WsServer {

@OnOpen
public void onOpen(){
System.out.println("Open Connection ...");
}

@OnClose
  public void onClose(){
  System.out.println("Close Connection ...");
}

@OnMessage
public String onMessage(String message){
  System.out.println("Message from the client: " + message);
  String echoMsg = "Echo from the server : " + message;
  return echoMsg;
}

@OnError
  public void onError(Throwable e){
  e.printStackTrace();
}

}

0 Likes
9 Replies
Highlighted
Micro Focus Expert
Micro Focus Expert

I'm afraid your application architecture is not clear to me.

Is your COBOL program running on the client side or the server side?

If it's on the client side, then the only way for a JVM program to run in a web browser is as an applet, which is not really a web application at all. It's a conventional JVM application that's downloaded from a server and uses the browser as a container for its UI. In particular, it has no access to WebSocket, which is a feature for the browser's own scripting host - that is, for use by Javascript code (roughly speaking) running in web pages.

If it's on the server side, then it shouldn't care about WebSocket at all. The WebSocket conversation will be between Javascript running in the browser and your Tomcat WebSocket server. The latter can instantiate JVM classes as servlets and invoke methods on them, but those classes for the most part don't need to know anything about the conversation with the client. They receive data from Tomcat and pass data back to it.

On the client side, there's nowhere for your "native GNTs" to run, if the client application will now be hosted in a browser ("web enabled"). Browsers don't host native code, and even if they did, you have no way to deploy the native COBOL runtime, etc, to them.

On the server side, your "native GNTs" wouldn't be calling JVM code, because the point of instantiation - where everything begins for server-side operation - is the server. Tomcat is a JVM server (a servlet container and HTTP server), not a native-code server.

So if your native-GNT code is supposed to run on the server side (and there's no way of running it on the client), the options I see are:

  1. Tomcat as WebSocket server, invoking a JVM servlet, which runs the COBOL runtime and your native GNTs using JNI (Java Native Interface). The JVM servlet might be written in Java, in JVM COBOL, or in a combination of them. But this would mean running the COBOL RTS and native code in the Tomcat process, which is not advisable and perhaps not even possible.
  2. As above, but the native code runs in a separate process, and the JVM servlet communicates with it using some IPC mechanism. Seems over-engineered, not to mention a fair bit of work, and fragile (a bunch of loosely-coupled pieces).
  3. Rewrite your native COBOL code as JVM COBOL code and run it as the servlet under Tomcat. This is the most elegant of the options which reflect your original design (assuming I understand that), and much of the rewriting may just be a matter of recompiling. You'll need new code to interact with Tomcat, though, and you'll need it to be thread-safe, and it's quite possible that it tries to do things that don't make sense in this environment (such as interact with the user).
  4. Use a native-code WebSocket server and run your COBOL application as a CGI program. I believe there's a third-party Apache WebSocket module, for example. I'm not particularly fond of this option as I don't see what advantage WebSocket is giving you here. (To be honest, I'm not a big fan of WebSocket, which was intended as a superior workaround for the issues surrounding XHR - the next option in my list - but ends up being nearly as complicated.)
  5. Have your web application use XMLHttpRequest (aka XHR, and the communications component of the AJAX design paradigm) to talk to a native HTTP server, which runs your native COBOL application as CGI. This approach is well-understood - you can find tons of tutorials and references on XHR, AJAX, JSON (which replaces the XML of AJAX with a more-sensible encoding), etc. It does mean that the same server will have to serve the client-side resources (HTML, Javascript, etc) and run your server, or you'll have to deal with cross-origin request support (CORS or JSONP).

In short, there may not be any simple approach. If I'm correct about your architecture, I'd try to assess how hard it would be to rewrite the native COBOL into a JVM COBOL servlet; that would determine whether option 3 or option 5 looked best to me.

0 Likes
Highlighted
Regular Contributor.
Regular Contributor.

Hi Michael

First of all thanks so much for taking the time to answer my questions.

To clarify the architecture, the COBOL IS running on the server side, the client browser program will be probably be written in Angular 5.

<<If it's on the server side, then it shouldn't care about WebSocket at all. The WebSocket conversation will be between Javascript running in the browser and your Tomcat WebSocket server. The latter can instantiate JVM classes as servlets and invoke methods on them, but those classes for the most part don't need to know anything about the conversation with the client. They receive data from Tomcat and pass data back to it.>>

Yes I do understand that Tomcat is responsible for handling the websocket communication with the browser client.

Here's the part of the architecture that I left out. A Windows implementation of REXECD is used to start the COBOL application on the server.

The Java client (Windows 7 or 10) starts a Socket Server and establishes a unique port number (based on the client IP address); this is passed to the server and the COBOL back-end via using REXEC . The initial COBOL program passes the client IP and port number via linkage to a child COBOL screen program.

Finally, using the passed url and port number, the screen program connects with the Socket server that is listening in the Java desktop client. The java program uses this information to paint the screen and then sends back keystroke and user information to the child COBOL screen program.

The two parts of the current architecture that need to be replaced are rexec and sockets. The goal is to not rewrite the child screen programs. In other words they should just be able to call a replacement for the current sockets COBOL stub shown in my first post.

It may be helpful to look at this diagram which shows the current architecture and also a first attempt at the rewrite using a small COBOL app that would be deployed under the MicroFocus Enterprise Server REST service

www.lucidchart.com/.../c33c2d6d-13f0-4273-80a2-dfa5b30c2458

Will it be possible to use Enterprise Server and it's REST service to start the initial COBOL and then have the screen programs use Websockets under Tomcat in the same way that we are currently using native sockets?

In other words can my COBOL business program compiled into JVM managed code call the Java Websocket service .

Will it be able to do use the client url and port number to allow it to successfully connect with the Web client? I don't know enough about Websockets to know how unique connections are setup.

Or do you think there is a better way to do all of this? It's already complicated enough and I would like to keep it as simple as possible.

Thanks
Elliot
0 Likes
Highlighted
Micro Focus Expert
Micro Focus Expert

Thanks - this has clarified the situation.

I have only limited knowledge of WebSocket - it's not a protocol I've had to use in practice. However, I don't think it can replace the communications flows of your existing architecture.

The problem is that WebSocket does not provide passive open - inbound connections - on the client (browser) side. A script running in a browser can't expose a port and accept connections on it. So you can't use a WebSocket to emulate what you're doing with sockets on the client side currently.

There are a couple of ways I can see to design around this without significantly changing the existing code.

One would be to use Tomcat (or some other server) as a bidirectional proxy. Tomcat would host a WebSocket connection for the script running in the browser, and a plain stream (TCP) socket connection for the COBOL backend program. A servlet running in Tomcat would create the listening socket for the COBOL backend and wire the two together, along these lines:

  1. Browser gets the client side resources from Tomcat using regular HTTP(S) requests. The client-side script starts running.
  2. The script opens a WebSocket connection to Tomcat.
  3. The servlet running in Tomcat creates the listening socket and sends the URL back to the script. This URL has the IP address of the Tomcat server and the port for the listening socket created by the servlet.
  4. The script makes the REST request to ES to start the COBOL run unit and passes the URL.
  5. The COBOL backend program connects to the servlet's listening port.
  6. The script reads and writes to the WebSocket; the COBOL program reads and writes to its TCP connection to the servlet.
  7. The servlet watches for data on both connections. When any is available, it copies it to the other connection. When one connection is closed by the peer, it closes the other connection, cleans up, and terminates.

Now, there are some refinements possible with this. In particular, I don't see any real need for ES in step 4 (don't mention my name to your MF Sales rep...). The COBOL program could just as easily be run as a CGI under some other server, or simply be spawned by the servlet in step 3.

The other approach I can see, which has some advantages, is to get rid of WebSocket and Tomcat (unless that's your server of choice) in the design. Run everything under a simple HTTP(S) server like this:

  1. As above, web app is bootstrapped from the HTTP server.
  2. Script makes a XHR request (which may be RESTful but it really doesn't matter) to the server. This request is handled by the mechanism of your choice - CGI, JSP, ISAPI, a custom Apache module, PHP, ... whatever it is, it runs a piece of middleware code you create.
  3. The middleware piece running on the server creates a listening socket, as in step 3 above. It spawns the COBOL run unit. Basically it does everything the servlet would do in the previous architecture.
  4. The script uses conventional RIA (Rich Internet Application) AJAX-style architecture: XHR polling for data from the server, then XHR to send its responses back.

Here you just let one piece of code running under the HTTP server do all the work of supporting the existing TCP-socket-based COBOL backend architecture.

Now, one of the major motivations for WebSocket was to avoid the XHR polling of step 4 above. However, XHR polling is well-understood and widely documented, avoids relying on WebSocket support in the browser and server, and performs just fine for many RIAs. And if your application is primarily request/response, your script probably won't have to poll the server very often - maybe once every few seconds.

All that said, the simplest architecture would be to change the existing COBOL code so it can do its UI I/O through an existing conversation rather than needing to establish a new one.

0 Likes
Highlighted
Regular Contributor.
Regular Contributor.

Hi Michael

I like the first option which seems elegant enough. We could re-use our existing and well tested Java socket-server code in the servlet. The idea of using AJAX, yet another new technology for us, is not attractive.

BTW is there any reason I should be aware of not to use MF REST; are there advantages to using another approach?

Finally, when you say "spawned by the servlet" do you mean using JNI in the java applet? Wouldn't this run into the problems you mentioned in your first post, i.e. "this would mean running the COBOL RTS and native code in the Tomcat process, which is not advisable and perhaps not even possible."

It's still early days in this project but you've been very helpful. I'm not sure how it could be arranged or if it's possible but perhaps you could collaborate with us when the project goes forward.

Thanks
Elliot
0 Likes
Highlighted
Micro Focus Expert
Micro Focus Expert

Using Enterprise Server and a REST service simply to start a COBOL program is a rather heavyweight approach, and introduces complexity you don't need, since you aren't using any significant capabilities of Enterprise Server.

By "spawned by the servlet" I meant the servlet would actually start the COBOL runtime in a new process, using something like Runtime.getRuntime.exec(...).

I don't normally work directly with customers, except in forums like this. That role would fall to someone in Customer Care - and there are people in that group who have more experience with this type of application architecture than I do, to be honest - or someone in Professional Services, if you chose to engage them. I'd be happy to continue discussing this here as you move forward, though, and if you run into problems that you raise with Customer Care, feel free to mention my name.
0 Likes
Highlighted
Regular Contributor.
Regular Contributor.

Hi Michael

I've spent a lot of time researching various WebSocket implementations. I understand that this is not your area of expertise and it's certainly not mine but it seems that it's designed to handle multiple connections to the same socket server for example "chat" applications where the same message is broadcast to multiple browsers connected to the same url or "socket endpoint". I could possibly distinguish between connections by using session cookies or maybe some other technique, but I'm wondering if there is not a simpler way of implementing the client side.

Why couldn't I just use HTTP POST and GET with encoded messages? I could use GET to receive the screen information data and POST (submit form). I would think that this would keep all messaging unique by browser window instance which is what happens normally on the Web.

I'm not sure how this would change the servlet architecture very much for the TCP socket server logic. Different TCP port numbers would need to be assigned for each open browser window etc etc.

What do you think?

Elliot
0 Likes
Highlighted
Micro Focus Expert
Micro Focus Expert

You can just use HTTP POST and GET. That's the last approach I described in my previous message. XHR (XmlHttpRequest) is the API that a Javascript script uses to make an HTTP POST or GET request.

You can also use a Javascript framework such as JQuery, React, or Angular rather than making XHR calls directly.

The main disadvantage of using HTTP rather than WebSocket is that your script will have to periodically check for new data from the server (if the server ever sends unsolicited data). That's the polling aspect I mentioned in my previous message. But as I said, that's a well-understood requirement, and you can find a lot of books, tutorials, and other resources showing how to handle it.
0 Likes
Highlighted
Regular Contributor.
Regular Contributor.

Hi Michael
The current architecture is synchronous on the client side since the socket server waits for a message from the server. I understand that "polling" is a work around to overcome the asynchronous nature of HTTP.

So I googled "synchronous http call in angularJS" and found the following thread.

stackoverflow.com/.../synchronous-http-call-in-angularjs

In summary it says to "Take a look at promises to overcome such issues, because they are used all over the place, in angular world"

Are you at all familiar with this and if so what do you think in the context or our discussion?

Thanks
0 Likes
Highlighted
Micro Focus Expert
Micro Focus Expert

HTTP isn't asynchronous. The XMLHttpRequest API can be either synchronous or asynchronous, and asynchronous is recommended for a better user experience. (If the server is slow, the user isn't sitting and waiting for the page to respond.)

While the current client may be synchronous, that doesn't mean a web client should be. Javascript (on its own or with any of the popular frameworks) makes asynchronous design quite straightforward. If you need to simulate synchronous behavior, it's easy to do that: while a request is pending, change to the "wait" cursor and disallow additional requests to the server. A decent book on Javascript client programming should cover this sort of design.

Note that AngularJS is the old version of Angular - the new one is called Angular 5. (It used to be Angular 2, but was renamed for some reason.) I'd strongly recommend using the new framework, if you're going to use Angular.

Promises are actually a feature of Javascript (starting with ECMAScript 6), not of Angular itself. They're an alternative to using callback functions. The proponents of promises claim that they're cleaner and easier to understand than callbacks, and that may be true for complex scripts, but for many purposes callbacks are just fine and more straightforward for programmers coming from other languages.

In any case, my advice is to choose a Javascript framework (Angular, React, whatever) for your client, and get a book on that framework. It's much easier to understand this stuff when you've built some simple applications using it.
0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.