So, we've built a webapp using Grizzly/Jersey. You run the produced jar file, and it then provides REST endpoints, which allow pulling data from the database and creating new entries, etc. For one reason or another, we now want to migrate to a webserver, like Payara or Glassfish or something. I'm having trouble getting it to work. It compiles to a war, now, and gets deployed to Payara. Following Deploying jersey web services on Payara 4 doesn´t expose methods, I got it to at least acknowledge that there are endpoints. However, they rely on an injected EntityManager, which we define/bind (along with its dependencies) in a ResourceConfig subclass, which isn't getting loaded, so it crashes. Anybody know how to load the ResourceConfig? Also, anything else that will need to be done to get this working?
If you're going off the answer from your linked post
#javax.ws.rs.ApplicationPath("API_PATH_FOR_JAXRS")
public class SampleApplication extends Application {
}
This would explain the behavior you are seeing. An empty Application annotated with #ApplicationPath will cause the Jersey bootstrap to scan the classpath for #Path and #Provider class, and register those classes.
But you are using a ResourceConfig to do all your registration yourself. It just happens that ResourceConfig is actually a subclass of Application. So instead of creating a new Application subclass to put the #ApplicationPath annotation on, just put on your ResourceConfig subclass.
If you were not subclassing ResourceConfig previously, e.g.
ResourceConfig config = new ResourceConfig()
.packages("...")
.register(...);
Then just subclass it now
#ApplicationPath("...")
public class AppConfig extends ResourceConfig {
public AppConfig() {
packages("...");
register(...);
}
}
Related
I have an application called A packaged as a war.
I have an interface called CustomerLogic packaged in a jar.
Application A has a dependency and includes interface CustomerLogic in its war.
Now I would like to give this application to different customers so they can write their own logic by creating a class, implementing interface CustomerLogic, package it as a(EJB?) jar. And deploy that to the application server, in this case Glassfish.
So in my application code I have:
#Inject
private CustomerLogic customerLogic;//This will hopefully inject any implementation of the interface
But this fails to deploy since there are no implementations of CustomerLogic available yet.
So I create a customer specific jar that contains:
public class VolvoLogic implements CustomerLogic
and deploys this to the glassfish.
But this fails cause the interface can't be found, it resides in application A's war.
Am I thinking about this in the wrong way. What is the best way to do this.
I don't think I want to create an EAR cause I don't want to rebuild the application every time a new customer wants it. I just want to ship the standard untouched application and they can implement their own logic.
I want to start a new project using Spring Boot and Jersey. I have read numerous tutorials on how to do this, but one thing still puzzles me. Why do I have to register all my Jersey resources?
As an example, Lokesh Gupta has written a tutorial at https://howtodoinjava.com/spring-boot/spring-boot-jersey-example/#jersey-config where he has the following code:
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.stereotype.Component;
#Component
public class JerseyConfig extends ResourceConfig
{
public JerseyConfig()
{
register(UserResource.class);
}
}
I don't want to register all my resources this way. Is there a way to get the resources to be picked up by Jersey's resource scanner? Using the method above, will the #Provider annotation of Jersey be honored? Is it possible to set the jersey.config.server.provider.packages servlet parameter somewhere?
To sum it all up: "How can I autoconfigure Jersey using Spring Boot?"
If you read in the Spring boot documentation JAX-RS and Jersey
Jersey’s support for scanning executable archives is rather limited.
For example, it cannot scan for endpoints in a package found in a
fully executable jar file or in WEB-INF/classes when running an
executable war file. To avoid this limitation, the packages method
should not be used, and endpoints should be registered individually by
using the register method, as shown in the preceding example.
So if you want an executable jar/war file then the answer is no.
I am creating a few spring components and it would be a part of a library - jar.
I want the components to get loaded automatically by the applications that have the jar in the classpath.
#Component
public class AComponent {
}
I tried creating a configuration class and doing a component scan, but, the configuration is not loading.
#Configuration
#ComponentScan(BasePackages="")
public class ComponentConfig {
}
Can you please suggest a solution? It's a non-spring-boot application.
As you are writing a library, that uses Spring, I do not believe it is possible for the client applications to make zero changes. Your library has a collection of Spring beans that must be loaded into an ApplicationContext. At the very least, the clients will need to include your #Configuration/#Component classes (via scanning).
Good luck.
I have read that from JavaEE 6 web.xml is optional.
So without web.xml, how can I tell the application server to use Jersey as the implementation for JAX-RS specification?
What #AlexNevidomsky wrote in his answer is correct, as far as how to implement the app configuration with no web.xml; you use an #ApplicationPath annotation on an Application subclass.
#ApplicationPath("/api")
public class AppConfig extends Application {}
For more information on deployment options, see the Jersey Docs: Chapter 4. Application Deployment and Runtime Environments
Or more commonly, with Jersey as implementation, we would extend ResourceConfig (which extends Application).
#ApplicationPath("api")
public class AppConfig extends ResourceConfig {
public AppConfig() {
packages("package.to.scan");
}
}
So how is this implemented...
First things first, not all Java EE servers use Jersey. Actually the only ones I know that use Jersey are Glassfish and WebLogic. JBoss uses Resteasy. Tom EE uses CXF. WebSphere uses Apache Wink. Those are the only ones I can think of.
So I guess the question is "How does the Server know how to load the JAX-RS application?"
Servlet 3.0 introduced the pluggability mechanism, which makes use of a ServletContainerInitializer. How it works is that when the Server/Servlet container is started, it scans jars for a META-INF/services folder with a file named javax.servlet.ServletContainerInitializer. This file should include one or more fully qualified names of implementations of the ServletContainerInitializer.
This interface has only one method
void onStartup(java.util.Set<java.lang.Class<?>> c, ServletContext ctx)
The Set<Class<?> will be a list of classes, fitting the criteria in the #HandlesTypes annotation on the ServletContainerInitializer implementation. If you look at Jersey's implementation
#HandlesTypes({ Path.class, Provider.class, Application.class, ApplicationPath.class })
public final class JerseyServletContainerInitializer
implements ServletContainerInitializer {
You should notice some familiar annotation classes, as well as the Application.class. All these classes matching the criteria, while scanning, are added to the Set passed to the onStartup method.
If you scan the rest of the source code, you will see all the registration being done with all of those classes.
Resteasy uses
#HandlesTypes({Application.class, Path.class, Provider.class})
public class ResteasyServletInitializer implements ServletContainerInitializer
I won't get into to others.
Some source you can look at...
JerseyServletContainerInitializer source code
ResteasyServletInitializer source code
JAX-RS specs
You don't have to specify anything in web.xml. Define an activator class:
#ApplicationPath("/rest")
public class _JaxRsActivator extends javax.ws.rs.core.Application {
static {
//Check some system init on REST init.
Config.initCheck();
}
}
After playing around with example SOAP application Calculator from NetBeans, I began making my own app, using some third-party WSDL's as service models.
I managed to successfully create a web service classes from this WSDL, unfortunately, when I try to inject this service into my servlet (called ClientServlet), I got 500 error
"javax.servlet.ServletException: Error instantiating servlet class clients.ClientServlet".
The service interface methods are defined in Interface class MyServiceInterface. Don't ask me why it is that way - this service is made by third party.
When I comment out this annotation, and subsequent field declaration, then it works (but I can't use this service).
My code snippet:
#WebServiceRef(wsdlLocation="url/to/wsdl/of/my/service.wsdl")
public MyServiceInterface service;
Of course, I tried to do this without dependency injection, by direct creation of the instance of this class:
service1 = new MyService().getMyService();
MyService.java was created during importing a service from WSDL. GetMyService() method should return instance of the class that is implementing MyServiceInterface. But instead, Java throws me
exception at javax.xml.ws.Service.getPort(Service.java:92)
I am using Apache Tomcat 7.0 and Netbeans 7.0 IDE. What I should do now?
SOLVED - I just made it from scratch using GlassFish 3.1 server.