Saturday, October 24, 2015

Microservice - Spark Restful Framework ..sql2o

Spark Framework
Spark - A tiny Sinatra inspired framework for creating web applications in Java 8 with minimal effort

Spark - a Sinatra inspired web framework

For more detailed documentation please go to: http://sparkjava.com
NEWS: Spark 2.3 is now available on Maven central! :
    <dependency>
        <groupId>com.sparkjava</groupId>
        <artifactId>spark-core</artifactId>
        <version>2.3</version>
    </dependency>
NEWS: Spark google group created: https://groups.google.com/d/forum/sparkjava
Temporary API Docs: http://spark.screenisland.com


Built for Productivity

Spark Framework is a simple and lightweight Java web framework built for rapid development.

Spark's intention isn't to compete with Sinatra, or the dozen of similar web frameworks in different languages, but to provide a pure Java alternative for developers that want to, or are required to, develop their web application in Java.

Spark focuses on being as simple and straight-forward as possible, without the need for cumbersome (XML) configuration, to enable very fast web application development in pure Java with minimal effort.

It’s a totally different paradigm when compared to the overuse of annotations for accomplishing pretty trivial stuff seen in other web frameworks, for example, JAX-RS implementations.

Why Use Spark? GitHub

If you're a Java developer with neither the urge nor time to learn a new programming language, then Spark might be a great web framework for you. It will have you up and running in minutes, and you won't have to think too much about configuration and boilerplate code (like you often have to in other Java web frameworks, like Spring or Vaadin).

Why Not Use Sinatra?

If you're an experienced Ruby developer, or have experience with languages with similar syntax, you should probably use Sinatra. However, if you're a Java developer and want to get the benefits you get from Sinatra without having to learn a new language, Spark is a very good alternative. Spark is a simple and lightweight Java web framework that doesn't get in your way!

Why Not Go with JAX-RS?

JAX-RS made life easier for Java web developers when it arrived. However, it's a bit messy due to the overuse of annotations for accomplishing pretty trivial things. The annotation magic also makes things more implicit, and it's not always easy to get a clear understanding of what's going on. For people who are new to web frameworks and REST, Spark will have you up and running much faster than using one of the JAX-RS implementations

 
https://sparktutorials.github.io/

Quick Start

import static spark.Spark.*;

public class HelloWorld {
    public static void main(String[] args) {
        get("/hello", (req, res) -> "Hello World");
    }
}

Run and View

http://localhost:4567/hello
 




 
 
 
How to connect to database using spark java framework.
Spark and Databases: Configuring Spark to work with Sql2o in a testable way 

Designing the Model

Let’s assume you have access to a database. During development I would suggest to use a MySQL server running in a Docker container:
Docker or non Docker, I would assume you can now connect to your database.
Now let’s start to setup the dependencies in Maven: In addition to the Spark dependencies, you should add Sql2o and the jdbc extension specific to the database you are going to connect to. In my case I choose MySQL:

<dependency> 
 <groupId>org.sql2o</groupId>  
 <artifactId>sql2o</artifactId>  
 <version>1.5.4</version>  
</dependency>  
        
<dependency>
   <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.37</version>
</dependency>


Create Table in database
This is the schema we are going to use: 
 
CREATE USER team_lead WITH PASSWORD 'sparkMicroSvc';
CREATE DATABASE team_lead;
\connect team_lead
GRANT ALL PRIVILEGES ON DATABASE team_leadTO team_lead; 
 
CREATE TABLE IF NOT EXISTS `teams` (
  `TEAM_ID` int(11) NOT NULL AUTO_INCREMENT, 
 `TEAM_NAME` varchar(255) DEFAULT NULL,
  `PLAYER_NAME` varchar(255) DEFAULT NULL,
  `CREATED_ON` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `UPDATED_ON` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`TEAM_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO team_lead; 
 
Now, let’s start by defining a Model interface and one interface for each table 
of the database, with no references to the library we are going to use (Sql2o). 
 
The rest of your code will depend on this interface, not on the concrete implementation 
based on Sql2o that we are going to build. 
 
This will permit us to have testable code. 
 
For example we could use in our tests a dummy implementation storing data in memory. 
 
public interface Model {
    Integer createTeam(String teamName, String playerName);
    List getAllTeams();
    Team getTeam(Integer teamId);
}

@Data
public class Team{
    private Integer team_id;
    private String team_name;
    private String player_name;
    private Timestamp created_on;
    private Timestamp updated_on;
} 
 

Implement the Model using Sql2o

Great! It is now time to write some code that could actually integrate with a real database. The code it is pretty straightforward, if you know your SQL:

public class Sql2oModel implements Model { 

      private Sql2o sql2o;
    
      public Sql2oModel(Sql2o sql2o) {  
              this.sql2o = sql2o; 
         } 

       @Override 
       public Integer createTeam(String teamName, String playerName) {
        try ( 
            Connection conn = sql2o.open()) {
            conn.createQuery("insert into TEAMS(team_name,player_name,created_on,updated_on) VALUES (:teamName, :playerName, :created_on, :updated_on)")
                    .addParameter("team_name", teamName)
                    .addParameter("player_name", playerName)
                    .addParameter("created_on", System.currentTimeMillis())
                    .addParameter("updated_on", System.currentTimeMillis())
                   .executeUpdate();
            Integer teamId = conn.createQuery("select team_id from TEAMS where team_name = :teamName and player_name = :playerName");   
            return teamId;
        } 
   } 
 
    @Override
    public List<Team> getAllTeams() {
        try ( 
            Connection conn = sql2o.open()) { 
            List<Team> teams = conn.createQuery("select * from teams").executeAndFetch(Team.class); 
            return teams;
        }
    } 
 
    @Override
    public Team getTeam(Integer teamId) {
        try (  
              Connection conn = sql2o.open()) {   
              Team team = conn.createQuery("select * from teams where team_id = :teamId") 
              .addParameter("team_id",teamId);  
              .executeAndFetch(Team.class);   
              return teams;
        }
    }
  }
 
A few comments:
  1. when we want to execute several operations atomically (i.e., so if one fails no changes are persisted) we use a transaction, otherwise we just open a connection. We use the try-resource mechanism introduced in Java 8, so whatever happens transactions and connections are closed for us. 
  2. our queries a micro-templates where values preceded by a colon are replaced by the values specified using addParameter
  3. when we do a select we can use executeAndFetch and Sql2o will auto-magically map the result, creating a list of objects of the given type and setting the fields corresponding to the names of the columns. We can also map to simple types like a Strings when we have just one column
This is probably all you need to know about Sql2o to write pretty complex services. Maybe you just need to refresh your SQL.
 

Controllers

At this point we just need to use our model. Let’s see how to write the main method of our application:
 
public static void main( String[] args) {
    CommandLineOptions options = new CommandLineOptions();
    new JCommander(options, args);

    logger.finest("Options.debug = " + options.debug);
    logger.finest("Options.database = " + options.database);
    logger.finest("Options.dbHost = " + options.dbHost);
    logger.finest("Options.dbUsername = " + options.dbUsername);
    logger.finest("Options.dbPort = " + options.dbPort);
    logger.finest("Options.servicePort = " + options.servicePort);

    port(options.servicePort);

    Sql2o sql2o = new Sql2o("jdbc:mysql://" + options.dbHost + ":" + options.dbPort + "/" + options.database,
            options.dbUsername, options.dbPassword, null);

    Model model = new Sql2oModel(sql2o);
 
    // insert a team (using HTTP post method)
    post("/teams", (request, response) -> {
        ObjectMapper mapper = new ObjectMapper();
        Team creation = mapper.readValue(request.body(), Team.class);
        if (!creation.isValid()) {
            response.status(HTTP_BAD_REQUEST);
            return "";
        }
        Integer teamId = model.createTeam(creation.getTeamName(), creation.getPlayerName());
        response.status(200);
        response.type("application/json");
        return teamId;
    });

 
    // get all team (using HTTP get method)
    get("/teams", (request, response) -> {
        response.status(200);
        response.type("application/json");
        return dataToJson(model.getAllTeams());
    }); 
   
    get("/teams/:teamId", (request, response) -> {
        Team team = model.getTeam(request.params(":teamId"));
        if (!model.getTeam(teamId)) {
            response.status(400);
            return "";
        }
        response.status(200);
        response.type("application/json");
        return dataToJson(model.getTeam(teamId));
    });

 }

A few comments:
  • We start by parsing our arguments. The class CommandLineOptions is not shown (but it is present on the GitHub repository). Basically JCommander takes our command line parameters and map them to field of CommandLineOptions. In this way we can specify the address or the port of the database when launching the application.
  • We configure Sql2o and instantiate our Model. Pretty straightforward.
  • As we saw in our first tutorial we use Jackson to parse the body of our requests into Java beans. Each of them has a method called isValid. We use it to see if the request is acceptable.
  • Once we have an object representing the data associated to the request, we basically pass the content to some call of the model.
  • Possibly we return the result of some call to model. We convert the Java beans to JSONstrings using dataToJson (again, look it up on GitHub for the code).

A complete example

We start the application by running:
mvn exec:java -Dexec.args="--db-host myDBServer --db-port 3306"
 You will need to adapt the parameters to point to your database server. If everything works fine you should be able to invoke your service.

13 comments:

  1. Hey thanks for posting such an informative blog. Please share more frequently so that people looking to gain more knowledge can actually gain some. Keep up the good work.
    Php training in Chennai||Php course in Chennai

    ReplyDelete
  2. Many mistake HTML as a programming language but rather its a markup language and not progaramming language. HtML5 is the latest and technically most advanced version of HTML. To know more
    html5 training in chennai|html5 training chennai|html5 course in chennai

    ReplyDelete
  3. The main thing which i like about web designing is that itneeds creativity and we need to work differently acccording to our clients need this needs a creativity and innovation.
    web designing course in chennai|web designing training in chennai|web designing courses in chennai

    ReplyDelete
  4. After the website s completed it is very impoprtant to market it. Be it a brand or a website, if you want to reach a large audiece then effective marketive should done and this can be achieved by SEO.
    Seo training in chennai|Seo training|Seo courses in chennai|Seo training chennai

    ReplyDelete
  5. As the world is constantly getting advanced digitally for every brand or a company it is very improtant to mark their presence online. not only to mark their presence they also have to be very active on the web so that they can have a conversation with their clients/customers and solve their problems or improve their service.
    Digital Marketing Training in Chennai|Digital Marketing Course in Chennai|Digital Marketing Chennai

    ReplyDelete
  6. AngularJs is an open source framework which is used to add details to the website. AngularJs is supported by google which a major advantage to the developers.
    Regards,
    angularjs training in Chennai | angularjs training | FITA Academy reviews

    ReplyDelete
  7. Thanks for links to my article and the nice wrap up

    ReplyDelete
  8. I ‘d mention that most of us visitors are endowed to exist in a fabulous place with very many wonderful individuals with very helpful things.
    java training in chennai

    ReplyDelete
  9. Hello! This is my first visit to When I initially commented, I clicked the “Notify me when new comments are added” checkbox and now each time a comment is added I get several your blog!
    nebosh course in chennai

    ReplyDelete
  10. Hello there! This is my first comment here, so I just wanted to give a quick shout out and say I genuinely enjoy reading your articles.
    health and safrety courses in chennai

    ReplyDelete
  11. I and my friends were going through the nice, helpful tips from the blog then the sudden came up with an awful suspicion I never expressed respect to the website owner for those secrets.
    occupational health and safety course in chennai

    ReplyDelete