In my web application I have two servlets which act as a controller. One servlet is used to handle web requests and another servlet is used to handle AJAX requests.
//This servlet manages web requests, and forwards to JSP to display data
WebController extends HttpServlet:
// This servlet manages AJAX requests. And returns JSON to user
AJAXController extends HttpServlet: This servlet manages
In my web.xml I have the following mapping defined:
<servlet>
<servlet-name>WebController</servlet-name>
<servlet-class>com.frontend.WebController</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>WebController</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>AJAXController</servlet-name>
<servlet-class>com.AJAXController</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AJAXController</servlet-name>
<url-pattern>*.xhr</url-pattern>
</servlet-mapping>
So you can see I load WebController before AJAXController.
In the init() method of webController, I do all the initialization tasks.
loading the database driver
initializing the configuration
and other stuff that I need for my web application
The load-on-startup makes sure that before any AJAX request come to the server, the web app is initialized and I can be sure to make database access.
However, I do not like the idea of initializing web application in one servlet. I am thinking of having a separate servlet called InitServlet and move the code from WebController's init method to InitServlet's init() method
Questions
Is it a good idea? Are there other approaches to solve this problem?
What should my servlet-mapping look like given that init servlet's sole purpose is to initialize the web application and as such it should not be mapped to any URL
I will send HttpServletResponse.SC_FORBIDDEN in their doPost() and doGet() method. But if possible I want ths servlet not to be mapped to anything.
It's a better idea to move your initialize code to ServletContextListener.
When your app starts it will execute contextInitialized(ServletContextEvent sce) and you'll get a chance to init everything.
And this is how you hook it to your web.xml
I think it is not necessarily a bad idea. Just define your initialization server to load first in the web.xml. As far as the entry goes, it needs to define the servlet class, of course and the load on startup order.
Put your initialization code in an implemented init method. Leave the doGet doPost methods empty so if they get called nothing happens. The init method will only get called once when the servlet is loaded.
The only issues I see is if this is being run into the context of a clustered set of application servers and you have resources that are truly singleton (like a connection pool), but in that case you can initialize these through application configuration in the application server. They will get intialized when the application starts and before the servlets are loaded.
Related
I have a standard Java 11 Web application, with multiple servlets in it. Some servlets are imported by libraries, others are written within the application itself.
I need to perform a task AFTER all web servlets have been initialized, preferably before any requests come in. The task requires access to ServletContext.
I have tried performing this by creating a ServletContextListener and it's corresponding contextInitialized method, but this performs the task BEFORE the servlets have been initialized.
I cannot add the task to the last servlet to load, as the last servlet loaded is imported from an external library.
It would be preferable if the solution does not involve creating a servlet with no mapping.
If you have access to your deployment descriptor (web.xml) and the servlets are eager loaded, then you could append your servlet in the servlet list and set a high number in load-on-startup element.
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>com.project.LastServlet</servlet-class>
<load-on-startup>99</load-on-startup>
</servlet>
I tried to find a workaround in the documentation, but I couldn't find it and the ServletContextListener is a no go:
"All ServletContextListeners are notified of context initialization before any filters or servlets in the web application are initialized."
MVC - JSP + Servlets, TomEE, MySQL, Eclipse
I know how to put something to application scope in servlet, and forward request to some jsp page, where I read data from some of scopes(request, session, aplication). But, I would like to have certain object in application scope (Servlet Context) when I load my application.
In web.xml I have specified application entry point:
<welcome-file-list>
<welcome-file>/home.jsp</welcome-file>
</welcome-file-list>
I would like to have some data in application scope, because I am creating menu items from that data.
So, when app starts, no servlet has been processed yet, app goes straight to home.jsp, so there is nothing attached to any scope. Or situation when user have bookmarked some of other application jsp pages, and goes straight there.
You can use a ServletContextListener
Interface for receiving notification events about ServletContext
lifecycle changes.
You implement its contextInitialized(ServletContextEvent) method giving you access to the ServletContext through the ServletContextEvent. You can then add any attribute to it and reference that attribute in the jsp.
Obviously you'll have to register the ServletContextListener with the <listener> element in your deployment descriptor
<listener>
com.yourcomp.listeners.YourListener
</listener>
The container will take care of initializing this class and invoking its contextInitialized() method when the web application starts up.
I have written a simple servlet with init() and doGet(), doPost() method. I have a requirement, that I have an API which i need to invoke an server startup.
Is it possible to do so. I tried with init method, and setting default values in web.xml, but i am still unable to do so.
Please tell if I am missing something.
Thanks
Have you set the load-on-startup attribute to be positive?
<servlet id=”servlet1”>
<load-on-startup>2</load-on-startup>
</servlet>
Alternatively, you might want to use a ServletContextListener to do initialisation work when the container comes up. This is the 'de facto' standard for having a callback to do some initialisation work when the servlet container comes online e.g. we use that to read in some XML files and populate a cache.
Use a listener class to invoke a method. For e.g....Define a listener in web.xml file. and give a class name in the listener. And now create a servlet class or java class to write a code to invoke the API.
<web-app>
<listener>
<listener-class>MyServlet</listener-class>
</listener>
</web-app>
hope this helps out.
I have a tomcat 7 application which I can get requests from external sources.
Most of them call my request like this:
http://localhost:8080/MyWeb/exRequest
and I build servlet with URL pattern inside MyWeb app.
However, one external source must send the request like this:
http://localhost:8080/
and in the body:
<xml name="test" />
Since I don't want to declare a general servlel (like tomcat default) since it means that any request will need to go through my servlet, I thought to change index.jsp of ROOT to redirect to my servlet.
Is it the best option?
Is there an option to create a default servlet that will be invoked only if there is a special parameter in the body?
EDITED
Please note that I get the requests to localhost:8080 and not localhost:8080/MyWeb - it's general to tomcat and not to a specific web app
You can't choose a servlet to invoke based on the request body, but you can set a servlet as the "welcome-file" in your web.xml.
<servlet>
<servlet-name>index</servlet-name>
<servlet-class>com.y.MyWelcomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>index</servlet-name>
<url-pattern>/index</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index</welcome-file>
</welcome-file-list>
If you want to preserve the "welcome" function of some existing index.jsp, your servlet could forward requests without the correct XML in the body to an index.jsp file located under the WEB-INF directory.
No, but you can create a Filter and forward/redirect to a specific servlet whenever the request meets certain conditions.
If using servlet 3.0 map it with #WebFilter, otherwise use web.xml and <filter> + <filter-mapping>. You should map it be executed before the default servlet.
I'm trying to use the restlet.org library to build a RESTful web interface, and I've noticed that unlike it's servlet counterpart, it has no complement to GenericServlet.init().
Short of building another servlet to do my startup logic, is there any built-in way to avoid building my database factories and the like on the first request (and all the commensurate locking I'll have to do to avoid multiple initializations)?
Are you wanting to run it in a servlet container? If not, the documentation shows you how to run it stand-alone:
public static void main(String[] args) throws Exception {
// Create a new Component.
Component component = new Component();
// Add a new HTTP server listening on port 8182.
component.getServers().add(Protocol.HTTP, 8182);
// Attach the sample application.
component.getDefaultHost().attach("/firstSteps",
new FirstStepsApplication());
// Start the component.
component.start();
}
You could certainly do the initialization there.
If you want to use the servlet approach, try writing a new servlet and extending theirs. Implement your init method and call the one for the super class.
If you really want to do this in a servlet environment, you could potentially have two servlets within your webapp: one for the Restlet application/component and one for your initialization, using load-on-startup (which you wouldn't necessarily map to any URL, as far as I'm aware you don't have to). This way, you wouldn't have to subclass org.restlet.ext.servlet.ServerServlet. I think this is probably easier, since that init servlet would just contain init(), but this would only work for things that do not depend on the Restlet app/component to be initialized first.
<context-param>
<param-name>org.restlet.clients</param-name>
<param-value>HTTP HTTPS CLAP FILE</param-value>
</context-param>
<servlet>
<servlet-name>ExampleInit</servlet-name>
<servlet-class>example.TestInitServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>Example</servlet-name>
<servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
<init-param>
<param-name>org.restlet.application</param-name>
<param-value>example.TestApplication</param-value>
</init-param>
<init-param>
<param-name>org.restlet.autoWire</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Example</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Alternatively (or perhaps in complement to this), I tend to use JNDI for initializing the database connections and a few other configuration settings. This also allows me to keep the same configuration and loading mechanisms, whether I use a Restlet standalone server or Restlet within a webapp.
For example, for deployment within a servlet container (e.g. Jetty or Tomcat), I use the container's JNDI configuration, but for local tests (with a standalone Restlet app), I use the Jetty JNDI context factory (which you can get as a separate jar from the rest of Jetty).