Confused with load-on-startup value - servlets

When we mention any servlet as loadOnStartup in web.xml then its init method is called at applicaton startup.
<web-app xmlns="http://java.sun.com/xml/ns/javaee"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd     version="3.0">       
<servlet>         
<servlet-name>SimpleServlet</servlet-name>         
<servlet-class>app01c.SimpleServlet</servlet-class>         
<load-on-startup>10</load-on-startup>     
</servlet>      
 <servlet-mapping>         
<servlet-name>SimpleServlet</servlet-name>         
<url-pattern>/simple</url-pattern>     
</servlet-mapping>        
</web-app>
<load-on-startup>10</load-on-startup>
here, what does it mean for the value 10? if i change it to
5, what will happen? having less value will make it to load earlier? if so, if it is 0, is it the earliest? i am little confused with as i came across some googling that positive value in load-on-startup, make it to load at start up.
Does this positive is greater than than 0? Does 0 value is same as nothing in load-on-startup?

0 is the highest priority.
If you have only one servlet you can not see the difference
ServletName load-on-start-up_value
Servlet1 4(3)
Servlet2 6(4)
Servlet3 3(2)
Servlet4 2(1)
Servlet4 object will be created first then Servlet3 object will be created and then Servlet1 and Servlet2 objects will be created.
If you give -1 it will be ignored

By default, servlet object is created when you make the first request to servlet, but if you want to create the servlet object at the load time(or start up time), then you can provide <load-on-startup></load-on-startup> value in web.xml.
<load-on-startup></load-on-startup> is servlet wise. If there are 2 servlets in your application so you need to provide <load-on-startup></load-on-startup> value for each servlet.
<load-on-startup></load-on-startup> value either 0 or any positive integer. If you are putting <load-on-startup>10</load-on-startup> value 10, and you have only single servlet then it will not affect any thing, but you have more then 1 servlet then 0 value is highest priority and then so on.

Related

URL pattern servlet mapping

I created hello world example using Spring MVC, but there is one thing I didn't understand in servlet URL mapping, I did the following in web.xml:
<servlet>
<servlet-name>HelloWeb</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloWeb</servlet-name>
<url-pattern>/test/*</url-pattern>
</servlet-mapping>
now if I want to call the following controller:
#Controller
#RequestMapping("/hello")
public class HelloWorld {
#RequestMapping(method = RequestMethod.GET)
public String printWelcome(ModelMap model){
model.addAttribute("message","hello world");
return "index";
}
}
it will work using the following link:
http://localhost:8080/test/hello
but when I change the servlet url-pattern to "/*" and try:
http://localhost:8080/hello
it doesn't work, shouldn't it match my servlet ? as * matches everything
When you register a servlet with "/*" then it will override all the servlet mappings if there are any. Hence it should be avoided. This overrides default servlet mapping as well hence all default url handling also overridden and hence any specific url matching fails. In your case it is /hello.
With your case, initially you registered with /test/* this registered all your URL's with /test and hence they got identified.
It doesn't work for /* because, you have not registered/created a controller for that pattern.
It worked for http://localhost:8080/hello because, you have controller #RequestMapping("/hello")
Just change the RequestMapping to #RequestMapping("/") for url-pattern /*

#SessionScoped CDI bean is a different Instance when injected

My config is a bean that I inject in my code wherever I need it. However, when injected, I get a new instance of the bean instead of the one from the session.
My bean:
#Named
#SessionScoped
public class TestModel implements Serializable {
private static final long serialVersionUID = 4873651498076344849L;
private String version;
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public void changeVersion() {
this.version = "Version 2";
System.out.println("New version : " + version + ", Object : " + this);
}
}
When injected in different classes, all occurences are different instances.
When annotating the bean with #ApplicationScoped, it is the same instance.
I do need the bean to be #SessionScoped since every user should have his own config.
The WebApp is running on TomEE 1.7.4
UPDATE: I created a new project to test it, and the SessionScope works. I now need to find out what is wrong with my current project in order to fix it.
Facets:
CDI 1.0
Dynamic Web Module 3.0
Java 1.8
JSF 2.2 (MyFaces impl from TomEE)
JPA 2.1
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>Project</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>omega</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>
faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
</faces-config>
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="annotated">
</beans>
Any ideas ?
Looks like your test doesn't work:
testModel object = model.TestModel#689a6064
New version : Version 2, Object : model.TestModel#61606aa6
So you update an instance which is not the same as the one linked to the session (another request not reusing the same session I'd say)
You are doing it right. That is, from CDI perspective, you made no mistake and what you want is perfectly legit and should work (assuming you solved the problem of multiple sessions, which you did).
I just tried this with my own piece of code and it works as expected. You can check it on GitHub. The sample is more or less identical to yours.
However, I am running Wildfly 10 and therefore Weld 2.3 which comes with it (Weld being a reference impl of CDI). While you are running TomEE which contains OpenWebBeans (another CDI implementation).
To me it seems like you either missed some TomEE/OWB specific configuration (unrealistic scenario) or, more likely, you found a bug. In any case, if I were you, I would try asking on their forums or creating an issue in their tracking system because, once again, there is imho nothing wrong with your bean/servlet setup.
We have #SessionScope annotation in both JSF & CDI. Please review whether the annotation you are using in your old project is from JSF or from CDI.
Find more on the difference between the annotation from JSF & CDI

Log4j2 web look up cannot access servletcontext attribute

We are using Tomcat 7.0.54.
The web.xml:
<context-param>
<param-name>log4jContextName</param-name>
<param-value>SabaLog4jContext</param-value>
</context-param>
There is sample servlet which starts on load
<servlet>
<servlet-name>startUp</servlet-name>
<servlet-class>foo.StartupServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
The StartupServlet simple as:
public class StartupServlet extends HttpServlet {
#Override
public void init() throws ServletException {
getServletContext().setAttribute("test", "ATest");
super.init();
}
}
The log4j2 can not access the test attribute with ${web:attr.test} and I got the warning as:
INFO: org.apache.logging.log4j.web.WebLookup unable to resolve key 'test'
It seems that Log4j2 works fine but the problem is that it starts before my Startup. I tried to use a servletContextListener class but no luck.
I also tried to disable Log4jAutoInitialization in web.xml and manually start set them as below.
<listener>
<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>
<filter>
<filter-name>log4jServletFilter</filter-name>
<filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>log4jServletFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
But no luck:(
The log4j2.xml is as below:
<property name="baseFolder">${web:rootDir}/../logs/${web:test}</property>
So how can setup my web.xml so that my code execute before Log4j context.
The web.xml also contains spring Listeners as:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
First, make sure Tomcat is configured to provide the functionality of a servlet 3.0 container in your web.xml file:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
You'll want the 3.0 functionality so you can specify the order in which the servlets are loaded. Then you'll want to have your own ServletContainerInitializer to initialize the ServletContext attributes. Here's an snippet of one of mine:
/* Initializer that is configured, via web.xml, to initialize before Log4j2's initializer. This gives us the
* opportunity to set some servlet context attributes that Log4j2 will use when it eventually initializes.
*/
public class BitColdHardCashContainerInitializer implements ServletContainerInitializer {
#Override
public void onStartup(final Set<Class<?>> classes, final ServletContext servletContext) throws ServletException {
if (servletContext.getMajorVersion() > 2) {
servletContext.log("BitColdHardCashContainerInitializer starting up in Servlet 3.0+ environment.");
}
// Set the webapp.name attribute so that Log4j2 may use it to create a path for log files.
servletContext.setAttribute("webapp.name", servletContext.getContextPath().replaceAll("/", "").trim());
Next, you want your ServerContainerInitializer to run before Log4j2's. In your web.xml, give your servlet a name:
<absolute-ordering>
<name>BitColdHardCash</name>
<others/>
</absolute-ordering>
This needs to be be specified before the <servlet> element.
Create a web-fragment.xml file:
<web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
version="3.0" metadata-complete="true">
<name>BitColdHardCash</name>
<distributable />
<ordering>
<before>
<others />
</before>
</ordering>
</web-fragment>
This tells Tomcat to initialize your ServletContainerInitializer first, before anything else, including Log4j2's. This goes in the META-INF directory.
That should do it. One more thing to check would be your catalina.properties file. You are using a version of Tomcat that fixes a bug regarding the calling of ServletContextInitializers. I'm not sure if the bug was in Tomcat source code or in the default supplied catalina.properties file. In the event you are using a catalina.properties file that pre-dates the fix, just crack it open an ensure that log4j*.jar is not included in the list of files specified for the tomcat.util.scan.DefaultJarScanner.jarsToSkip property.

Servlet url pattern - java.lang.NullPointerException in servlet Context

my servlet performs three tasks:
When it receives a message "resourceupdate" stores the requested resource (an HTML page) to an object sharedClient.
When it receives an asynchronous get (querystring indicated by "t = UPDATE") adds the object sharedClient this request pending.
When it receives a delivery_resource (indicated by pathinfo myServlet/sharedsessionID - eg. myServlet/8439jfndofsd93jcanjc) performs the dispatch of the resource.
this is my Web.xml:
<servlet>
<description></description>
<display-name>MyServlet</display-name>
<servlet-name>MyServlet</servlet-name>
<servlet-class>it.package.MyServlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet/*</url-pattern>
</servlet-mapping>
I keep all the active SharedClients in this way:
ConcurrentHashMap<String, SharedClient> hmClients = (ConcurrentHashMap<String, SharedClient>) this.getServletConfig().getServletContext().getAttribute("sharedClients");
And I get the SharedClient with a specific SharedSessionID in this way:
SharedClient targetClient = hmClients.get(ssid);
now the problem:
until I do a resourceupdate servlet works fine, but when i do a delivery_resource (to a path of type myServlet/sharedsessionID) the servlet is unable to obtain the sharedClient reference, and I get a Null Pointer Exception.
if (resourceUri!=null) {
String ssid = resourceUri.substring(1);
ConcurrentHashMap<String, SharedClient> hmClients = (ConcurrentHashMap<String, SharedClient>) this.getServletConfig().getServletContext().getAttribute("sharedClients");
if (hmClients.containsKey(ssid)) {
SharedClient targetClient = hmClients.get(ssid);
if (targetClient.getParticipantSession().containsKey(session)) {
IoUtils.copy(targetClient.streamSnapshot(), response.getOutputStream());
}
} else System.out.println("hmClient do not contains ssid"); //always in this branch
From this time also the long polling with asynchronous get are not completed successfully.
If i do not do a delivery_resource to a path of type myServlet/sharedsessionID after the update the asynchronous get continue to function properly.
Thanks to all.
ok, i resolved.
i need to write
#WebServlet(urlPatterns = {"/myServlet/*"}, asyncSupported=true)
before myServlet declaration.

spring 3 uploadify giving 404 Error

I am using Spring 3 and implementing Uploadify. The problem is, the files are updating properly but it is giving HTTP Error 404, on completion of file upload. I tried every possible solution, but none of them works.
The files are uploaded. Values are storing in DB properly, only that i am getting HTTP Error 404. Any help is appreciated and Thanks in advance.
The Solution is :
Finally i found the solution but it is lame.
I removed the return "" and changed the method as void. Thats it.
But still i don't understand why the same code is working in Spring 2.5.6 and not in 3.
The URL of the screenshot : http://imgur.com/bf3qo
The JSP Page
$(function() {
$('#file_upload').uploadify({
'swf' : 'scripts/uploadify.swf',
'fileObjName' : 'the_file',
'fileTypeExts' : '*.gif; *.jpg; *.jpeg; *.png',
'multi' : true,
'uploader' : '/photo/savePhoto',
'fileSizeLimit' : '10MB',
'uploadLimit' : 50,
'onUploadStart' : function(file) {
$('#file_upload').uploadify('settings', 'formData', {'trip_id' :'1', 'trip_name' :'Sample Trip', 'destination_trip' :'Mumbai','user_id' :'1','email' :'s#s.com','city_id' :'12'});
},
'onQueueComplete' : function(queueData) {
console.log('queueData : '+queueData);
window.location.href = "trip/details/1";
}
});
});
The Controller
#RequestMapping(value="photo/{action}", method=RequestMethod.POST)
public String postHandler(#PathVariable("action") String action, HttpServletRequest request) {
if(action.equals("savePhoto"))
{
try{
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request;
MultipartFile file = multipartRequest.getFile("the_file");
String trip_id = request.getParameter("trip_id");
String trip_name = request.getParameter("trip_name");
String destination_trip = request.getParameter("destination_trip");
String user_id = request.getParameter("user_id");
String email = request.getParameter("email");
String city_id = request.getParameter("city_id");
photo.savePhoto(file,trip_id,trip_name,destination_trip,user_id,email,city_id);
photo.updatetrip(photo_id,trip_id);
}catch(Exception e ){e.printStackTrace();}
}
return "";
} **Solution** : Change the method return type as void and remove the return
spring config
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
<property name="maxUploadSize" value="10000000"/>
</bean>
Web.xml is
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>project_name</display-name>
<distributable/>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/project_name-servlet.xml,/WEB-INF/applicationContext-jdbc.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>project_name</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>project_name</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
maybe you simply haven't page trip/details/1 in your application?
EDIT:
Change window.location.href = "trip/details/1"; to
window.location.href = "<%= request.getContextPath() %>/trip/details/1";
The files are uploaded. Values are storing in DB properly, only that i
am getting HTTP Error 404.
What this tells me is that your request is properly being submitted to the URL at '/photo/*'
and is properly handled by the postHandler() method.
You're getting a 404 because your web application doesn't know what to do with the url of "" that the postHandler() method is trying to direct you to.
There is most likely (and I'm making some assumptions here, it'd be helpful if you included the web.xml) a request mapper not set up to handle the " " that your controller is returning; make your controller return some sort of meaningful view name that has a valid servlet mapping and you will not get a 404.
I had this problem too. I added "#ResponseBody" and got the right result.
I think the problem is that without the annotation "#ResponseBody", the returned string is handled by some strange resolver and javascript code gets response of unexpected form.
#RequestMapping(value="/uploadFile",method=RequestMethod.POST)
public #ResponseBody String upload(HttpServletResponse response,
HttpServletRequest request) throws IOException{

Resources