spring web services configuration in web.xml? - java

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.

Related

Caching of Static Files in GWT

Developed application using GWT which contains lot of static files(javascript,css,images) which i want to cache for 30 days. I read lot of blogs but didn't get any clue.
- How to cache static files?
- What are the possible option to achieve caching (do i need to configure in server or GWT application, here i am using glassfish/payara server for deployment)
Any idea?
Note: I want do achieve this with minimal code changes, even i read this Client side caching in GWT
but don't want to go with dispatcher approach
You will need to add something like the ExpiresFilter to your servlet container.
I'm adding the details for the configuration from the link mentioned above just in case the content of the link goes away:
You will need to edit web.xml to add a filter and a filter mapping:
<filter>
<filter-name>ExpiresFilter</filter-name>
<filter-class>server.ExpiresFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ExpiresFilter</filter-name>
<url-pattern>/images/\*</url-pattern> <!-- these patterns should match cached resources -->
<url-pattern>/resources/\*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
If you need a more portable approach for use in different application servers, you might end up writing a generic servlet Filter like I did.
After all that is no big deal as you just have set the Expires and Cache-Control: max-age headers for HttpServletRequests on your given paths.
As a starter, I stumpled upon this implementation and how Tomcat does it.

How to dynamically configure the WebLogicCluster property outside of web.xml

I have a web application deployed as war file in weblogic 10.3.3. Now I want to make this application clusterable. For this I'm using the HttpClusterServlet from Weblogic as a load balancer. According to the documentation I can put this servlet configuration into the web.xml
<servlet>
<servlet-name>HttpClusterServlet</servlet-name>
<servlet-class>weblogic.servlet.proxy.HttpClusterServlet</servlet-class>
<init-param>
<param-name>WebLogicCluster</param-name>
<param-value>server-1:7122|server-1:7123</param-value>
</init-param>
</servlet>
The problem is that this configuration is hard wired at build time and can't be reconfigured at runtime. For instance I would like to be able to add 5 more servers dynamically. I had several ideas to solve that problem:
Extend the weblogic.servlet.proxy.HttpClusterServlet with an own servlet implentation. This is not possible, the class is final.
Use a servlet filter to reconfigure the servlet. The servlet is not accessible anymore through ServletContext().getServlet(String) since Java Servlet API 2.1, with no direct replacement.
Reflection might be an option, but I couldn't figure out a reliable way to access the configuration
All of my attempts to reconfigure this init-param externally failed so far. I'm open to any solutions.
This might help How to externalize web.xml servlet init-param? Spring DelegatingFilterProxy for Servlets? Even if your not using Spring it wouldn't be too hard to port that servlet to another IoC container.

Java servlet - any built-in way to restrict access to username/password?

I have an app engine java app. I'm defining my servlets in web.xml as usual, something like:
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.me.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/private/dangerous</url-pattern>
</servlet-mapping>
It works fine. Is there any "built-in" security available for us? I don't want to allow access to the above servlet, it's an admin thing that only I should have access to. Do I build some simple username/password deal myself?
Thanks
There is a security mechanism in web.xml, security constraints, that might work for a relatively simple case. You can find information on how to use this mechanism with GAE at : http://code.google.com/appengine/docs/java/config/webxml.html#Security_and_Authentication
Maybe a filter would be a good way to tackle it. You can check the user's role, using basic auth, and allow or deny access as needed.
You normally use a security-constraint in the web.xml for this.

How to access static resources when mapping a global front controller servlet on /*

I've mapped the Spring MVC dispatcher as a global front controller servlet on /*.
<servlet>
<servlet-name>home</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>home</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
However, this mapping stops the access to static files like CSS, JS, images etc which are all in the /res/ folder.
How can I access them anyway?
Map the controller servlet on a more specific url-pattern like /pages/*, put the static content in a specific folder like /static and create a Filter listening on /* which transparently continues the chain for any static content and dispatches requests to the controller servlet for other content.
In a nutshell:
<filter>
<filter-name>filter</filter-name>
<filter-class>com.example.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>com.example.Controller</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>/pages/*</url-pattern>
</servlet-mapping>
with the following in filter's doFilter():
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());
if (path.startsWith("/static")) {
chain.doFilter(request, response); // Goes to default servlet.
} else {
request.getRequestDispatcher("/pages" + path).forward(request, response);
}
No, this does not end up with /pages in browser address bar. It's fully transparent. You can if necessary make "/static" and/or "/pages" an init-param of the filter.
With Spring 3.0.4.RELEASE and higher you can use
<mvc:resources mapping="/resources/**" location="/public-resources/"/>
As seen in Spring Reference.
What you do is add a welcome file in your web.xml
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
And then add this to your servlet mappings so that when someone goes to the root of your application, they get sent to index.html internally and then the mapping will internally send them to the servlet you map it to
<servlet-mapping>
<servlet-name>MainActions</servlet-name>
<url-pattern>/main</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MainActions</servlet-name>
<url-pattern>/index.html</url-pattern>
</servlet-mapping>
End result: You visit /Application, but you are presented with /Application/MainActions servlet without disrupting any other root requests.
Get it? So your app still sits at a sub url, but automatically gets presented when the user goes to the root of your site. This allows you to have the /images/bob.img still go to the regular place, but '/' is your app.
If you use Tomcat, you can map resources to the default servlet:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
and access your resources with url http://{context path}/static/res/...
Also works with Jetty, not sure about other servlet containers.
Serving static content with appropriate suffix in multiple servlet-mapping definitions solved the security issue which is mentioned in one of the comments in one of the answers posted. Quoted below:
This was a security hole in Tomcat (WEB-INF and META-INF contents are accessible this way) and it has been fixed in 7.0.4 (and will be ported to 5.x and 6.x as well). – BalusC Nov 2 '10 at 22:44
which helped me a lot.
And here is how I solved it:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
I've run into this also and never found a great solution. I ended up mapping my servlet one level higher in the URL hierarchy:
<servlet-mapping>
<servlet-name>home</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
And now everything at the base context (and in your /res directory) can be served up by your container.
As of 3.0.4 you should be able to use mvc:resources in combination with mvc:default-servlet-handler as described in the spring documentation to achieve this.
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-static-resources
The reason for the collision seems to be because, by default, the context root, "/", is to be handled by org.apache.catalina.servlets.DefaultServlet. This servlet is intended to handle requests for static resources.
If you decide to bump it out of the way with your own servlet, with the intent of handling dynamic requests, that top-level servlet must also carry out any tasks accomplished by catalina's original "DefaultServlet" handler.
If you read through the tomcat docs, they make mention that True Apache (httpd) is better than Apache Tomcat for handling static content, since it is purpose built to do just that. My guess is because Tomcat by default uses org.apache.catalina.servlets.DefaultServlet to handle static requests. Since it's all wrapped up in a JVM, and Tomcat is intended to as a Servlet/JSP container, they probably didn't write that class as a super-optimized static content handler. It's there. It gets the job done. Good enough.
But that's the thing that handles static content and it lives at "/". So if you put anything else there, and that thing doesn't handle static requests, WHOOPS, there goes your static resources.
I've been searching high and low for the same answer and the answer I'm getting everywhere is "if you don't want it to do that, don't do that".
So long story short, your configuration is displacing the default static resource handler with something that isn't a static resource handler at all. You'll need to try a different configuration to get the results you're looking for (as will I).
'Static' files in App Engine aren't directly accessible by your app. You either need to upload them twice, or serve the static files yourself, rather than using a static handler.
The best way to handle this is using some kind of URL re-writing. In this way, you can have clean restful URLs, and NOT with any extensions i.e abc.com/welcom/register as opposed to abc.com/welcome/resister.html
I use Tuckey URL which is pretty cool.
It's got instructions on how to set up your web app.I have set it up with my Spring MVC web app. Of course, everything was fine until I wanted to use annotations for Spring 3 validations like #Email or #Null for domain objects.
When I add the Spring mvc directives:
< mvc:annotation-driven />
< mvc:default-servlet-handler />
.. it breaks the good ol Tuckey code. Apparently, < mvc:default-servlet-handler /> replaces Tuckey, which I'm still trying to solve.
I'd recommend trying to use a Filter instead of a default servlet whenever possible.
Other two possibilities:
Write a FileServlet yourself. You'll find plenty examples, it should just open the file by URL and write its contents into output stream. Then, use it to serve static file request.
Instantiate a FileServlet class used by Google App Engine and call service(request, response) on that FileServlet when you need to serve the static file at a given URL.
You can map /res/* to YourFileServlet or whatever to exclude it from DispatcherServlets' handling, or call it directly from DispatcherServlet.
And, I have to ask, what does Spring documentation say about this collision? I've never used it.
Add the folders which you don't want to trigger servlet processing to the <static-files> section of your appengine-web.xml file.
I just did this and looks like things are starting to work ok. Here's my structure:
/
/pages/<.jsp files>
/css
I added "/pages/**" and "/css/**" to the <static-files> section and I can now forward to a .jsp file from inside a servlet doGet without causing an infinite loop.
After trying the filter approach without success (it did for some reason not enter the doFilter() function) I changed my setup a bit and found a very simple solution for the root serving problem:
Instead of serving " / * "
in my main Servlet, I now only listen to dedicated language prefixes
"EN", "EN/ *", "DE", "DE/ *"
Static content gets served by the default Servlet and the empty root requests go to the index.jsp which calls up my main Servlet with the default language:
< jsp:include page="/EN/" />
(no other content on the index page.)
I found that using
<mvc:default-servlet-handler />
in the spring MVC servlet bean definition file works for me. It passes any request that isn't handled by a registered MVC controller on to the container's original default handler, which should serve it as static content. Just make sure you have no controller registered that handles everything, and it should work just fine. Not sure why #logixplayer suggests URL rewriting; you can achieve the effect he's looking for just adequately using Spring MVC alone.
I found a simpler solution with a dummy index file.
Create a Servlet (or use the one you wanted to respond to "/") which maps to "/index.html"
(Solutions mentioned here use the mapping via XML, I used the 3.0 version with annotation #WebServlet)
Then create a static (empty) file at the root of the static content named "index.html"
I was using Jetty, and what happened was that the server recognized the file instead of listing the directory but when asked for the resource, my Servlet took control instead. All other static content remained unaffected.
In Embedded Jetty I managed to achieve something similar by adding a mapping for the "css" directory in web.xml. Explicitly telling it to use DefaultServlet:
<servlet>
<servlet-name>DefaultServlet</servlet-name>
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DefaultServlet</servlet-name>
<url-pattern>/css/*</url-pattern>
</servlet-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<mvc:default-servlet-handler/>
</beans>
and if you want to use annotation based configuration use below code
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
With regard to Tomcat, a lot depends on the particular version. There was a bug fix
https://bz.apache.org/bugzilla/show_bug.cgi?id=50026
which means the servlet-mapping (other than for '/') for the default servlet behaves differently in Tomcat 6.0.29 (and earlier) compared with later versions.
In section "12.2 Specification of Mappings" of the Servlet Specification, it says:
A string containing only the ’/’ character indicates the "default" servlet of the
application.
So in theory, you could make your Servlet mapped to /* do:
getServletContext().getNamedDispatcher("/").forward(req,res);
... if you didn't want to handle it yourself.
However, in practice, it doesn't work.
In both Tomcat and Jetty, the call to getServletContext().getNamedDispatcher('/') returns null if there is a servlet mapped to '/*'

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