Domain Modelling Patterns

Image
There are two main patterns for organizing business logic: the procedural Transaction script pattern, and the object-oriented Domain model pattern. 1. Transaction script pattern: An important characteristic of this approach is that the classes that implement behavior are separate from those that store state. When using the Transaction script pattern, the scripts are usually located in serviceclasses, which in this example is the OrderService class. A service class has one method for each request/system operation. The method implements the business logic for that request. It accesses the database using data access objects (DAOs), such as the OrderDao. The data objects, which in this example is the Order class, are pure data with little or no behavior. This style of design is highly procedural and relies on few of the capabilities of objectorientedprogramming (OOP) languages. This what you would create if you were writing the application in C or another non-OOP language. Neverthe

DropWizard Tutorial

In this article I will discuss about dropwizard , how to implement a simple application using dropwizard.

Dropwizard is a simple tool to develop reliable web applications with minimal maintainance and is easy to learn,implement.

It includes:
  • Jetty, a high-performance HTTP server.
  • Jersey, a full-featured RESTful web framework.
  • Jackson, the best JSON library for the JVM.
  • Metrics, an excellent library for application metrics.
  • Guava, Google’s excellent utility library.
  • Logback, the successor to Log4j, Java’s most widely-used logging framework.
  • Hibernate Validator, the reference implementation of the Java Bean Validation standard.  

Moving head on to the implementation part ; each dropwizard application must have below components to expose rest api(s):

1. Configurations in yaml format
2. Application configuration (This contains all the configuration files required by your application )
3. POJOs required for data transmission
4. Resource Files to expose your apis
5. Application File

We will be implementing some GET,POST apis using dropwizard to understand the implementation part.Follow up with below steps to create a simple LinkRepository application in Java.

1. Create a new maven project in your favourite IDE.

Below I have added configuration for mysql db and configuration for welcome page

pom.xml

#To connect to mysql db
MysqlDBconfiguration:  
  host: localhost
  port: 3306
  username: root
  password:  dbname: test
#Some other configuration
welcomeConfiguration:  
  template: Welcome , %s
  defaultname: Anonymous

#To start jetty server on port 9000
server:  
  applicationConnectors:  - type: http
    port: 9000
  adminConnectors:  - type: http
    port: 9001
2. Next we need to create java configuration classes for each of our configurations to fetch and use the data in the yaml.

Note:To keep your configuration file and class manageable, it is recommended that you group related configuration parameters into independent configuration classes and then plug into the Application Configuration class.

Create a package named configuration with these java files:

DbConfiguration.java

package configuration;

import org.hibernate.validator.constraints.NotEmpty;

public class DbConfiguration {

    @NotEmpty    
    private String host;
    private int port;
    private String username;
    private String password;
    private String dbname;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getDbname() {
        return dbname;
    }

    public void setDbname(String dbname) {
        this.dbname = dbname;
    }
}

WelcomeConfiguration.java

package configuration;


import org.hibernate.validator.constraints.NotEmpty;

public class WelcomeConfiguration {

    @NotEmpty    
    String template;
    @NotEmpty    
    String defaultname;

    public String getTemplate() {
        return template;
    }

    public void setTemplate(String template) {
        this.template = template;
    }

    public String getDefaultname() {
        return defaultname;
    }

    public void setDefaultname(String defaultname) {
        this.defaultname = defaultname;
    }
}

And to bind these configurations
ApplicationConfiguration.java

package configuration;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.dropwizard.Configuration;

public class ApplicationConfiguration extends Configuration {

    DbConfiguration dbConfiguration = new DbConfiguration();
    WelcomeConfiguration welcomeConfiguration = new WelcomeConfiguration();


    @JsonProperty("MysqlDBconfiguration")
    public DbConfiguration getDbConfiguration() {
        return dbConfiguration;
    }

    @JsonProperty("MysqlDBconfiguration")
    public void setDbConfiguration(DbConfiguration dbConfiguration) {
        this.dbConfiguration = dbConfiguration;
    }

    public WelcomeConfiguration getWelcomeConfiguration() {
        return welcomeConfiguration;
    }

    public void setWelcomeConfiguration(WelcomeConfiguration welcomeConfiguration) {
        this.welcomeConfiguration = welcomeConfiguration;
    }
}

Note:

1. The @NotNull, @NotEmpty, @Min, @Max, and @Valid annotations are part of Dropwizard Validation functionality. If your YAML configuration file’s field was missing (or was a blank string), Dropwizard would refuse to start and would output an error message describing the issues.


2. Both the getters and setters for template and defaultName are annotated with @JsonProperty, which allows Jackson to both deserialize the properties from a YAML file but also to serialize it.
The mapping from YAML to your application’s Configuration instance is done by Jackson. This means your Configuration class can use all of Jackson’s object-mapping annotations. The validation of @NotEmpty is handled by Hibernate Validator, which has a wide range of built-in constraints for you to use.



          WelcomeConfiguration    DbConfiguration        ...... any other configuration
                                                         I
                                                         I
                                                         I
                                          ApplicationConfiguration

3. Create the POJOs named Link and Welcome ; that we will be using to perform get/post operations in our application. Getters are annotated with @JsonProperty  which allows Jackson to serialize and deserialize from JSON. Note that there is empty constructor which is needed for Jackson’s deserialization; this will be particularly required if we want to pass Link as an input to any post api call.

package DTO;

import com.fasterxml.jackson.annotation.JsonProperty;

public class Link {
    String url;
    String description;

    public Link(String url, String description) {
        this.url = url;
        this.description = description;
    }

    public Link() {
    }

    @JsonProperty    
    public String getUrl() {
        return url;
    }

    @JsonProperty    
    public void setUrl(String url) {
        this.url = url;
    }

    @JsonProperty    
    public String getDescription() {
        return description;
    }

    @JsonProperty    
    public void setDescription(String description) {
        this.description = description;
    }
}


package DTO;

public class Welcome {
    String value;

    public Welcome(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}
3.  Create a resource file ; resource file is where you will actually define your get/post apis

package resources;

import DTO.Link;
import DTO.Welcome;
import app.datastore.LinkDataStore;
import com.codahale.metrics.annotation.Timed;
import com.google.common.base.Optional;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;

@Path("/linkrepoapp")
@Produces(MediaType.APPLICATION_JSON)
public class LinkRepositoryResource {
    private final String defaultName;
    private final String template;
    private final LinkDataStore linkDataStore;

    public LinkRepositoryResource(String defaultName, String template, LinkDataStore linkDataStore) {
        this.defaultName = defaultName;
        this.template = template;
        this.linkDataStore = linkDataStore;
    }

    @GET    
    @Timed    
    @Path("/welcome")
    public Welcome call(@QueryParam("name") Optional<String> name){
        final String value = String.format(template, name.or(defaultName));
        return new Welcome(value);
    }

    @GET      
    @Timed    
    @Path("/getByUrl")
    public Link call(@QueryParam("url") String url){
        return linkDataStore.getLinkFromRepo(url);
    }

    @POST    
    @Timed    
    @Path("/save")
    @Produces(MediaType.TEXT_PLAIN)
    @Consumes({MediaType.APPLICATION_JSON})
    public String addLink(Link link) {
        linkDataStore.saveLinkInRepo(link.getUrl(), link.getDescription());
        return "Stored in database!";
    }
}




4. Finally , create an application class. Application class is where you will register all your resources and configurations with jersey.

package app;

import app.datastore.LinkDataStore;
import configurations.ApplicationConfiguration;
import configurations.DbConfiguration;
import configurations.WelcomeConfiguration;
import io.dropwizard.Application;
import io.dropwizard.setup.Environment;
import resources.LinkRepositoryResource;

public class LinkRepositoryApplication extends Application<ApplicationConfiguration>{

    @Override    
    public void run(ApplicationConfiguration applicationConfiguration, Environment environment) throws Exception {

        DbConfiguration dbConfiguration = applicationConfiguration.getDbConfiguration();
        WelcomeConfiguration welcomeConfiguration = applicationConfiguration.getWelcomeConfiguration();

        // Register all configurations with jersey        
        environment.jersey().register(dbConfiguration);
        environment.jersey().register(welcomeConfiguration);

        LinkDataStore linkDataStore = new LinkDataStore(dbConfiguration.getHost(), dbConfiguration.getDbname(), dbConfiguration.getPassword(),
                dbConfiguration.getUsername(), dbConfiguration.getPort());
        // Register all resources with jersey        
        environment.jersey().register(new LinkRepositoryResource(welcomeConfiguration.getDefaultname(), welcomeConfiguration.getTemplate(),
                linkDataStore));

    }

    public static void main(String[] args) throws Exception {
        new LinkRepositoryApplication().run(args);
    }
}



Finally execute the code with below program argument
server path_to_my_yaml_file/configuration.yml


Testing your code:

1. /welcome api

You can directly check this by hitting below url:

http://localhost:9000/linkrepoapp/welcome?name=Akash

If everything is fine you will get below response:

{"value":"Welcome , Akash"}

2. /save api

Make sure you have mysql installed ; also create a database and table according to the configs you plugged in the yaml for mysql.
You may use below DDL to create table:


create table Link(    link_id INT NOT NULL AUTO_INCREMENT,    url VARCHAR(100) NOT NULL,    description VARCHAR(100) NOT NULL,    PRIMARY KEY ( link_id ) );


Below is a sample post api call using postman:


If everything is fine you will get below response:


3. /getByUrl api

You can check this by hitting below url:

http://localhost:9000/linkrepoapp/getByUrl?url=abcd.def

If everything is fine you will get below response:

{"url":"abcd.def","description":"some description"}

Hope you liked the above tutorial ; if any questions please comment below.















Comments

Popular posts from this blog

Guice Tutorial

Introduction to Kafka

Ruby Syntax Cheat Sheet