according to this (servlet response time is slow for first request) SO Question I can use the load-on-startup parameter in web.xml to create the services classes on startup and not on the first client request, which causes better first-response times for clients.
However I'm using Grizzly+Jersey, how can I configure this behaviour in grizzly, or is this completetly impossible? Then what would be alternatives to grizzly without using a full blown Java EE Application Server
EDIT: Main main method is this:
public static void main(String... args){
//Packages which contain service classes
final ResourceConfig rc = new ResourceConfig()
.packages("de.danielr1996.flamingoapi.services");
//Logging Aktivieren
rc.register(new LoggingFilter());
//Dependency Injection konfigurieren
rc.register(new DependencyBinder());
//Jackson hinzufügen
rc.register(JacksonFeature.class);
//Datenbank initialisieren
DatabaseUtil.getEntityManagerFactory();
// Server erstellen
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
}
Thanks in Advance
ServletAdapter adapter =new ServletAdapter();
...
adapter.setProperty( "load-on-startup", 1 );
UPDATE
I don't now how to configure instance created from Factory. I assume it does not allow you to provide complex configuration.
But you can create server manually this way :
GrizzlyWebServer ws = new GrizzlyWebServer(80);
ServletAdapter adapter = new ServletAdapter();
Then configure adapter Javadocs
adapter.setContextPath("...");
adapter.setRootFolder("...");
adapter.setHandleStaticResources(true);
adapter.setProperty("load-on-startup","1");
Add adapter to server
ws.addGrizzlyAdapter(adapter, new String[]{"/uri"});
Related
I am new to Jetty and trying to understand by online example program. Here is the sample program I used:
public class EmbeddedJettyMain {
public static void main(String[] args) throws Exception {
Server server = new Server(7070);
ServletContextHandler handler = new ServletContextHandler(server, "/example");
handler.addServlet(ExampleServlet.class, "/");
server.start();
}
}
With that I can use:
http://localhost:7070/example/
Now I want to add one more servlet URI
http://localhost:7070/example2
How can I do this ?
I can see some reference such as webapp, looking for a good approach.
Server server = new Server(7070);
ServletContextHandler handler = new ServletContextHandler(server, "/");
handler.addServlet(ExampleServlet.class, "/example");
handler.addServlet(ExampleServlet.class, "/example2");
Each addServlet creates a mapping. Jetty will create an instance of the Servlet that will be a singleton for each mapping, meaning that init(ServletConfig config) will only be called once in each instance and all requests to a mapping go to the same instance.
Jetty provides a Web server and javax.servlet container.
Your servlets are stored and served via jetty's embedded container to serve when needed.
I have a Jersey REST 2.5.1 service which is served through a Grizzly server. Everything works fine so far. I want to add some static content, which is also served through Grizzly and provided from my JAR file. Therefore I use CLStaticHttpHandler. When I access static resources, such as my index.html explicitly (e.g. http://localhost:8080/index.html), everything works fine. However, when I try to access the root http://localhost:8080, I get a 404. The code looks like this:
ObjectMapper mapper = new ObjectMapper();
// some configuration stuff here
JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
provider.setMapper(mapper);
ResourceConfig resourceConfig = new ResourceConfig()
.packages("my.restapi.package")
.register(provider);
HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), resourceConfig);
HttpHandler httpHandler = new CLStaticHttpHandler(HttpServer.class.getClassLoader(), "/static/");
httpServer.getServerConfiguration().addHttpHandler(httpHandler, "/");
As far as I can tell from debugging, org.glassfish.grizzly.http.server.CLStaticHttpHandler.handle(String, Request, Response) never gets called. Any hints, how I can make the index.html accessible as default page?
After some wasted hours, I feel a bit stupid now, but the simple solution was, to specify a path in BASE_URI (http://localhost:8080/api/ instead of http://localhost:8080/). Now, when accessing /, I get the index.html and the REST methods are under /api.
I am migrating my Jersey web application from Jersey 1.17.1 to 2.3.1, using Jetty 9.0.6. With Jersey 1.17.1, the Resource would load during startup. However, pretty much the same code (below) only starts when a request comes in. But I would like to make sure it is loaded during startup (i.e., the constructor of the annotated resource class is called). Any idea what's wrong?
public static void startServer(){
org.eclipse.jetty.server.Server server = new Server();
org.eclipse.jetty.servlet.ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
org.glassfish.jersey.servlet.ServletContainer servletContainer = new ServletContainer();
org.eclipse.jetty.servlet.ServletHolder servletHolder = new ServletHolder(servletContainer);
servletHolder.setInitParameter(ServerProperties.PROVIDER_PACKAGES, "mypackage");
servletHolder.setInitOrder(0); // this does not seem to work
context.addServlet(servletHolder, "/*");
server.start();
}
And roughly:
package mypackage;
#Singleton
#Path("/foo")
public class MyResource {
public MyResource(){
// I want this to be called when I start the server
}
#Path("bar")
public Response receivePayload(#Context HttpServletRequest request, String payloadString){
// do some stuff
return response;
}
}
Uli,
The servletHolder.setInitOrder(0) that you refer to is related to the org.glassfish.jersey.servlet.ServletContainer class. The unit tests for servlet init ordering in jetty-9.0.6 are passing, so I assume that the jersey ServletContainer class is in fact being loaded on startup as expected.
Perhaps jersey has changed behaviour between version 1.17 and 2.3 and only lazily initializes the resources mapped using the #Path annotation?
Or perhaps jersey has changed to use some servlet 3.0 features for initialization, such as ServletContainerInitializers? If that is the case, then you'll need to upgrade from a ServletContextHandler to a WebAppContext, and ensure that the support for these servlet 3.0 features are enabled (see jetty docs on using annotations with embedded jetty here: http://www.eclipse.org/jetty/documentation/current/using-annotations-embedded.html)
cheers
Jan
I have searched everywhere for a basic example of how to use HK2 dependency injection in Jersey 2.0, but have come up short.
From this question, it appears you need to create a class which extends AbstractBinder. However, the rest of the example shows how to register the binder with your application by editing the web.xml file. However, I want to avoid this and would like to instead register the binder with my HttpServer instance directly.
This is what I have written for my HttpServer:
int port = config.getInt("port", 8080);
boolean useFake = config.getBoolean("fake", false);
final URI baseUri = URI.create("http://" + "localhost" + ":" + port + "/");
List<Binder> binders = Arrays.asList((Binder)new StatusModule(useFake),
(Binder)new NetworkModule(useFake));
final ApplicationHandler applicationHandler = new ApplicationHandler();
applicationHandler.registerAdditionalBinders(binders);
WebappContext webappContext = new WebappContext("Webapp context", "/resources");
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(
baseUri, applicationHandler);
for(NetworkListener listener : server.getListeners()){
listener.setCompression("on");
}
server.getServerConfiguration().addHttpHandler(
new StaticHttpHandler("/jersey2app/www"), "/static");
Any help will be greatly appreciated.
Turns out I just needed to add a couple of lines of code, but I'll post it here in case anyone else has the same problem.
ResourceConfig rc = new ResourceConfig();
rc.packages("com.danny.resources");
rc.registerInstances(new StatusModule(useFake), new NetworkModule(useFake));
GrizzlyHttpContainer resourceConfigContainer = ContainerFactory
.createContainer(GrizzlyHttpContainer.class, rc);
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri);
server.getServerConfiguration().addHttpHandler(resourceConfigContainer, "/");
The ResourceConfig lets you tell the server where to find your dynamic resources, in my case "com.danny.resources". It also allows you to register hk2 binders which will be used to inject those resources into your code.
Hope this helps someone along the way, and I hope hk2/Jersey 2.0 puts out some more examples!
I have a Restlet (2.0.10) application, I start with the following code:
public static void main(final String[] args) {
try {
// Create a new Component
final Component component = new Component();
// Add a new HTTP server listening on port 8182
component.getServers().add(Protocol.HTTP, SERVER_PORT);
// Add a client protocol connector for static files
component.getClients().add(Protocol.FILE);
// Attach the sample application.
component.getDefaultHost().attach("/myApp", new MyApplication(Context.getCurrent()));
// Start the component.
component.start();
} catch (Exception e) {
LOGGER.error(e);
}
}
Now I require the applications root (i.e. /myApp) inside the application and I try to get this according to Java accessing ServletContext from within restlet Resource:
Client serverDispatcher = context.getServerDispatcher();
ServletContext servletContext = (ServletContext)serverDispatcher.getContext().getAttributes()
.get("org.restlet.ext.servlet.ServletContext");
String contextPath = servletContext.getContextPath();
This works perfectly fine while deploying my application to a Tomcat Server, but as soon as I start the server using a Component as shown above, my Context is always null. Can someone please tell me how to get a properly initialized context using restlets internal server capabilities?
Seems logic.
You want a servlet context but you are not running in a servlet container, so the servlet context is NULL.
When doing component.start() you are using the Restlet connectors to server HTTP/HTTPS requests, not a servlet container like Tomcat.
You would need to pick up the context from the Component Class:
component.getDefaultHost().attach("/myApp",
new MyApplication(component.getContext().createChildContext());
That would just give you the Restlet context, but Servlet Context still won't be available since this is a standalone Java application.