Null pointer exception with OutboundSseEvent in a server sent event service - java

I am trying to set up server sent events in a Java server with the OutboundSseEvent class. I'm not sure why my code keeps throwing a null pointer exception. I am using these tutorials as reference.
https://www.baeldung.com/java-ee-jax-rs-sse and https://www.programcreek.com/java-api-examples/index.php?api=javax.ws.rs.sse.OutboundSseEvent
#Path("ssetest")
public class SSETestService extends SecureService {
private Sse sse;
#GET
#Path("/test")
#Produces("text/event-stream")
public void SSETestService(#Context Sse sse, SseEventSink sseEventSink)
throws InterruptedException, IllegalArgumentException {
OutboundSseEvent stringEvent = sse.newEventBuilder()
.name("ping")
.data("hello world").build();
sseEventSink.send(stringEvent);
}
}
On the client side...
testSSE() {
console.log("in testSSE()");
const evtSource = new EventSource(
"http://localhost:8081/api/ssetest/test"
);
evtSource.onmessage = function(event) {
console.log("received message");
console.log("event.data: " + event.data);
};
evtSource.addEventListener("ping", function(event) {
console.log("event.data: " + event.data);
console.log("received ping event");
});
evtSource.onerror = function(err) {
console.error("EventSource failed:", err);
};
}
Thanks for any pointers.

The instance sse is null. For litmus like test, you can print sse to see. If you using Spring framework private Sse sse; should be autowired as follows
#Autowired
private Sse sse;
I think the parameter #Context Sse sse should be removed as you have already defined in the class.

I'm not sure where exactly your null pointer occurs, but in my case it was because injection of the Sse and SseEventSink instances failed. In that case, an implementation of the SSE feature is missing on your classpath. You could use:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-sse</artifactId>
<version>3.4.5</version>
</dependency>
Furthermore, you need to make sure that your servlet allows asynchronous communication by enabling that setting, e.g.:
#WebServlet(... asyncSupported = true, ...)
...
public class MyServlet {
...

Related

Apache camel 2.16 enrich - No consumers available on endpoint in JUnit

I upgraded to camel 2.16 and one of my route Unit Tests started failing.
Here is my route definition:
public class Route extends RouteBuilder{
#Override
public void configure() throws Exception {
from(start).enrich("second");
from("direct:second")
.log(LoggingLevel.DEBUG, "foo", "Route [direct:second] started.");
}
}
Here is my test:
#RunWith(MockitoJUnitRunner.class)
public class RouteTest extends CamelTestSupport {
private Route builder;
#Produce(uri = "direct:start")
protected ProducerTemplate template;
#Before
public void config() {
BasicConfigurator.configure();
}
#Override
protected RouteBuilder createRouteBuilder() {
builder = new Route();
return builder;
}
#Override
protected CamelContext createCamelContext() throws Exception {
SimpleRegistry registry = new SimpleRegistry();
return new DefaultCamelContext(registry);
}
#Test
public void testPrimeRouteForSubscriptionId() {
Exchange exchange = ExchangeBuilder.anExchange(new DefaultCamelContext()).build();
exchange.getIn().setBody(new String("test"));
template.send(exchange);
}
}
The error I'm getting when I run the test is:
org.apache.camel.component.direct.DirectConsumerNotAvailableException: No consumers available on endpoint: Endpoint[direct://second]. Exchange[][Message: test]
Worthy of note is the following line in the camel 2.16 notes:
http://camel.apache.org/camel-2160-release.html
The resourceUri and resourceRef attributes on and has been removed as they now support a dynamic uris computed from an Expression.
Thanks in advance for any help.
Swap the order so the the direct route is started before the enrich.
http://camel.apache.org/configuring-route-startup-ordering-and-autostartup.html
Or use seda instead of direct in your unit test: http://camel.apache.org/seda
Or use ?block=true in the direct uri to tell Camel to block and wait for a consumer to be started and ready before it sends a message to it: http://camel.apache.org/direct
This is a somewhat old issue, but since i pulled out most of my hair out last night, trying to figure out why it was ok to use to("direct:myEndpoint") but not enrich("direct:myEndpoint"), I'll post the answer anyway - maybe it'll save somebody else from getting bald spots ;-)
It turns out to be a test-issue. In case of Direct endpoints, enrich checks whether there is a running route in the context before passing the Exchange to it, but it does so by looking at the CamelContext held by the Exchange it is currently handling. Since you passed your ProducerTemplate an Exchange what was created with a new DefaultCamelContext(), it has no "direct:second" route available.
Luckily there is a couple of simple solutions. Either create the Exchange using the CamelContext from CamelTestSupport, or use the ProducerTemplate sendBody(...) method instead:
#Test
public void testWithSendBody() {
template.sendBody(new String("test"));
}
#Test
public void testPrimeRouteForSubscriptionId() {
Exchange exchange = ExchangeBuilder.anExchange(context()).build();
exchange.getIn().setBody(new String("test"));
template.send(exchange);
}
The blueprint test keeps throwing exception, No Consumers available.
My scenario was that I have an osgi svc which exposes a method which can be called from any another osgi svc.
So the exposed svc method makes a call to a direct:
#EndpointInject(uri = "direct-vm:toRestCall")
ProducerTemplate toRestCall;
svcMethod(Exchange xch){
exchange.setOut(
toRestCall.send("seda:toDirectCall", xch -> {
try{
xch.getIn().setBody("abc");
}catch (Exception ex){
ex.getMessage();
}
}
}).getIn());
And when I tested the direct that it calls, Blueprint advice with JUnit used to keep throwing the following exception:
org.apache.camel.component.direct.DirectConsumerNotAvailableException:
No consumers available on endpoint: Endpoint. Exchange[Message: {..........

Play framework 2.5.x Web Socket Java

I am following the instructions in the official documentation of Play framework 2.5.x to Java Websockets, I created a controller with this function
public static LegacyWebSocket<String> socket() {
return WebSocket.withActor(MyWebSocketActor::props);
}
And an Actor class MyWebSocketActor:
public class MyWebSocketActor extends UntypedActor {
public static Props props(ActorRef out) {
return Props.create(MyWebSocketActor.class, out);
}
private final ActorRef out;
public MyWebSocketActor(ActorRef out) {
this.out = out;
}
public void onReceive(Object message) throws Exception {
if (message instanceof String) {
out.tell("I received your message: " + message, self());
}
}
}
Then the app is started I try to connect at ws://localhost:9000 as is written in the official documentation:
Tip: You can test your WebSocket controller on
https://www.websocket.org/echo.html. Just set the location to
ws://localhost:9000.
But the web socket seems unreachable, how can I test it?
Thanks
In order to handle WebSocket connections, you also have to add a route in your routes file.
GET /ws controllers.Application.socket()
Then your WebSocket endpoint will be ws://localhost:9000/ws - use it for testing with the echo service.
Finally with the help of Anton I solved it!
First: remove static from socket() method
public LegacyWebSocket<String> socket() {
return WebSocket.withActor(MyWebSocketActor::props);
}
Then add an endpoint in routes file for the socket() method
GET /ws controllers.HomeController.socket()
At this point you have to start the application with SSL/TLS in this way, for example:
activator run -Dhttps.port=9443
In websocket.org/echo.html insert wss://localhost:9443/ws in Location field and it connects to websocket!
Furthermore if I visit https://localhost:9443/ws I continue to obtain the message
Upgrade to WebSocket required

Jersey Endpoint+OSGi Dependency, Keeping Track

I have a Jersey endpoint which uses a custom OSGi Service ExceptionManager Service.
#Path("service")
public class ServiceFacade {
private volatile ExceptionManager exceptionManager;
public ServiceFacade() {
BundleContext bC = FrameworkUtil.getBundle(ServiceFacade.class).getBundleContext();
ServiceReference<ExceptionManager> sR = bC.getServiceReference(ExceptionManager.class);
if (sR != null)
this.exceptionManager = bC.getService(sR);
}
#GET
#Consumes({MediaType.APPLICATION_JSON})
#Produces(MediaType.APPLICATION_JSON)
public Response sayHello() {
try {
if (exceptionManager == null)
return Response.status(Status.SERVICE_UNAVAILABLE).build();
// Do some work...
} catch (Exception e) {
exceptionManager.handle(e);
}
}
}
This Jersey class is added to the Jersey Application as a simple class, that means that every time a user hits this endpoint, a new instance of this class is created to handle the request. As you can see, the class contains a constructor which initializes the ExceptionManager Service. My question is, isn't there a simplified way of retrieving the service without going to BundleContext?
I have seen DependencyManager, but this bundle seems to only add the dependencies to the class (ServiceFacade in this case) during the Activation process, but that dependency resolution is too early this has to be done during run-time, every time an instance is created. Bellow is an approximation with DependencyManager but is not a solution for this:
public class Activator extends DependencyActivatorBase {
#Override
public void init(BundleContext bundleContext, DependencyManager dependencyManager) throws Exception {
dependencyManager.add(createComponent()
.setImplementation(ServiceFacade.class)
.add(createServiceDependency()
.setService(ExceptionManager.class)
.setRequired(true));
}
}
Thanks.-
You can obtain the reference to an OSGi service without accessing to BundleContext by using Declarative Services. A tutorial can be found here.
You can make the endpoint a singleton resource. This way you can let the dependency manager create a single instance and inject services and then add that instance to the Jersey application.
There are a few limitations, like Jersey's field or constructor injection does not work. You also have to be careful about concurrency when using fields of the resource.

Showing Grizzly exceptions in Eclipse console

When launching a simple REST interface with Eclipse using the jersey-container-grizzly2-http Maven dependency version 2.13, I do not get any exceptions shown after triggering errors in the browser. Other log output gets shown in the console just fine, but Exceptions just get swallowed.
I created an Exception handler which is neither instantiated or called:
package mypackage.rest;
#Provider
class ExceptionHandler implements ExceptionMapper<Throwable>
{
#Override public Response toResponse(Throwable t)
{
System.out.println("toResponse called");
t.printStackTrace();
return Response.status(Status.BAD_REQUEST).entity(t.getMessage()).build();
}
}
The Grizzly Server construction:
package mypackage.rest;
public class GrizzlyHttpUtil
{
public static final URI baseURI = UriBuilder.fromUri("http://localhost/").port(10010).build();
public static HttpServer startThisServer()
{
ResourceConfig resCon = new ResourceConfig().packages("mypackage.rest");
return server = GrizzlyHttpServerFactory.createHttpServer(baseURI, resCon);
}
}
The REST API class
package mypackage.rest;
#Path("")
public class Rest
{
#GET #Path("datasets") #Produces(MediaType.TEXT_HTML)
public static String datasets()
{
throw new RuntimeException();
}
}
Update
I got it to work with resCon.register(ExceptionHandler.class);. Why is that necessary? Why does ResourceConfig().packages(...) not handle this on its own?
I've just had to solve the same problem. Here is my initialization code that convinces Grizzly HTTP server to display errors: http://source.apidesign.org/hg/bck2brwsr/rev/18ae4fbcfb87
Logger l = Logger.getLogger("org.glassfish.grizzly.http.server.HttpHandler");
l.setLevel(Level.FINE);
l.setUseParentHandlers(false);
ConsoleHandler ch = new ConsoleHandler();
ch.setLevel(Level.ALL);
l.addHandler(ch);
I am using Grizzly 2.3.3

Mapping of custom exception in JAX-RS via #WebFault annotation

I am developing a Client-Server app with JAX-RS / Apache CXF, JSON
I would like Apache CXF to handle my exception transparently on both ends : Which means transforming the exception into a bean, serializing it with my Jackson Serializer (JSON) and then doing the over way around on client side.
I have seen several confusing posts/answers on this subject and came up with using the #WebFault annotation :
#WebFault(name=CODE, faultBean="foo.bar.FaultBean")
public class DuplicateRuleNameFault extends Exception {
static final public String CODE = "DUPLICATE_RULE_NAME";
private FaultBean faultBean;
public DuplicateRuleNameFault(String msg) {
super(msg);
this.faultBean = new FaultBean(msg);
}
public DuplicateRuleNameFault() {
}
public FaultBean getFaultBean() {
return faultBean;
}
public void setFaultBean(FaultBean faultBean) {
this.faultBean = faultBean;
}
}
With no success ... Currently, CXF seems to happily ignore the annotation on the Exception and handle it as an unknown exception : 500 status error and no response body generated on the server side.
Is there something specific I have to configure in the "" server element of my Spring context ? I already have Spring scanning my Exception/FaultBean classes (is it even needed BTW ?).
I would appreciate if you could point me at some working example.
Thanks.
#WebFault's are not part of the JAX-RS specification. You will want to read up on section 3.3.4 of the specification, which describes the different ways you can accomplish what you are trying to do.
Option 1
Design your resource classes to throw WebApplicationException's. Set the response property of these exceptions to be a valid JAX-RS response containing the fault beans you want to send to the client.
Option 2
Define exception mapping providers. You can create a hierarchy of these to handle all the common exceptions your application will throw. Or you can create a top level exception with an embedded bean and an exception handler for it. And then derive several specific exceptions from the top level one.
public abstract class MyApplicationException<T> extends Exception {
private T faultBean;
// Constructors, setters/getters
}
#Provider
public class MyApplicationExceptionHandler implements ExceptionMapper<MyApplicationException<?>> {
// Implementation
}
One way of doing this is by using the javax.ws.rs.core.Response object like so :
#GET
#Path("/")
public Response getBlah()
{
try {
return Response.status(Response.Status.OK)
.entity(<Object you want to return>).build();
}
catch (final DuplicateRuleNameFault e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(e.getFaultBean().getMsg()).build();
}
}

Categories