Disable #Webservice loading during start up - java

How to disable #Webservice loading during start up to save some loading time in xfire?
I have a bunch of services with #Webservice annotation. They are all being loaded during the startup and causing a slow startup. I don't want to load these if I test non-services in dev instance. I am wondering if there is a way to disable this by setting system property or something .

Sure, in your web.xml, where you configure the xfire servlet:
<servlet>
<servlet-name>xfire</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>-1</load-on-startup>
</servlet>
A negative value for load-on-startup means the servlet is only initialized when the container 'feels like it', and for most containers, this means when the first request comes in.
From the servlet specification:
The load-on-startup element indicates that this servlet should be
loaded (instantiated and have its init() called) on the startup of the
web application. The optional contents of these element must be an
integer indicating the order in which the servlet should be loaded. If
the value is a negative integer, or the element is not present, the
container is free to load the servlet whenever it chooses. If the
value is a positive 128 integer or 0, the container must load and
initialize the servlet as the application is deployed. The container
must guarantee that servlets marked with lower integers are loaded
before servlets marked with higher integers. The container may choose
the order of loading of servlets with the same load-on-start-up value.
So consult the documentation for your web container to make sure this has the desired effect in your case.

Related

How can you determine which servlet matches a URL when inside a servlet filter?

I am running a Jetty web server and I have a generic servlet filter to handle exceptions. As part of this, I want to log aggregated metrics about which servlets are causing the exceptions. Is there a way I can figure out which servlets defined in the web.xml match the servlet path of the current request?
I have a generic servlet filter to handle exceptions
I take you to mean that your filter extends javax.servlet.GenericFilter directly.
Is there a way I can figure out which servlets defined in the web.xml match the servlet path of the current request?
In any given servlet context there should not be more than one servlet mapped to a given servlet path, so in any given case you're looking for just one servlet, not multiple.
As far as I know or can tell, GenericFilter and the generic ServletRequests and ServletResponses with which it works do not provide a good way to access the information you are after. If you cast the request to HttpServletRequest, however, then you can obtain its HttpServletMapping (since Servlet 4.0 / Java EE 8)
, which contains the servlet name as declared in the webapp's deployment descriptor, among other information. Or the HttpServletRequest can directly provide the servlet path, too.
But if you are contemplating casting the requests, then you would probably be better off having your filter extend javax.servlet.http.HttpFilter, which would give you type-safe access. This is itself a subclass of GenericFilter, so it probably wouldn't be difficult to perform such a refactoring.

How to make a servlet handle all URLs except JSPs [duplicate]

The familiar code:
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
My understanding is that /* maps to http://host:port/context/*.
How about /? It sure doesn't map to http://host:port/context root only. In fact, it will accept http://host:port/context/hello, but reject http://host:port/context/hello.jsp.
Can anyone explain how is http://host:port/context/hello mapped?
<url-pattern>/*</url-pattern>
The /* on a servlet overrides all other servlets, including all servlets provided by the servletcontainer such as the default servlet and the JSP servlet. Whatever request you fire, it will end up in that servlet. This is thus a bad URL pattern for servlets. Usually, you'd like to use /* on a Filter only. It is able to let the request continue to any of the servlets listening on a more specific URL pattern by calling FilterChain#doFilter().
<url-pattern>/</url-pattern>
The / doesn't override any other servlet. It only replaces the servletcontainer's built in default servlet for all requests which doesn't match any other registered servlet. This is normally only invoked on static resources (CSS/JS/image/etc) and directory listings. The servletcontainer's built in default servlet is also capable of dealing with HTTP cache requests, media (audio/video) streaming and file download resumes. Usually, you don't want to override the default servlet as you would otherwise have to take care of all its tasks, which is not exactly trivial (JSF utility library OmniFaces has an open source example). This is thus also a bad URL pattern for servlets. As to why JSP pages doesn't hit this servlet, it's because the servletcontainer's built in JSP servlet will be invoked, which is already by default mapped on the more specific URL pattern *.jsp.
<url-pattern></url-pattern>
Then there's also the empty string URL pattern . This will be invoked when the context root is requested. This is different from the <welcome-file> approach that it isn't invoked when any subfolder is requested. This is most likely the URL pattern you're actually looking for in case you want a "home page servlet". I only have to admit that I'd intuitively expect the empty string URL pattern and the slash URL pattern / be defined exactly the other way round, so I can understand that a lot of starters got confused on this. But it is what it is.
Front Controller
In case you actually intend to have a front controller servlet, then you'd best map it on a more specific URL pattern like *.html, *.do, /pages/*, /app/*, etc. You can hide away the front controller URL pattern and cover static resources on a common URL pattern like /resources/*, /static/*, etc with help of a servlet filter. See also How to prevent static resources from being handled by front controller servlet which is mapped on /*. Noted should be that Spring MVC has a built in static resource servlet, so that's why you could map its front controller on / if you configure a common URL pattern for static resources in Spring. See also How to handle static content in Spring MVC?
I'd like to supplement BalusC's answer with the mapping rules and an example.
Mapping rules from Servlet 2.5 specification:
Map exact URL
Map wildcard paths
Map extensions
Map to the default servlet
In our example, there're three servlets. / is the default servlet installed by us. Tomcat installs two servlets to serve jsp and jspx. So to map http://host:port/context/hello
No exact URL servlets installed, next.
No wildcard paths servlets installed, next.
Doesn't match any extensions, next.
Map to the default servlet, return.
To map http://host:port/context/hello.jsp
No exact URL servlets installed, next.
No wildcard paths servlets installed, next.
Found extension servlet, return.
Perhaps you need to know how urls are mapped too, since I suffered 404 for hours. There are two kinds of handlers handling requests. BeanNameUrlHandlerMapping and SimpleUrlHandlerMapping. When we defined a servlet-mapping, we are using SimpleUrlHandlerMapping. One thing we need to know is these two handlers share a common property called alwaysUseFullPath which defaults to false.
false here means Spring will not use the full path to mapp a url to a controller. What does it mean? It means when you define a servlet-mapping:
<servlet-mapping>
<servlet-name>viewServlet</servlet-name>
<url-pattern>/perfix/*</url-pattern>
</servlet-mapping>
the handler will actually use the * part to find the controller. For example, the following controller will face a 404 error when you request it using /perfix/api/feature/doSomething
#Controller()
#RequestMapping("/perfix/api/feature")
public class MyController {
#RequestMapping(value = "/doSomething", method = RequestMethod.GET)
#ResponseBody
public String doSomething(HttpServletRequest request) {
....
}
}
It is a perfect match, right? But why 404. As mentioned before, default value of alwaysUseFullPath is false, which means in your request, only /api/feature/doSomething is used to find a corresponding Controller, but there is no Controller cares about that path. You need to either change your url to /perfix/perfix/api/feature/doSomething or remove perfix from MyController base #RequestingMapping.
I think Candy's answer is mostly correct. There is one small part I think otherwise.
To map host:port/context/hello.jsp
No exact URL servlets installed, next.
Found wildcard paths servlets, return.
I believe that why "/*" does not match host:port/context/hello because it treats "/hello" as a path instead of a file (since it does not have an extension).
The essential difference between /* and / is that a servlet with mapping /* will be selected before any servlet with an extension mapping (like *.html), while a servlet with mapping / will be selected only after extension mappings are considered (and will be used for any request which doesn't match anything else---it is the "default servlet").
In particular, a /* mapping will always be selected before a / mapping. Having either prevents any requests from reaching the container's own default servlet.
Either will be selected only after servlet mappings which are exact matches (like /foo/bar) and those which are path mappings longer than /* (like /foo/*). Note that the empty string mapping is an exact match for the context root (http://host:port/context/).
See Chapter 12 of the Java Servlet Specification, available in version 3.1 at http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html.

Global Web Application Parameter

I'm trying to set a parameter that's not allocated to a specific servlet but rather available globally throughout the web application. My current code gets the following as null:
<context-param>
<param-name>example</param-name>
<param-value>This is an example parameter value</param-value>
</context-param>
and
getServletConfig().getInitParameter("example");
Figured it out. Just had to change:
getServletConfig().getInitParameter("example");
to:
getServletContext().getInitParameter("example");

Difference between session.getServletContext() and session.getServletContext().getContext("/SampleProject")

I have a Tomcat 6 instance running on my local machine.
I have made the following changes in its configuration:
In /conf/context.xml – changed the tag as follows
<Context crossContext="true">
In /conf/server.xml – changed the tag as follows
<Connector port="8080" protocol="HTTP/1.1" emptySessionPath="true"
connectionTimeout="20000"
redirectPort="8443" />
Suppose I have a WAR file named SampleProject.war deployed here which extract to folder SampleProject.
In some servlet in this WAR, say SampleServlet, I write two blocks of code as follows :
ServletContext context1 = session.getServletContext();
and
ServletContext context2 = session.getServletContext().getContext("/SampleProject");
What is the difference between context1 and context2? I thought that both refer to the application context. But if I set some attribute in context1 and access in context2, I don't get the value in context2.
Any help would be appreciated.
I feel your question was slightly misunderstood and that you already had the basic understanding of the API i.e. once a web-app sets its crossContext="true" it could use getContext() to get access to a context that corresponds to some other web-app deployed on the server.
getServletContext().getContext() equals NULL unless <Context crossContext="true">
From what I've understood, your question actually is that in /SameWebApp why
ServletContext context1 = session.getServletContext();
context1.setAttribute("contextAttribute", new Object());
ServletContext context2 = session.getServletContext().getContext("/SameWebApp");
System.out.println(context1.equals(context2)); // prints false, or
System.out.println(context2.getAttribute("contextAttribute")); // prints null (at least they could have been clones)
In just one word, the answer is "Security". Imagine if you couldn't guarantee that an "adminEmail" context attribute has not been tampered with by an evil web-app having its crossContext=true. Your app could potentially help compromise itself as soon as that "Forgot Password" request comes! :)
A Dive into Tomcat internals
Tomcat 7 provides a class ApplicationContext implements ServletContext that returns from getContext("/context-root") as
if (context.getCrossContext()) {
// If crossContext is enabled, can always return the context
return child.getServletContext();
} else if (child == context) {
// Can still return the current context
return context.getServletContext();
} else {
// Nothing to return
return (null);
}
Here context belongs to current web-app and child represents the other web-app. But, hold on, what makes Tomcat call it a child?
These two actually aren't ApplicationContext but instances of StandardContext a class that implements Context but instead of servlet specific things holds Tomcat specific config settings for a web-app like crossContext, hostname, mimeMappings etc. StandardContext.getParent() gives you the Container and hence it has been referred to as a child above.
Anyways, we're interested in the case when child == context is true i.e. getContext() was called on the "/SameWebApp". The call is being delegated to StandardContext.getServletContext() which has been implemented to return a different instance of ApplicationContext.
This is why the attributes you set in context1 are not found in context2.
But wait, there's some more to it. Why does StandardContext.getServletContext() return like
return (context.getFacade());
A Tomcat instance is basically executing two types of Java code:
container provided, and
user deployed
The container code is "Trusted" and may need to run with elevated privileges sometimes. The user code, on the other hand, is not trusted and needs to be restricted from compromising Tomcat internals.
One of the things that Tomcat does to achieve this is always wrap an ApplicationContextFacade around the ApplicationContext (and hence the StandardContext as well). So just to recap, what appears to be a simple ServletContext implementation is actually a StandardContext mapped to an ApplicationContext which is then wrapped within an ApplicationContextFacade.
For further information on how the ApplicationContextFacade works using Reflection in tandem with Globals.IS_SECURITY_ENABLED and SecurityUtil.isPackageProtectionEnabled() settings please take a look at Why do Servlets access Tomcat ApplicationContext through a Facade on SO.
References:
Tomcat 7 Source Code (Download Link)
Absolutely those two context objects are different from another..
Context1 object gives current web application servlet context obj.
( ServletContext context1 = session.getServletContext();)
and
context2 object gives the servletcontext obj of specified web application
(ServletContext context2 = session.getServletContext().getContext("/SampleProject");)
you are setting object in one context and trying to retrieve using another context, so it is not possible to get attribute from another web application context by putting it in current application context. But you can get attribute resides in another web application context by using second method.
Think OO & java EE platform standards + security.
The first call returns the definitive servlet context for the current app, with all operations supported.
The second call returns a copy of the servlet context that could be for any app. As stated (rather vaguely!) in the javadoc, it's purpose is to allow you to obtain a RequestDispatcher, so you can dispatch to pages of other apps. It's other major but implicit requirement is to do this securely and to respect the Java EE specs, which do not allow sharing of session state or servlet context between apps. Imagine the terrible damage "rogue App B" could do to "good App A" if it could just change (or read) Servlet Context data by brute force. That's why it's a copy.
Hence, setting attributes on the copy, does not result in changes to the original. You could argue that the copy should throw some "Operation Not Supported Exception". Alternatively, you could argue that getRequestDispatcher should be refactored either to another class, or to allow an App Context URL to be passed in. ... But, unfortunately, neither of these things are true. B^)

FacesServlet and URL Mapping in Web.xml

HI,
We are declaring the FacesServlet and its URL mapping in the Web.xml. From my understanding,
FacesServlet loaded only once at the server startup.
URL mapping is used only when first time JSP application accessed from the external context.
One of the new learner for JSF has asked me the questions, these two things are used only once by the application. Is it true? Also is there any other way by not including in the web.xml?
What I should answer?
Updated
For example, I am accessing the application using the URL http://localhost:8080/webapp/index.jsf. When we are accessing this URL, FacesServlet invoked and view is rendered. The following is my question:
In JSF, we never seen changing the URL in the address bar. In that case, how it is handling the new request with the same URL?
In faces-config.xml we are giving the navigation cases as follows:
to-view-id>failure.jsp /to-view-id>
Why we need not give the view name as failure.jsf? We are just giving the *.jsp in the faces-config.xml. How it is handled internally?
FacesServlet loaded only once at the server startup.
Correct.
URL mapping is used only when first time JSP application accessed from the external context.
Incorrect. It's been tested on every incoming HttpServletRequest. How else should the container know which servlet to invoke?
Also is there any other way by not including in the web.xml?
If you're using a servletcontainer which supports Servlet 3.0, you can also do this by #WebServlet annotation. JSF 2.0, however, is designed to be backwards compatible with Servlet 2.5, so it doesn't ship with that annotation and you need to explicitly declare it in web.xml.
See also:
Servlets tag info page
Lifecycle of a JSP/Servlet webapplication
How servlets are initialized and used
Update as per the new series of questions (which should each belong in its own question, but ala)
In JSF, we never seen changing the URL in the address bar. In that case, how it is handling the new request with the same URL?
This happens only if under the covers a forward by RequestDispatcher#forward() takes place. In a forward, the servletcontainer basically reuses the same HTTP request/response for a view (JSP/XHTML page). It does not force/instruct the webbrowser to send a brand new request. On the other hand, the HttpServletResponse#sendRedirect() will instruct the client (the webbrowser) to fire a new GET request and thus the URL will change. You can force this in the JSF sice by adding <redirect/> to the <navigation-case>. Note that since this causes a new request, all request scoped beans of the initial request will be lost.
Why we need not give the view name as failure.jsf? We are just giving the *.jsp in the faces-config.xml. How it is handled internally?
The FacesServlet knows its own url-pattern.
Yes. while loading your application container will load web.xml and will extract the data for
particular URL pattern to servlet . when request comes it checks from memory that for this pattern which servlet to invoke and then if servlet is already loaded it will take it from memory otherwise it will create an instance of servlet and it will invoke doGet() or doPost() depending on the request type.
and there is another way to delcare URL mapping as from JAVAEE-6 by annotation
something like
import javax.servlet.annotation.InitParam;
import javax.servlet.annotation.WebServlet;
#WebServlet(
name = "SimpleServlet",
urlPatterns = {"/login"},
initParams = {
#InitParam(name = "param1", value = "value1"),
#InitParam(name = "param2", value = "value2")}
)
public class SimpleServlet {
}
In faces-config.xml we are giving the navigation cases as follows:
<to-view-id>failure.jsp </to-view-id>
Why we need not give the view name as failure.jsf? We are just giving the *.jsp in the faces-config.xml. How it is handled internally?
it is view identifier not the URL FacesServlet will load that view upon invocation of that navigation case.

Categories