Get servlet init params in servlet context listener - servlets

<listener>
<listener-class>config</listener-class>
</listener>
<servlet>
<servlet-name>ProcessReg</servlet-name>
<servlet-class>ProcessReg</servlet-class>
<init-param>
<param-name>text</param-name>
<param-value>HelloWorld1</param-value>
</init-param>
public class config implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
ServletContext servletContext = event.getServletContext();
String text1 = servletContext.getInitParameter("text");
In method contextInitialized(ServletContextEvent event) , If There would be two servlets , for example , Let's say name of the second servlet be Servlet2 and it let's say has also has init - param called text with value HelloWorld2 .
How does listener know to take ProcessReg servlet ?
How to get param from Servlet2 ??

You need to distinguish between servlet initialization parameters and context initialization parameters.
Context initialization parameters are:
context-wide;
declared in <context-param> elements directly under the <web-app> root;
typically accessed using the ServletContext.getInitParameter() method, e.g. from inside a listener's contextInitialized() method.
Servlet initialization parameters are:
servlet-specific;
declared in <init-param> elements inside a <servlet> element;
typically accessed using the ServletConfig.getInitParameter() method, e.g. from inside the servlet's init() method.

Related

How do I make jcaptcha work with Spring Session?

We implemented Spring Session backed by Redis and have a cluster of Tomcat servers. When we turned sticky sessions off by not setting the jvmRoute we keep getting "Text verification failed" in the jcaptcha service. I assume this is because the jcaptcha servlet knows nothing about the Spring Dispatcher servlet, which has all of the Spring Session filters, and thus cannot read the session variable. How can we make jcaptcha work with Spring Session?
Here is our setup:
Web.xml
<servlet>
<servlet-name>my-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>throwExceptionIfNoHandlerFound</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>my-servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>jcaptcha</servlet-name>
<servlet-class>com.octo.captcha.module.servlet.image.SimpleImageCaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jcaptcha</servlet-name>
<url-pattern>/jcaptcha/jcaptcha.jpg</url-pattern>
</servlet-mapping>
CustomHttpSessionAppInitializer.java
public class CustomHttpSessionAppInitializer extends AbstractHttpSessionApplicationInitializer {}
RedisSessionConfig.java
#Configuration
#EnableRedisHttpSession
public class RedisSessionConfig {
#Value("${spring.redis.host}")
private String redisServerName;
#Value("${spring.redis.port}")
private Integer redisServerPort;
#Value("${spring.redis.database}")
private Integer redisServerDatabase;
#Value("${spring.redis.password}")
private String redisServerPassword;
#Value("${spring.server.affinity}")
private Boolean isServerAffinity = Boolean.FALSE;
#Autowired
private SessionIdentifierService sessionIdentifierService;
#Bean
public JedisConnectionFactory jedisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisServerName, redisServerPort);
config.setDatabase(redisServerDatabase);
config.setPassword(RedisPassword.of(redisServerPassword));
return new JedisConnectionFactory(config);
}
/*
* We need to register every HttpSessionListener as a bean to translate SessionDestroyedEvent and SessionCreatedEvent into
* HttpSessionEvent. Otherwise we will got a lot of warning messages about being Unable to publish Events for the session.
* See Spring Session Docs at:
* {#link} https://docs.spring.io/spring-session/docs/current/reference/html5/#httpsession-httpsessionlistener
*/
#Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
#Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("JSESSIONID");
serializer.setUseBase64Encoding(false);
if (isServerAffinity) {
serializer.setJvmRoute(sessionIdentifierService.getJvmRoute());
}
return serializer;
}
#Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(jedisConnectionFactory());
return template;
}
}
There shouldn't be a problem integrating jcaptcha with Spring Session. As long as there is a way of loading the session from Redis (via a SESSION cookie in this case) and the session exists, calling request.getSession() or request.getSession(false) will return the Redis-backed session.
This works in any filter and servlet that is called AFTER the springSessionRepositoryFilter. If you look at the source code of SessionRepositoryFilter, you will see that the HttpServletRequest is swapped with a SessionRepositoryRequestWrapper.
So your SimpleImageCaptchaServlet and whichever servlet you use to validate the user response will obtain a SessionRepositoryRequestWrapper that will seemlessly give you access to the Redis-backed session.
The problem then might be your configuration; the springSessionRepositoryFilter might not be registered with the container, especially since you’re using both web.xml and a Servlet 3.0+ WebApplicationInitializer. If your app works properly, then your web.xml is most likely working fine. Are you using a WebApplicationInitializer to load your web.xml? If not, then it might be that your Java Config is not loading. Make sure your web.xml loads your configuration somehow, perhaps by enabling component scanning (<context:component-scan/>) in the contextLoaderListener xml config file to load your Java Config along with:
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
to load the configuration that will create the filter, which you must then add to your web.xml:
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
Check out the Spring Session reference on XML config

Spring 3.2 MVC #RequestParam unexpected decoding

Consider following query string
siteId=360798&listingId=695332&stockFilename=6065/1mb%20&%20(Custom).jpg&uploadToken=2640861a8f06799416bae9d0a58839dd&username=Chuck%20Norris
I have the following on my MVC controller
#RequestParam("stockFilename") String stockFilename
I expect to get as value in my param to have "6065/1mb & (Custom).jpg", yet the result is "6065/1mb". My first guess was that this was an encoding issue so I went to web.xml and looked at my encoding filter but this seems to be in order
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
Next up I went to look at my server setting
Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"
I've added the URIEncoding attribute, since I found an article explaining this as a possible culprit. However it didn't fix my problem at all. I'm actually out of ideas now I'm still quite sure it has to be an encoding issue, and spring is decoding it wrongly. I'll continue searching but any help would be appreciated.
Add this method and bean in your servlet-context :
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
public final class DoNotTruncateMyUrls implements BeanPostProcessor {
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof RequestMappingHandlerMapping) {
((RequestMappingHandlerMapping)bean).setUseSuffixPatternMatch(false);
}
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
Bean :
<beans:bean class="com.packagename.DoNotTruncateMyUrls" />
Let me know if this works, or I have another solutions.

servlet or ejb singleton to initialize web app

I need to initialize state of web application.
I can use initialization servlet with load-on-startup = 0.
Or I can use singleton ejb service.
What is better to use and why?
i think load-on-startup is better than ejb.
i have used load on start up in my web application.
<servlet>
<servlet-class>com.agileinfotech.bsviewer.servlet.InitServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>InitServlet</servlet-name>
<url-pattern>/InitServlet</url-pattern>
</servlet-mapping>
There is a special "thing" for initialization of web app - ServletContextListener.
it is used like this:
package example;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ServletContextExample implements ServletContextListener{
ServletContext context;
public void contextInitialized(ServletContextEvent contextEvent) {
... some init work
}
public void contextDestroyed(ServletContextEvent contextEvent) {
... some destroy work
}
}
And in web.xml
<listener>
<listener-class>
example.ServletContextExample
</listener-class>
</listener>

Retrieve servletContext reference in quartz scheduler

I am using Quartz Scheduler with my spring 3.0 based application. I am successfully able to create new schedulers and they are working fine.
I have seen thus reference.
But.. I am not able to retrieve servletContext in my quartz job file. can anyone help me for How to retrieve servletContext reference in executeInternal() method ??
I had a similar need. I sorted it out in a similar fashion to the solution presented here.
In my servlet context listener I am setting the servlet context using the job data map object which then is set for a job:
#Override
public void contextInitialized(ServletContextEvent sce) {
try {
//Create & start the scheduler.
StdSchedulerFactory factory = new StdSchedulerFactory();
factory.initialize(sce.getServletContext().getResourceAsStream("/WEB-INF/my_quartz.properties"));
scheduler = factory.getScheduler();
//pass the servlet context to the job
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("servletContext", sce.getServletContext());
// define the job and tie it to our job's class
JobDetail job = newJob(ImageCheckJob.class).withIdentity("job1", "group1").usingJobData(jobDataMap).build();
// Trigger the job to run now, and then repeat every 3 seconds
Trigger trigger = newTrigger().withIdentity("trigger1", "group1").startNow()
.withSchedule(simpleSchedule().withIntervalInMilliseconds(3000L).repeatForever()).build();
// Tell quartz to schedule the job using our trigger
scheduler.scheduleJob(job, trigger);
// and start it off
scheduler.start();
} catch (SchedulerException ex) {
log.error(null, ex);
}
}
Then inside my job I am doing this:
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
ServletContext servletContext = (ServletContext) context.getMergedJobDataMap().get("servletContext");
//...
}
EDIT:
Also since you mention that you are using Spring I found this link, where in the last post a guy mentions to implement ServletContextAware. Personally, I would go with the JobDataMap, since that is its role.
Starting from Quartz 2.0, if you are starting the scheduler inside your webapp via QuartzInitializerServlet in your web.xml, you can store ServletContext in your SchedulerContext by setting scheduler-context-servlet-context-key as an init parameter as follows:
<!-- Quartz Scheduler Initializer Servlet -->
<servlet>
<servlet-name>QuartzInitializer</servlet-name>
<servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
<init-param>
<param-name>shutdown-on-unload</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>start-scheduler-on-load</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>scheduler-context-servlet-context-key</param-name>
<param-value>servletContext</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
See the following reference in code: https://github.com/elventear/quartz-scheduler/blob/quartz-2.0.0-rc/quartz/src/main/java/org/quartz/ee/servlet/QuartzInitializerServlet.java#L122
To get to your ServletContext from a QuartzJob configure like Kalman said, Then here is some code to get a actual "servletContext"
private void initContext(JobExecutionContext jobContext) {
Scheduler scheduler = jobContext.getScheduler();
SchedulerContext schedulerContext = null;
try {
schedulerContext = scheduler.getContext();
} catch (SchedulerException e) {
e.printStackTrace();
}
ServletContext servletContext = (ServletContext)schedulerContext.get("servletContext");
System.out.println("ServletContextName : "+ servletContext.getServletContextName());

JBoss AS7: ServletContextListener#contextInitialized called after Servlet instantiation

I am trying to deploy my webservice (originally running on JBoss AS5) on the new JBoss AS7 (Everything) Final.
The problem is that i used a ServletContextListener to initialize my environment (f.e. to initialize the resource management).
But when I try to deploy the war file on JBoss AS 7 the configured Servlets are instantiated before the #contextInitialized-method of the listener is called (wich cases an Exception because a mandatory resource can not be found).
My listener:
#WebListener
public class StandardStartup implements ServletContextListener {
#Override
public void contextDestroyed(final ServletContextEvent arg0) {
//destroy environment
}
#Override
public void contextInitialized(final ServletContextEvent arg0) {
//initialize environment
}
}
My web.xml:
<?xml version="1.0"?>
<web-app version="3.0" 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/web-app_3_0.xsd">
<display-name>any.displayname</display-name>
<listener>
<display-name>Startup</display-name>
<listener-class>any.StandardStartup</listener-class>
</listener>
<servlet>
<servlet-name>AnyServlet</servlet-name>
<servlet-class>any.AnyServlet</servlet-class>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AnyServlet</servlet-name>
<url-pattern>/AnyServlet</url-pattern>
</servlet-mapping>
</web-app>
Can someone explain me why the listener is not called before the instantiation of the servlets (maybe with a possible workaround) or knows what I am doing wrong?
PS.: I tried to implement the listener as a Servlet and set the load-on-startup to 0, but JBoss AS7 says I have declare a servlet-mapping which I do not want in that case.
Thanks for your help!

Resources