Christopher Dodunski

Ranch Hand
+ Follow
since Jul 28, 2017
Cows and Likes
Cows
Total received
0
In last 30 days
0
Total given
0
Likes
Total received
3
Received in last 30 days
0
Total given
10
Given in last 30 days
0
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Christopher Dodunski

Dave Tolls wrote:You'd found all the parts, they just weren't in quite the right place.



And just to add another chapter to the story, I had to incorporate the coalesce() function within the HQL to deal with the case of 'updated' potentially being null.  Without this, records with null in the 'updated' column got thrown to the end of the result set, despite having a recent 'created' date.  An unexpected behaviour of the greatest() function.

Dave Tolls wrote:greatest is supposed to be used as part of an ORDER BY.

So (and this is hand written, so is likely to have errors):



So it doesn't transfer everything from the database, as you only want the newest, you need to use the setMasResults() method on Query to limit the number returned.
Set it to 1, and the result will have the newest Movement.



Ahh... thanks Dave!  I expected that there would be a simple explanation.  :-)
By the way, here is the HQL query I wrote, but it errors.  It's the first time I've ever attempted to use greatest() in an HQL named query.
Hi all,

I have a table for storing items, and wish to receive the single most recently created or updated record.  The table has a 'created' date column and an 'updated' date column.  Of course I could easily separately retrieve the record with the latest created date, and the record with the latest updated date, then compare the two in my code.  But, partly for performance reasons, I'd prefer to do this using the one HQL query, and have just the one record back.

I don't imagine this is such an unusual need, but a Google search revealed no online examples that fit the bill.

Regards,

Chris.
Hit a dead end with the 'WebSocket annotations on interface' idea, sorry to say.  

From the Java WebSockets specification:


4.1
@ServerEndpoint
This class level annotation signifies that the Java class it decorates must be deployed by the implementation as a websocket server endpoint and made available in the URI-space of the websocket implementation. The class must be public, CONCRETE, and have a public no-args constructor.


May have to venture into the unfamiliar world of programmatic endpoints by the looks.

Regards,

Chris.

Al Hobbs wrote:So you get the interface implementation from the registry and then when you cast it to the underlying class it throws a cast exception?  It seems like that should work.



Good point!  Looking at the Tapestry-IoC Registry code I notice that although it constructs a (plastic) service proxy object, it does cast it to its associated interface before making it available from the registry's getService() method.  So if I move the WebSocket annotations to my interface as previously intended, Tomcat should be getting back from the registry what it expects: an instance of the interface annotated with @ServerEndpoint.  My first job for tomorrow.  :-)

You seem to be in a similar time zone Al?  I'm in Taranaki, NZ.

Al Hobbs wrote:Yeah, I was thinking you could put the annotation on the interface.  That seems like a better design anyway.  If you have an interface that acts as a server endpoint, you probably aren't going to use it in another situation where you don't need the annotation. maybe..



According to the folks at Tomcat...

> The WebSocket spec explicitly states that WebSocket annotations do not
> follow Java inheritance so moving the annotation to the interface is not
> an option.
>
> I think you are going to have to build your ServerEndpointConfig
> programmatically so you can specify the correct endpoint class.

Al Hobbs wrote:It seems like what the site says is to put those classes into a service  class and then get that service class from the registry.



Indeed, except that what you get back from the IoC registry is a proxy object that implements the interface for that particular service.  The service implementation of course implements this same interface, but unfortunately the registry does not return an instance of this implementation.  Therein lies the problem: Tomcat requires an instance of the class annotated with @ServerEndpoint, and this is on the service implementation class.

Someone suggested shifting the WebSocket annotations from the implementation to the interface.  I will try this, though I've only ever seen POJOs annotated as WebSocket endpoints, never interfaces.

Regards,

Chris.

Al Hobbs wrote:is that the full error message without casting?  It seems like something screwy is going on with the class types.  The expected class and the given class don't match, so you need to make sure they match up.



Hi Al,

In the meanwhile I researched Tapestry-IoC and how it works.  Turns out there is a reason for what is being returned looking a little 'screwy' ($HarbourServerEndpoint_39c9cc24eb8b2a).  It is a service proxy object, not an instance of the service implementation as I was expecting.  I'm not sure how typical this is for IoC containers.  Quoting from the Tapestry website:


Services consist of two main parts: a service interface and a service implementation.

The service interface is how the service will be represented throughout the rest of the registry. Since what gets passed around is normally a proxy, you can't expect to cast a service object down to the implementation class (you'll see a ClassCastException instead). In other words, you should be careful to ensure that your service interface is complete, since Tapestry IoC effectively walls you off from back doors such as casts.



This makes it rather tricky to acquire from the IoC registry instances of the class annotated with @ServerEndpoint, and I'm now exploring other options.

Regards,

Chris.
Hello,

Just a quick question with regard to extending ServerEndpointConfig.Configurator to override Tomcat's default action of instantiating the POJO class annotated with @ServerEndpoint on receiving a WebSocket request.  My reason for doing this is that my endpoint class depends on IoC dependency injection, and therefore needs to be got from the registry to have its dependencies in place.

My Configurator method:



The @ServerEndpoint annotation is placed on on my HarbourServerEndpointImpl POJO class, not the interface that it implements.  Based on the below runtime catalina.out error message the problem appears to be that the registry is returning HarbourServerEndpoint whereas Tomcat is expecting an instance of HarbourServerEndpointImpl?

I'm hoping someone can please explain what is going wrong with my custom Configurator.


15-Apr-2019 12:45:28.488 SEVERE [http-nio-8080-exec-915] org.apache.coyote.AbstractProtocol$ConnectionHandler.process Error reading request, ignored java.lang.ClassCastException: Cannot cast $HarbourServerEndpoint_39c9cc24eb8b2a to com.optomus.harbour.services.HarbourServerEndpointImpl
       at java.lang.Class.cast(Class.java:3369)
       at com.optomus.harbour.services.HarbourServerEndpointConfigurator.getEndpointInstance(HarbourServerEndpointConfigurator.java:17)
       at org.apache.tomcat.websocket.pojo.PojoEndpointServer.onOpen(PojoEndpointServer.java:44)
       at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:133)
       at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:846)
       at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471)
       at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
       at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
       at java.lang.Thread.run(Thread.java:748)


Finally, with no casting at all, the compiler gives the error:

   Error:(17, 40) java: incompatible types: inference variable T has incompatible bounds
       equality constraints: com.optomus.harbour.services.HarbourServerEndpoint
       upper bounds: T,java.lang.Object

Regards,

Chris.
Hi team,

I'm developing a web app that accepts websocket connections from desktop clients for viewing various areas of a worksite.  The relationship between worksites and watching clients is many-to-many, as any given client app may register to watch several worksite areas, and any given worksite area may be watched by several connected clients.

On the server endpoint I chose to implement this relationship using  Guava multimap: keys being worksite areas (duplicates allowed), and values being endpoint connections (again, duplicates allowed).  This map is declared as a class (static) field.

When a change occurs, serverside, in relation to a given worksite area, I simply use the multimap's get() method to retrieve all the endpoints watching that particular area, and PUSH a notification message out to those clients.  So far so good.

The challenge is how to remove from this multimap all entries relating to a client endpoint that subsequently disconnects.  I'm wondering whether there might be a better alternative to the below, where I simply iterate through all entries and test each value as to whether it equates to the endpoint that just disconnected.

5 months ago
Hi Claude,

I promised to report back once I'd settled on a working solution for full duplex communication between server and desktop application, and I have.  The vast majority of example code online is for chat room, where the client is a browser rather than a Swing application.  I ended up using Tyrus standalone (Grizzly) on the client, and it is working very well for me.

There is an excellent series of video tutorials where WebSocket messages may be of multiple type - rather more complicated than your typical chatroom service.  Moreover, each message type is encoded/decoded to/from JSON.  I was able to adapt this code to use with Tyrus rather than browser oriented JavaScript.  The author is Kevin Jones (sounds British), and here is a link to the first episode: https://youtu.be/bdFhsxOQRQ4

I'm happy to help anyone out with similar needs.

Regards,

Chris.
Thank you Claude, you make good sense.

I've found some example code that seems to sit nicely with what you suggested...

Server-side: https://www.baeldung.com/java-websockets

Client-side: https://youtu.be/X2R_Iyga88E

I'll start coding tomorrow and let you know how I get on.  :-)

Thank you, too, for advising on JMS.  I'll keep that in mind in case WebSocket proves problematic for some reason (for instance connectivity proves fickle).

Regards,

Chris.
My needs:  I've developed a web application that models commercial harbour environments.  To complement the webapp, I've developed a Swing desktop application.  This application is more graphical, and gives a 'computer game' like bird's eye overview.  Obviously for this desktop app to reflect the state of the webapp in realtime, the latter must have the ability to push data out to connected clients.  This data is in the form of several custom object types - eg. VesselState.java.
Netty indeed looks interesting.

I found an introduction to Netty here: https://www.baeldung.com/netty

In the example code I see that port to port communication is low level, requiring that custom objects be deconstructed down to their member fields for transmission (encoding/decoding).  Moreover, any String values are not simply serialised, but are preceded by an int value denoting their length (so Strings sent as a pair of values).

Given all this extra overhead, compared to simply serialising and deserialising custom objects - using Apache serialize utils in combination with 'instanceof' - why would one typically opt for Netty over plain Java websockets?

Also, the example simply involved responding to a network request.  I assume Netty allows connection sessions to be held open, too, so that the server can not only 'respond' but also 'push' data out to a client?

Netty looks interesting, but just wondering whether it is the right tool for the job.  :-)

Regards,

Chris.