Showing Grizzly exceptions in Eclipse console - java

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

Related

Microprofile #Fallback not working in native image mode

Having the following code running on Quarkus:
#Singleton
#RegisterForReflection
public class StoreService {
private static final Logger LOGGER = Logger.getLogger(StoreService.class);
#Inject
#RestClient
StoresApiClient client;
#CacheResult(cacheName = "stores")
#Fallback(fallbackMethod = "allFallbackStores")
public List<Store> allStores() {
// call REST API using client
}
#SuppressWarnings("unused")
public List<Store> allFallbackStores() {
try {
LOGGER.info("Falling back to internal stores list");
...
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
the fallback mechanism is working properly in regular JDK mode. On the other hand in native image mode, #Fallback annotation is not being respected and an exception is thrown after unsuccessful API call. What might be a reason for that if #RegisterForReflection annotation is in place?

How to make _asyncSupported = true in Jetty 9.3 while servlet is loaded in code with Google guice ServletModule

I am trying to upgrade the Jetty from 8 to 9.3. As the default value of _asyncSupported become false so it will show the following error.
java.lang.IllegalStateException: !asyncSupported: stackDumperFilter
at org.eclipse.jetty.server.Request.startAsync(Request.java:2248) at
org.eclipse.jetty.continuation.Servlet3Continuation.suspend(Servlet3Continuation.java:188)
at
org.eclipse.jetty.servlets.ProxyServlet.service(ProxyServlet.java:659)
The servlet is loaded in the code through Google guice's ServletModule in the following way.
public class ProxyModule extends ServletModule {
#Override
protected void configureServlets() {
serve("/someurl/*").with(ProxyServlet.class);
}
}
#Singleton
public static class ProxyServlet extends SuperHttpProxyServlet {
#Inject
public ProxyServlet(#Named("something.proxy") Transparent proxy) {
super(proxy);
}
}
After Jetty 9 upgrade, it will take the default value of _asyncSupported which become false. So it will give exception for the following reason in the jetty library file (Package : org.eclipse.jetty.server).
public AsyncContext startAsync() throws IllegalStateException
{
if (!_asyncSupported)
throw new IllegalStateException("!asyncSupported");
_async.startAsync();
return _async;
}
So how do I make the ProxyServlet asyncSupported (true) when it is called by Google Guice's ServletModule ?
I have tried with annotation but it won't work.
#WebServlet(urlPatterns={"/someurl/*"}, asyncSupported=true, loadOnStartup = 1)
#Singleton
public static class ProxyServlet extends SuperHttpProxyServlet {
#Inject
public ProxyServlet(#Named("something.proxy") Transparent proxy) {
super(proxy);
}
}
But it got failed with the same error.
java.lang.IllegalStateException: !asyncSupported: stackDumperFilter at org.eclipse.jetty.server.Request.startAsync(Request.java:2248) at
Set your stackDumpFilter to be asyncSupported=true
The rule of thumb is, if anything in your filter chain (all filters + servlet) uses async, then all of those filters and servlet must be set to asyncSupported=true.

Hysterix Javanica AsyncResult Future.get Throwing Exception

I have a Spring Cloud set up running on my local tomcat. I am using feign client to invoke a remote service wrapped inside Hysterix command one direct and other async as below.
#HystrixCommand(fallbackMethod = "fallBackEmployeeCall")
public List<EmployeeBean> getEmployees() {
//Call through Feign Client
return empInterface.getEmployees();
}
//Async Version
#HystrixCommand(fallbackMethod = "fallBackEmployeeCall")
public Future<List<EmployeeBean>> getEmployeesAsync() {
return new AsyncResult<List<EmployeeBean>>() {
#Override
public List<EmployeeBean> invoke() {
return empInterface.getEmployees();
}
};
}
When I am calling getEmployeesAsync().get()
I am getting below exception
java.lang.UnsupportedOperationException: AsyncResult is just a stab and cannot be used as complete implementation of Future
It is similar to below issue :-
[https://github.com/Netflix/Hystrix/issues/1179][1]
According to docs the solution is to configure HystrixCommandAspect class, which I did as below :-
#Configuration
#EnableAspectJAutoProxy
public class HystrixConfiguration {
#Bean
public HystrixCommandAspect hystrixAspect() {
return new HystrixCommandAspect();
}
}
But I am still getting the same exception. It seems I am missing some configuration.
Note :- my sync method is working fine.
you can try call getEmployeesAsync in the other class, which injected the instance of the class with getEmployeesAsync. I had this exception, too. Then I do it like this successful.

Jersey + Spring standalone webservice #Autowire not working

I am running Restful web-service as standalone application using Jersey.
Below are my service classes which serve's the requests.
LoginServiceImpl.java
#Component
public class LoginServiceImpl implements LoginService {
#Value("${login.service.defaultmessage}")
private String defaultMessage;
#Autowired
private EmLoginDAO emLoginDAO;
#Override
public String defaultCall() {
return defaultMessage;
}
#Override
public String updatePassword(List<Login> userList) {
System.out.println(emLoginDAO + "\n" + userList);
emLoginDAO.save(userList);
return "Passwords Updated...";
}
#Override
public List<Login> getPasswords() {
System.out.println("OBJECT: " + emLoginDAO);
List<Login> userList = null;
userList = emLoginDAO.findAll();
return userList;
}
}
LoginService.java
#Component
#Path("/user")
public interface LoginService {
#GET
public String defaultCall();
#POST
#Path(value = "/print")
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.TEXT_PLAIN)
public String updatePassword(List<Login> userList);
#GET
#Path(value = "/getpassword")
#Produces(MediaType.APPLICATION_XML)
public List<Login> getPasswords();
}
Below is my spring configuration file.
<context:component-scan base-package="com.em.login" />
<context:annotation-config />
After starting the service when I call the respective method get called.
But my defaultMessage and emLoginDAO objects are null. So it is not referring to the properties and spring configuration files.
So can any one please help me to get this correct. Or to find a way to set the properties and spring configuration file paths to Jersey.
Update
Closeable server = null;
try {
DefaultResourceConfig resourceConfig = new DefaultResourceConfig(
LoginServiceImpl.class);
resourceConfig.getContainerResponseFilters().add(
new GZIPContentEncodingFilter());
server = SimpleServerFactory.create(serviceurl,
resourceConfig);
System.in.read();
} catch (IOException e) {
} finally {
if (server != null) {
try {
server.close();
} catch (IOException ex) {
}
}
}
I think this is the culprit:
DefaultResourceConfig resourceConfig = new DefaultResourceConfig(LoginServiceImpl.class);
You are using Spring's IOC to create the objects and do the autowiring, but you are not getting the instance from the Spring container. You need to get the LoginServiceImpl instance from the Spring container, and not have Jersey create it (Jersey does not know how to autowire your #Autowired properties.
You should use the Spring integration with Jersey, seen here.
Edit to respond to your comment, you posted this code:
LoginServiceImpl loginServiceImpl = (LoginServiceImpl) SpringApplicationContext.getBean("loginServiceImpl");
DefaultResourceConfig resourceConfig = new DefaultResourceConfig( loginServiceImpl.getClass());
You are creating a loginServiceImpl via the spring container, and I'll bet if you check your autowired fields will be there.
However, the second line where you use loginServiceImpl.getClass() this is going to create a new LoginServiceImpl, which is not the same one as the loginServiceImpl you got from the context, so you still are going to have the same problem.
You could take a look at Microserver, that will do all the wiring between Jersey and Spring for you (and setup a Grizzly webserver). From the tags I notice you are using Spring boot, with Microserver: micro-boot module you can do (in a class in package com.em.login):
public static void main(String[] args){
new MicrobootApp(()->"test-app").run();
}
And it should wire up Grizzly, Jersey & Spring with Spring-boot enabled for any backend (non-Jax-rs) dependencies.
Alternatively without Spring Boot (plain old Jersey and Spring)
public static void main(String[] args){
new MicroserverApp(()->"test-app").run();
}
To do it manually, you will need to add the Jersey-Spring integration jar to your classpath and make sure both are configured in a way that interoperates (i.e. I think a registering Spring ContextListener is essential). There is an example app here.
Have you configured those two in your spring configuration files?
I mean have you annotated EmLoginDAO also as stereotype Component?
I got this working.
Referred the this part of the Jersey documentation.
Below is the code I have used to make this working.
ResourceConfig resourceConfig = new ResourceConfig(LoginServiceImpl.class);
resourceConfig.register(org.glassfish.jersey.server.filter.UriConnegFilter.class);
resourceConfig.register(org.glassfish.jersey.server.spring.SpringComponentProvider.class);
resourceConfig.property(ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE, true);
resourceConfig.property("contextConfigLocation", "classpath:/spring-config.xml");
URI serviceUri = UriBuilder.fromUri(serviceHost).port(servicePort).build();
server = SimpleContainerFactory.create(serviceUri, resourceConfig);
Thank you all for helping.

Accessing main class from Jersey listener without the main class being a singleton object

I often use Jersey simple server as a webservice in my Java applications. Whenever I do this I only seem to be able to fetch properties from my application (main class) if it is setup as a singleton. So, I only seem to be able to fetch the information with MainClass.getInstance().
I know I can make the Jersey listener some sort of singleton in Jersey but this only means that the listener object will be instantiated once within Jersey in stead of for every single request: The listener is not a real singleton because it still needs a public constructor.
Is there a way to access my application class without it being a singleton object itself?
Here is the relevant code:
public class JerseyService {
private MainClass mainClass;
private int port = 8080;
private DefaultResourceConfig config;
private Closeable jerseyServer;
public JerseyService() {
config = new DefaultResourceConfig(JerseyListener.class); // Attach the listener (resource) to the Jersey server
jerseyServer = SimpleServerFactory.create("http://0.0.0.0:" + jerseyPort, config);
}
public String getData() {
return "somedata";
}
}
#Path("/")
public class JerseyListener {
#Path("getData")
#GET
#Produces("application/json")
public Response getData() {
// How can i call getData() from JerseyService
// without JerseyService being a singleton??
return Response.status(Response.Status.OK).entity("{<jsondata>}").build();
}
}

Categories