Pages

Friday, November 7, 2014

Spring Boot examples

What is spring boot?


There are probably a lot of explanations about what it is, but my take on it is simple:
Spring Boot solves your classpath problems without troubling you thinking about it.

For example: Let's say you want to build a standard Spring MVC application.
You create a maven project (or gradle), you add spring-web to classpath and you get it working.
You may be missing few jars so you simple add it to your pom.xml

With Spring Boot, you don't need to do so. Once you add a class and annotate it with @RestController, Spring will automatically add all the jars to the classpath that Spring thinks you need.
It may be more than you really need, but this is an opinionated view - take it or leave it.

Interesting features

For me, the most interesting feature besides classpath resolution is an ability to run Spring Boot application as simple java app, even if it is intended to be a web server. 
Spring Boot apps are intended to be run as java apps (jar files). Once you have some web semantics in your application (lets say you added a Controller) then Spring Boot will realize that and start embedded Tomcat and will let you use your application without creating a WAR file and deploying it into some Tomcat.

Examples

Very Basic Application

If you are user of STS (Spring Tools Suite) then you can simply create a basic Spring App.
Click on File -> New -> Spring Started Project and you will see this:
Once you created such application, you can simply run it as Java Application. It would not do much, but you can access Spring Context and see what are the default beans that are configured.

The class that would be generated in your project (Application) will have those lines:

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}


If you assign the return value of "run" to ApplicationContext then you can access all your beans.

Basic Application

The more interesting behavior will happen if you add a class to your project and annotate it as @RestController and rerun your application as Java Application.
What will happen is that Spring will start a tomcat instance and will not shutdown as in the first example, until you explicitly shut it down.

So if you will add a code:

@RestController 
public class ProductVerionController { 
 @RequestMapping("/version") 
 public String getVersion() { 
    return "1.0.0"; 
 } 
}



Then once the application is started, you can browse to http://localhost:8080/version and see the response "1.0.0"
There are few interesting points about this behavior:

  1. You run the program as simple Java but it is run as a web server (with embedded tomcat)
  2. There is not "web application name" in the URL, it is as if you deployed it to the ROOT of your tomcat - that aligns well with how Pivotal CloudFoundry deploys java apps and confirms that Spring Boot may be the way for building and deploying CF apps in the future

Basic Application + Some HTML files

By now, you have a simple web server that returns one String. 
But what if you need some html files? some static resources? at the end of the day, you have a web app.
Luckily, Spring Boot makes this easy as well. If you recall, in Spring MVC you had this line configured in servlet context

<resources location="/resources/" mapping="/resources/**" >

Well, this line was essentially taking resources from classpath of your web server.
In the case of Spring Boot, you don't have a web server, but you have a simple java application.
What you need to do in this case is something very simple.
Add either a folder named "resources" or "static" into src/main/resources folder, and any static HTML that you have there will be served by your app.
Here is my project structure:

and if you run an application than the URLs
http://localhost:8080/resources.html
and
http://localhost:8080/static.html
will return the respective HTML pages that I placed in a predefined folders I created

Next time - WAR files with Spring Boot.

Monday, January 27, 2014

Configuring Spring MVC with Mongo DB

Mongo DB is a popular NoSql database, that stores JSON objects.
It has few concepts to be aware of:
1. Collections - an equivalent of table in relational database
2. Document - an equivalent of a row in a table.
As a result, one can create collections and store documents inside them

Unlike relational database, structure of documents in the collection does not have to be identical.
It is common practice to have a similar structure, but it is not necessary the case

Now lets build a sample application with Mongo DB.
It will have one domain class BasicPerson and one service class PersistenceServiceImpl

Code for BasicPerson (setters and getters omitted ):
public class BasicPerson {
    private String id = null;
    private String name = null;
    private String lastName = null;
}


Code for PersistenceServiceImpl(interface declaration omitted ):
package com.dimalimonov.restmongo.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.stereotype.Service;
import com.dimalimonov.restmongo.domain.BasicPerson;

@Service
public class PersistenceServiceImpl implements PersistenceService {

    private static final String COLLECTION_NAME="restperson";

    @Autowired
    private MongoOperations mongoOperations = null;

    @Override
    public BasicPerson save(BasicPerson bp) {
        mongoOperations.insert(bp, COLLECTION_NAME);
    return bp;
    }

    @Override
    public List find() {
       List users = mongoOperations.findAll(BasicPerson.class, COLLECTION_NAME);
    return users;
    }

    @Override
    public BasicPerson update(BasicPerson bp) {
        mongoOperations.save(bp, COLLECTION_NAME);
    return bp;
    }
}

XML Configuration for the system:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">

<mongo:mongo id="mongoDefault" host="127.0.0.1" port="27017" />

<mongo:db-factory id="mongoDbFactory" dbname="rest" mongo-ref="mongoDefault" />

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> </beans>

Explanation

What is happening here, is rather simple, if you are familiar with Spring Template mechanism
First, you create a Mongo bean. This bean represents an instance of the database server you run, so you supply it host and port
Secondly, you create a Mongo Factory instance, where you reference a database in the Mongo server. This database will be used by you to create collections and documents in
Lastly, you create a Mongo template using the factory. Template will allow you to execute calls on the db.

When the mongoOperations.save(bp, COLLECTION_NAME); is invoked, Spring will serialize an instance of
BasicPerson into a JSON object (there is a default serializer for that) and will store it for you.
Other methods work similar using default deserialization
Interesting thing to notice is that when an object stored in Mongo, a special property _class will be stored with a class name for the object:
{
"_id": ObjectId("52e2b8ed8b4c2330d02d3ab8"),
"_class": "com.dimalimonov.restmongo.domain.BasicPerson",
"name": "newone",
"lastName": "newone1"
}

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