wild card support in Embedded Jetty WebAppContext - java

I am looking for wild card support in Embedded Jetty WebAppContext contextPath but could not work out any.
I have following code for my shopping webapp:
String path = "/shopping";
WebAppContext wac = new WebAppContext(WEBAPP_PATH, path);
contexts.addHandler(wac);
I want that if access http://ip:port/shopping/anything, it should load my above webapp. But it does not. I also tried with path = "/shopping/*" and it did not work either.
Can anyone here please help me if it is possible or not or am I doing something wrong here.
EDIT:
I am deploying a webapp (flatten content) on Jetty and can access it successfully using http://host:port/shopping.
To achieve this, I created a WebAppContext(wac) with webappPath to resource folder and context-path as /shopping. I added this wac to handler list and attached it to server (Jetty Server).
Now, what I want is to access this webapp using http://host:port/shopping/. Whatever I provide after shopping in url, my same webapp should get loaded.
UPDATE:
Further following on this, I tried below but it did not work out.
ServletContextHandler context = new
ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/shopping");
ServletHolder staticHolder = new ServletHolder(new DefaultServlet());
staticHolder.setInitParameter("resourceBase", webAppPath);
staticHolder.setInitParameter("pathInfoOnly", "true");
context.addServlet(staticHolder, "/*");
context.setWelcomeFiles(new String[] { "index.html", "index.htm", "index.jsp" });
contexts.addHandler(context);
Now, if I try /shopping, it works but /shopping/abc does not. It seems wildcard matching is not working. If I use /home instead of /, /shopping/home works. Can anyone please help me here.
My requirement is to server weabAppPath for any /shopping/ url.

Finally, I got it working. Below will serve webapp for /shopping and /shopping/anything/* requests.
String path = "/shopping";
WebAppContext wac = new WebAppContext(WEBAPP_PATH, path);
contexts.addHandler(wac);
wac.addServlet(new ServletHolder(new WebappServlet()), "/anything/*");
public class WebappServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/index.html").forward(request, response);
}
}

Based on your short code snippet (really there's almost nothing to work with here), your WebAppContext has no servlets declared.
Nothing in that WebAppContext will be called to handle the incoming request.
A WebAppContext is assigned to a context-path, which has a syntax of /<path>, there is no wildcard support within a context-path.
What you are looking for is wildcard support in a url-pattern, which only exists for Servlets and Filters.
Do this, create a ShoppingAnythingServlet and set it to the url-pattern of /* and then you'll get all requests to that new Servlet.
From within that code, use the HttpServletRequest.getPathInfo() to obtain what that /anything is.

Related

How to get ServletFilter to work on welcome files in embedded Jetty?

I have an application running on embedded jetty 9.4.12. A ServletContextHandler object is used to set welcome files as well as add servlet filters before the handler is set to the Server object. The filter list being added includes certain filters that perform authentication on the incoming requests. However, these filters do not get fired on the welcome page, but they do work on the other endpoints.
Relevant Server initialization code:
ServletContextHandler root = new ServletContextHandler(ServletContextHandler.SESSIONS);
root.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");
root.setInitParameter("org.eclipse.jetty.servlet.Default.redirectWelcome", "true");
root.setWelcomeFiles(new String[]{"welcome.html"});
FilterHolder filterHolder = new FilterHolder(
new AuthFilter());
root.addFilter(filterHolder, "/*", null);
HandlerList handlerList = new HandlerList();
handlerList.setHandlers(
new Handler[]{root)
}
);
server.setHandler(handlerList);
Is there a way to get the AuthFilter servlet filter here to work on the welcome.html page?
The AuthFilter will execute for both requests in your configuration.
Example:
You issue a GET request to /path/to/content/
The matching servlet for this request is the DefaultServlet
The AuthFilter is called, then the DefaultServlet (assuming you allow the chaining to work)
The DefaultServlet detects that this is a directory request (and that dirAllowed is false), so it uses the welcome list and issues a redirect response (because you have redirectWelcome set to true). (This behavior assumes that /path/to/content/welcome.html actually exists, otherwise this is a 404 response)
302 Found HTTP/1.1
Location: /path/to/content/welcome.html
The client follows the redirect and issues a GET request to /path/to/content/welcome.html
The matching servlet for this request is the DefaultServlet
The AuthFilter is called, then the DefaultServlet (assuming you allow the chaining to work)
The DefaultServlet detects that this is a file resource and returns its contents.
Your AuthFilter was called twice, once for step 3 and again for step 7.

multiple servlet in jetty

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.

Using rest Servlet in Camel with Guice and Undertow

I'm setting up and application using Undertow, I've set up a ResourceHandler for static files, and Servlet to be used by apache-camel to expose rest services.
I've done this using spring and servlet3.0 in an app container.
In a class extending org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer
#Override
public void onStartup(ServletContext servletContext) throws ServletException
{
super.onStartup(servletContext);
ServletRegistration.Dynamic servlet = servletContext.addServlet("RestServlet", new CamelHttpTransportServlet());
servlet.setLoadOnStartup(1);
servlet.addMapping("/rest/*");
}
And in camel route
restConfiguration()
.component("RestServlet")
.bindingMode(RestBindingMode.json)
.dataFormatProperty("prettyPrint", "true");
Pretty close to whats described in http://camel.apache.org/servlet.html
But if I do this in Undertow as an embedded I get org.apache.camel.NoSuchBeanException: No bean could be found in the registry for: RestServlet of type: org.apache.camel.spi.RestConsumerFactory as I guess Guice never finds the servlets created by Undertow. I tried to manually expose the CamelHttpTransportServlet as a Guice Binding but that doesn't seem to change things.
ClassLoader classLoader = getClass().getClassLoader();
ResourceHandler staticHandler = new ResourceHandler(new ClassPathResourceManager(classLoader, STATIC_RESOURCE_ROOT))
.addWelcomeFiles(INDEX_HTML);
DeploymentInfo deploymentInfo = Servlets.deployment()
.setClassLoader(classLoader)
.setContextPath(ROOT_MAPPING)
.setDeploymentName(DEPLOYMENT_NAME)
.addServlet(
Servlets.servlet("RestServlet", CamelHttpTransportServlet.class)
.addMapping(REST_MAPPING)
.setLoadOnStartup(1)
);
DeploymentManager manager = Servlets.defaultContainer().addDeployment(deploymentInfo);
manager.deploy();
PathHandler path = Handlers.path()
.addPrefixPath(REST_MAPPING, manager.start())
.addPrefixPath(ROOT_MAPPING, staticHandler);
undertow = Undertow.builder()
.addHttpListener(port, LOCALHOST)
.setHandler(path)
.build();
undertow.start();
The static resource work as expected, and it also seems the rest servlet is running and getting the responses but CamelContext won't start up.
I can't use restlet or anything in camel as then the port will be in use so I need to use different port for static files and rest.
Is there any way to have camel identify the Servlet initiated by Undertow?
Ok I finally found out where it went wrong.
I suspect I always used .component("servlet") and not .component("RestServlet"), but Camel wouldn't link this automatically before.
I changed this section to
restConfiguration()
.bindingMode(RestBindingMode.json)
.component("servlet")
.dataFormatProperty("prettyPrint", "true")
.endpointProperty("servletName", "RestServlet);
And the deployment I changed the servlets mapping to /* or else request.getPathInfo() would return null inside CamelHttpTransportServlet.
NB I encountered a problem beause I initially set contextPath to /rest/* which messed up sessions and cookies
DeploymentInfo deploymentInfo = Servlets.deployment()
.setClassLoader(classLoader)
.setContextPath("/rest/")
.setDeploymentName(DEPLOYMENT_NAME)
.addServlet(
Servlets.servlet("RestServlet", CamelHttpTransportServlet.class)
.addMapping("/*")
.setLoadOnStartup(1)
);

Grizzly Server with static content and REST resource

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.

Context of RESTlet Application is null using internal RESTlet Server

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.

Categories

Resources