Execute JSP at Tomcat Startup - java

Please note that I am not the developer of this app and I realize that there are probably better ways to implement it. However, I have been given the following objective:
I need to automatically execute a jsp page when tomcat starts on an RHEL server. The only kicker is that their are three URL Parameters that need to be passed.
Here is an example of the URL:
http://www.myurl.com/app/getlistdata.jsp?param1=P1&param2=P2&param3=P3
In my web.xml I have the following but it does not seem to be loading automatically. I suppose I could modify the start_tomcat script to include a wget but I was hoping to make this independent from the server it is deployed to.
<servlet>
<servlet-name>getlistdata</servlet-name>
<jsp-file>/getlistdata.jsp</jsp-file>
<init-param>
<param-name>param1</param-name>
<param-value>P1</param-value>
</init-param>
<init-param>
<param-name>param2</param-name>
<param-value>P2</param-value>
</init-param>
<init-param>
<param-name>param3</param-name>
<param-value>P3</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>

As #home said - Init attributes are not request parameters - so which do you mean? JSPs are used to render a view to a browser as a response to a request. Doing that when Tomcat starts up makes no sense because there's no request.
Look at the JSP. Perhaps it uses a Java Bean under the hood to do some processing. If you can move this processing out to a Context Listener, that would work:
In your web.xml:
<listener>
<listener-class>
path.to.YourListener
</listener-class>
</listener>
And then create a java class:
public class YourListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// this will execute when tomcat initialized the web application (on startup)
// so whatever your JSP was doing, you can do in here instead.
}
}
Not quite what you asked for, but this is the closest you can do, AFAIK.

The solution used was to add a curl command to the startup_tomcat script.
URL="http://SOMEURL.COM/GOES/HERE"
nohup curl $URL >> /home/tomcat/log &
exit
While there are many technical reasons not to do this, it met the business requirements that were provided.

Related

spring web services configuration in web.xml?

I am using spring-ws and I have the below configuration in my web.xml
<servlet>
<servlet-name>spring-ws</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>**transformWsdlLocations**</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>spring-ws</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Here I have transformWsdlLocations configured. Please explain me the use of transformWsdlLocations here. I am using the dynamic WSDL generation concept.
Is transformWsdlLocations really required for dynamic WSDL generation?
Thanks!
Given that it only takes a couple of minutes to remove the value and redeploy your application, I would advise you to do that and see what happens. Just try accessing the WSDL through "localhost" and through "127.0.0.1", and see what differences there are.
However I'll explain what you should see here...
When you read the WSDL that is generated, you should find that there are URLs in there.
i.e. From the local machine you might use:
http://localhost:8080/myservice.wsdl
But when you go live, your service might be:
http://www.<yourdomain>.com/myservice.wsdl
You don't want someone downloading the WSDL from your production domain to have those values populated with "localhost:8080". Likewise, you can't test your service properly if the URL being returned in the WSDL is for your production server. Or you might have multiple production services with different URLs.
transformWsdlLocations ensures that this is generated dynamically based on whatever URL is being used to access the service.
It is not needed for dynamic WSDL generation, but I have always found it very useful to have it. However, it is not enabled by default, so if you do want those URLs to be generated dynamically then it's best to include it.

Tomcat not serving static files

I'm at the end of my rope on this one. I'm try to get a super simple webapp up and I can't seem to get tomcat to not 404 static files.
I'm using the gradle tomcat plugin with tomcat version 7.0.39
My html file is at hey-world/src/main/webapp/index.html
My web.xml looks like this:
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>HeyWorldApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
So I thought this setup would map localhost:8080/hey-world/static/index.html to the file, but it 404's everytime. Is this a problem with some convention in the gradle tomcat plugin?
The URL-patterns used in web.xml/servlet-mapping is often a little simplistic. I think in your case, the /* pattern for Resteasy will work as a catch-all, so that no other mapping will really matter.
For debugging, I suggest you remove the Resteasy-servlet altogether, and see if you can serve static files from a custom URL with your mapping.
If that works, re-enable Resteasy, but on a different URL-pattern (eg. /rest/*).
If that works, well, then everything really works fine, it's just that the URL-mapping for /* blocks anything else from working.
The easiest solution would probably be to server static files as per default (no mapping), and serve rest-stuff from another URL.
Alternatively use two web apps. One with context root /static, one with context root /.

welcome-file in web.xml with spring not working?

I have setup my spring-mvc servlet to match *.page requests. I have setup the welcome-file-list in web.xml to be index.page
This works when I go to the root of my webserver:
http://me.com does get redirected to http://me.com/index.page correctly.
However, it doesn't redirect when I use subdirectoris:
http://me.com/dashboard does not get redirected to http://me.com/dashboard/index.page
Is there any way to get this mapping working?
My web.xml file (extract):
<welcome-file-list>
<welcome-file>index.page</welcome-file>
</welcome-file-list>
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>*.page</url-pattern>
</servlet-mapping>
My webdefault.xml (from jetty):
<init-param>
<param-name>dirAllowed</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>welcomeServlets</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>redirectWelcome</param-name>
<param-value>false</param-value>
</init-param>
The <welcome-file> should represent a physically existing file in an arbitrary folder which you would like to serve whenever the enduser requests a folder (such as the root /, but it can also be any other folder such as /foo/). You only need to understand that the servletcontainer will test its physical existence before performing a forward, if it does not exist then a HTTP 404 page not found error will be returned.
In your particular case, you do not have a physical index.page file in your root folder. You have actually a index.jsp file in your root folder. The index.page is merely a virtual URL. So the servletcontainer won't be able to find the physical index.page file and hence error out with a 404.
You can workaround this by fooling the servletcontainer by placing a physically existing index.page file next to the index.jsp file in the same folder. That file can just be kept completely empty. The servletcontainer will find the file and then forward to index.page which will then invoke the controller servlet which in turn will actually serve the index.jsp as view. That'll work just fine.
It will work only for real, physical directories, not won't work for arbitrary servlet mappings simulating directory structure.
Spring MVC allows very complex URL mappings, so you'd better handle this scenario with #RequestMapping
To avoid forwarding welcome file itself, its better add a mapping for it.
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>index.html</url-pattern>
</servlet-mapping>
And in case of java configuration you can override two methods in class that extends WebMvcConfigurerAdapter
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("/index");
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
If you wanna serve index.html explicitly, turn it into a resource override a method in the same class as below:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/index.html").addResourceLocations("/WEB-INF/views/index.html");
}
Of course addResourceLocations must follows the folder choosen to hold your views.
See these samples
This is something you need to probably set in your web server, and so, maybe server specific
For Apache HTTP Server you can achieve this by setting the DirectoryIndex directive like so:
DirectoryIndex index.page
Apparently, someone has already asked this question, and has accepted an answer at web.xml default file in directory (for jetty, or tomcat)? - See if it works for you.

RESTlet startup initialization deprecated?

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).

Can anyone explain servlet mapping?

I'm trying to write a web application using SpringMVC. Normally I'd just map some made-up file extension to Spring's front controller and live happily, but this time I'm going for REST-like URLs, with no file-name extensions.
Mapping everything under my context path to the front controller (let's call it "app") means I should take care of static files also, something I'd rather not do (why reinvent yet another weel?), so some combination with tomcat's default servlet (let's call it "tomcat") appears to be the way to go.
I got the thing to work doing something like
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>tomcat</servlet-name>
<url-pattern>*.ext</url-pattern>
</servlet-mapping>
and repeating the latter for each one of the file extensions of my static content. I'm just wondering why the following setups, which to me are equivalent to the one above, don't work.
<!-- failed attempt #1 -->
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>tomcat</servlet-name>
<url-pattern>*.ext</url-pattern>
</servlet-mapping>
<!-- failed attempt #2 -->
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>tomcat</servlet-name>
<url-pattern>/some-static-content-folder/*</url-pattern>
</servlet-mapping>
Can anyone shed some light?
I think I may know what is going on.
In your working web.xml you have set your servlet to be the default servlet (/ by itself is the default servlet called if there are no other matches), it will answer any request that doesn't match another mapping.
In Failed 1 your /* mapping does appear to be a valid path mapping. With the /* mapping in web.xml it answers all requests except other path mappings. According to the specification extension mappings are implicit mappings that are overwritten by explicit mappings. That's why the extension mapping failed. Everything was explicitly mapped to app.
In Failed 2, App is responsible for everything, except content that matches the static content mapping. To show what is happening in the quick test I set up. Here is an example. /some-static-content-folder/ contains test.png
Trying to access test.png I tried:
/some-static-content-folder/test.png
and the file was not found. However trying
/some-static-content-folder/some-static-content-folder/test.png
it comes up. So it seems that the Tomcat default servlet (6.0.16 at least) drops the servlet mapping and will try to find the file by using the remaining path. According to this post Servlet for serving static content Jetty gives the behavior you and I were expecting.
Is there some reason you can't do something like map a root directory for your rest calls. Something like app mapped to /rest_root/* than you are responsible for anything that goes on in the rest_root folder, but anywhere else should be handled by Tomcat, unless you make another explicit mapping. I suggest setting your rest servlet to a path mapping, because it declares the intent better. Using / or /* don't seem appropriate, since you have to map out the exceptions. Using SO as an example, my rest mappings would be something like
/users/* for the user servlet
/posts/* for the posts servlet
Mapping order
Explicit (Path mappings)
Implicit (Extension mappings)
Default (/)
Please correct anything that I got wrong.
For reference, the "failed attempt #2" is perfectly correct in version of Tomcat >= to 6.0.29.
It was the result of a Tomcat bug that get fixed in version 6.0.29:
https://issues.apache.org/bugzilla/show_bug.cgi?id=50026
<!-- Correct for Tomcat >= 6.0.29 or other Servlet containers -->
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/some-static-content-folder/*</url-pattern>
</servlet-mapping>
I've never tried to map a servlet like this, but I would argue that /* does technically both start with / and end with /*, even though the same character is used for both matches.

Categories