Pages

Wednesday, February 13, 2013

Serving Static HTML within WAR file using Spring

In my previous post
I've described how to serve static HTML files with simple WAR
In this post, I will add a description for the same task but using Spring MVC

In your WAR file, create any folder under WEB-INF

- sample-war.war
----- META-INF
-------- MANIFEST.MF
----- WEB-INF
-------- classes
-------- some-pages
----------- some-page.html
-------- lib
-------- web.xml
----- index.html

then, go to your servlet-context.xml file, this is a file used by spring to configure web context, and add this line
<resources mapping="/**" location="/WEB-INF/some-pages/" />
or
<mvc:resources mapping="/**" location="/WEB-INF/some-pages/" />

depends in what namespace your servlet-context.xml is configured

The meaning of this line is: serve me any HTML located under /WEB-INF/some-pages/ and map it to my root context

This would mean, that the link http://localhost:8080/sample-war/some-page.html will work
Another example: if we use this mapping
<resources mapping="/super-web-site/**" location="/WEB-INF/some-pages/" />
then this link http://localhost:8080/sample-war/super-web-site/some-page.html will work

Serving Static HTML within WAR file

How to create a WAR file with static HTML pages inside

War file, as you know is a zipped folder. It must have the following structure

- sample-war.war
----- META-INF
-------- MANIFEST.MF
----- WEB-INF
-------- classes
-------- lib
-------- web.xml

Two important thing to remember:

  1. HTML file or folder that contains HTML files located inside WEB-INF will not be accessible to users
  2. HTML file or folder that contains HTML files located inside the WAR file, on the same level as WEB-INF will be visible to users

Let's consider the following structure, and see what will work and what will not
Assumption: your application deployed on localhost, port 8080 and the application name is sample-war

- sample-war.war
----- META-INF
-------- MANIFEST.MF
----- WEB-INF
-------- classes
-------- hidden-pages
----------- hidden-page.html
-------- lib
-------- web.xml
----- pages
-------- visible-page.html
----- index.html
----- outside.html

URI Is Page Visible
http://localhost:8080/sample-war/index.html true
http://localhost:8080/sample-war/outside.html true
http://localhost:8080/sample-war/pages/visible-page.html true
http://localhost:8080/sample-war/hidden-page.html false
http://localhost:8080/sample-war/hidden-pages/hidden-page.html false

Note: Normally you would like to enable this URI
http://localhost:8080/sample-war
and make it serve some home page for you, index.html for example.
In this case, simply add those lines to your web.xml

<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>

Friday, June 29, 2012

How to consume custom JSON using Spring MVC

When using Spring MVC, you get number of things free, one of them is Jackson, that will produce JSON from your classes  (it happens automatically if you use <mvc> namespace) and consume JSON on the inbound request

But sometimes, you need to consume a custom JSON, that you do not have a class dedicated for it, hence it is not driven by Jackson annotations.
To do that, simply define a method in your Controller:


@RequestMapping(value = "/customer/{id}", method = RequestMethod.POST)
@ResponseBody
public onPost(@PathVariable("id") String id, @RequestBody String body) {
ObjectMapper mapper = new ObjectMapper();
try {
Map<String, Object> readValue = mapper.readValue(body, Map.class);
logger.info("Object is {}", readValue.getClass().getName());
} catch (Exception e) {
e.printStackTrace();
}
}


Spring will bind the body of the request to a java.lang.String and ObjectMapper will convert this String to a Map, so you could access it however you like.
In practice, Object (the value in the map) could be another Map, so you would have to traverse it as well.

Tuesday, June 26, 2012

How to use Spring Resources in WAR Example

Problem: Assume you have a some resources in your WAR file, that you want to use in run time, for example accessing XML files and printing it's content, or reading some meta-data and using it.

Solution: Spring provided an useful Resource abstraction, that can be used. To obtain a reference to a service that will allow access to resource, you can use:

@Autowired
private ResourcePatternResolver resourceLoader = null;


Spring will inject a bean that implements this interface, in practice it would actually be a reference for ApplicationContext (ApplicationContext must implement ResourcePatternResolver interface)

and then you can get an array of resources by using:

Resource[] resources = resourceLoader.getResources("resources/my-xml-files/**");

After that, you can iterate over the resources and easily perform

resource.getInputStream()

to read the contents.

Good luck