Saturday 8 September 2018

Spring Boot SSL configuration -Tomcat Server

Hi Friends hope you all are doing well. Today I am going to demonstrate about how to configure SSL in Spring boot web Application.

Need of SSL communication arises to transmit data between web client and web server in secure manner. data exchange between both parties will be encrypted in SSL communication.  I am going to use keytool to generate certificates locally. i will generate self signed certificate. however in production we need to get certificate from certification authorities.

keystore can be of PKS12 or JKS. in this example i am going to use pks12 Keystore.

I am going to use java base configuration to  configure SSL communication.

Technology stack being used :
1) Spring Boot 1.4.1 Release
2) Spring 4.2
3) Maven 3.2.1
4) JDK 1.7
5) Apache tomcat
6) Keytool

Project Structure is given below :



There are some steps that need to be followed to generate certificate .given below:

1) keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12

You then will be asked to enter a password for the keystore. It must have at least 6 characters.

Finally, you will be asked to input some information, but you are free to skip all of it 
In the place of the first and last name, you may want to insert the base name of your host (in my case it is localhost).


Below is the code given :

Application.java : main class to run Spring Boot Application

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package org.test.ssl.SslSpringConfig;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


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

you need to configure ssl communication in application.properties.

1
2
3
4
5
6
server.port=8443
security.require-ssl=true
server.ssl.key-store-type=PKCS12
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=test@123
server.ssl.key-alias=tomcat

Below is the configuration file to route HTTP request to HTTPS.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package org.test.ssl.SslSpringConfig;

import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ConnectorConfig {

 @Bean
  public EmbeddedServletContainerFactory servletContainer() {
  TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
  @Override
  protected void postProcessContext(Context context) {
  SecurityConstraint securityConstraint = new SecurityConstraint();
  securityConstraint.setUserConstraint("CONFIDENTIAL");
  SecurityCollection collection = new SecurityCollection();
  collection.addPattern("/*");
  securityConstraint.addCollection(collection);
  context.addConstraint(securityConstraint);
  }
  };
  tomcat.addAdditionalTomcatConnectors(getHttpConnector());
  return tomcat;
  }
  
  private Connector getHttpConnector() {
  Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
  connector.setScheme("http");
  connector.setPort(8099);
  connector.setSecure(false);
  connector.setRedirectPort(8443);
  return connector;
  }
}

below is controller to test SSL configuration :


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package org.test.ssl.SslSpringConfig;


import java.util.Date;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SecuredServerController {
  @RequestMapping("/secure")
     public String secured(){
         return "Hello user ,you are secured";
     }
  
}

when you trying to hit localhost:8099/secured you will be redirected to 8443 SSL port.

 Thanks for reading this article . for any query ping me on npjava90@gmail.com

Wednesday 11 April 2018

Spring Boot Rest Basic Security implementation

Hi Friends hope you all are doing well. Today I am going to demonstrate you about implementation of Basic  security for Spring Boot Rest Service,

Basic Authentication : where authentication header is added which contains combination of username and password  in format as : authentication username:password  in encrypted form. whenever you call REST API ,you need to present username and password in order to gain access to that API. There may be requirement that endpoint URL which are exposed as REST API need to best secured. that's all.
let's go ahead with coding part.

I am going to use  java based configuration in order to setup spring security in this example.

Technology stack is being used:
1) Spring Boot 1.4.1 Release
2) Spring 4.2
3) Spring Security  4.0
4) Maven 4.0
5) JDK 1.7
6) Postman Rest Client Project Structure is  as given below :



Below is the code given :
Application.java : main class to run Spring Boot Application

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package com.basicSecurity.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan(basePackages = "com.basicSecurity")
@SpringBootApplication

public class Application extends SpringBootServletInitializer{

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

}

ApplicationInitializer.java : used to initialize front controller of Spring boot application

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.basicSecurity.config;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
//WebApplicationInitializer used to init front controller  programatically

public class ApplicationInitializer implements WebApplicationInitializer {

    public void onStartup(ServletContext container) throws ServletException {

        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.setServletContext(container);
        ServletRegistration.Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(ctx));
        servlet.setLoadOnStartup(1);
        servlet.addMapping("/");
    }
}


AuthenticationEntryPoint.java : will be triggered when wrong/invalid credentials passed.




 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.basicSecurity.config;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
import org.springframework.stereotype.Component;

//BasicAuthenticationEntryPoint that will be triggered when wrong credentials passed & response will be returned

@Component
public class AuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
 @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
      throws IOException, ServletException {
  
        response.addHeader("WWW-Authenticate", "Basic realm=" +getRealmName());
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        PrintWriter writer = response.getWriter();
        writer.println("HTTP Status 401:" + authEx.getMessage());
    }
 
 @Override
    public void afterPropertiesSet() throws Exception {
        setRealmName("nppstack");
        super.afterPropertiesSet();
    }

}

SpringSecurityConfig.java : WebSecurityConfigurerAdapter class used for intializing spring security features using java configuration.





 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.basicSecurity.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
//WebSecurityConfigurerAdapter and  @EnableWebSecurity work together  
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

 @Autowired
 private AuthenticationEntryPoint authEntryPoint;
 
 @Override
 protected void configure(HttpSecurity http) throws Exception {
  http.authorizeRequests()
    .anyRequest().authenticated()
    .and().httpBasic()
    .authenticationEntryPoint(authEntryPoint);
  
 }

 @Autowired
 public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  auth.inMemoryAuthentication().withUser("npp").password("npp").roles("USER");
 }

}


StudentController.java : Spring Boot Controller

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.basicSecurity.controller;

import java.util.Arrays;
import java.util.List;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.basicSecurity.model.Student;

@Controller
public class StudentController {
 
 @RequestMapping(path="/Student", method = RequestMethod.GET)
 public ResponseEntity<List<Student>>  listStudent(){
  return new ResponseEntity<List<Student>>(getStudents(), HttpStatus.OK);
 }
 
 @RequestMapping(path="/Student/{id}", method = RequestMethod.GET)
 public ResponseEntity<List<Student>>  listStudent(@PathVariable(value = "id") String id){
  List<Student> Students = getStudents();
        if(Students.isEmpty()){
            return new ResponseEntity<List<Student>>(HttpStatus.NO_CONTENT);
        }
        return new ResponseEntity<List<Student>>(Students, HttpStatus.OK);
  
 }
 
 private List<Student> getStudents() {
  Student Student1 = new Student();
  Student1.setId("1");
  Student1.setEmail("np90@gmail.com");
  Student1.setName("nisarg");
  Student1.setAddress("Bangalore, Karnataka");
  
  Student Student2 = new Student();
  Student2.setId("2");
  Student2.setEmail("mohitp@yahoo.com");
  Student2.setName("Mohit patel");
  Student2.setAddress("Orissa");
  
  Student Student3 = new Student();
  Student3.setId("3");
  Student3.setEmail("krishnkumar@gmail.com");
  Student3.setName("krishn kumar");
  Student3.setAddress("Bangalore, Karnataka");
  
  Student Student4 = new Student();
  Student4.setId("4");
  Student4.setEmail("prakashshah@gmail.com");
  Student4.setName("Prakash shah");
  Student4.setAddress("Ahmedabad, Gujarat");
  return Arrays.asList(Student1, Student2, Student3, Student4);
 }

}

Student.java : Plain Java Object used


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.basicSecurity.model;

public class Student {

 private String id;
 private String name;
    private String address;
    private String email;
    
    public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

}

now I am going to test this application using POSTMAN Client:

invalid credentials : error message  will come in response



valid credentials : Response will be obtained


Thanks for going through this article. for any query ping me on npjava90@gmail.com


Saturday 24 March 2018

Microservices using Spring Cloud/Spring Boot

Hello Friends hope you all are doing well. Today I am going to discuss about a very hot topic now a days -Microservice. Let's look into this.

Before  moving to Microservice Architecture ,we will discuss regarding Monolithic  Architecture.
In Monolithic Architecture we have a single deployable unit ,frequent changes in business needs lead to do deployment of application as a whole in order to make functionality work.

There are several pitfalls of monolithic architecture which are addressed by Microservice Architecture:

Agility : frequent changes in business needs hamper agility .even with small changes entire  application need to be repacked and assembled at the cost of reducing agility.

Scalability : Let's take a example of Shopping cart.there are various customer's for which unit has to be changed to incorporate a new customer there by reducing scalability of entire application.

Dev-ops Cycle  :  as there is a single deployable unit,even small change lead to deploy whole application again .there by  increasing effort time.

To address all this issues ,Microservice Architecture comes into picture where as modules are deployed as individual components .below is the Monolithic VS Microservice architecture.


below is the microservice eco system drawn for shopping cart service:



I am going to achieve Microservice Architecture using Spring boot and Spring Cloud module.

Technology stack is being used:

1) Spring Boot 1.4.1 Release
2) Spring Cloud
3) Spring 4.0
4) Spring JDBC
5) Maven 4.0
6) JDK 1.7

Spring Cloud has predefined list of components which will be used to address issues that we face in Monolithic architecture.I am going to use  below Components for this application:

(1)Netflix Eureka - Service Registration /Service  Discovery,
(2) Hystrix - For Load Balancing/Fault tolerance
(3) Zuul  - act as a API  gateway ,request will be routed through ZUUL.

localhost Port of each service as given below:

components Port
Eureka registry 8111
Producer 8112
Consumer  8113
zuul api gateway 8114


in this example ,I am going to expose  one  Rest End Point which will act as a producer and another will act as a consumer which will retrieve college details of particular student from Producer Microservice.

Project Structure of each micro service is as given below :




Below is the code given :
Eureka Registry :

EurekaServerApplication.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package org.main;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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


application.prerties:
1
2
3
4
5
spring.application.name=eureka-server
server.port=8111
eureka.client.serviceUrl.defaultZone=http://localhost:8111/eureka
eureka.client.registerWithEureka=true
eureka.client.fetchRegistry=false

pom.xml :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>org.server</groupId>
 <artifactId>eureka-server</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>eureka-server</name>
 <description>Demo project for Spring Boot</description>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.2.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
 </parent>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <!-- <java.version>1.8</java.version> -->
 </properties>

 <dependencies>
  <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-eureka-server</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>
 </dependencies>

 <dependencyManagement>
  <dependencies>
   <dependency>
   <groupId>de.codecentric</groupId>
   <artifactId>spring-boot-admin-starter-client</artifactId>
   <version>1.5.1</version>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
  </dependency>
  
   <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>Camden.SR6</version>
    <type>pom</type>
    <scope>import</scope>
   </dependency>
  </dependencies>
 </dependencyManagement>

 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>


</project>


Producer Microservice is as given below :

Model Class:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.example.hystrix.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Student implements Serializable {

 /**
  * 
  */
 private static final long serialVersionUID = 1L;
 
 @Id @GeneratedValue
 private String id;
 @Column
 private String name;
 @Column
 private String college;
 
 public Student()
 {
  
 }
 public Student(String id ,String name,String college)
 {
  this.id = id ;
  this.name = name ;
  this.college = college;
  
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public String getCollege() {
  return college;
 }
 public void setCollege(String college) {
  this.college = college;
 } 
 
 
 
}

Controller :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.example.hystrix.springhystrixstudentservice.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.example.hystrix.model.Student;
import com.example.hystrix.springhystrixstudentservice.dao.StudentDAOImpl;

@RestController
public class StudentServiceController {

 @Autowired
 StudentDAOImpl dao;

 @RequestMapping(value = "/getStudentDetailsForSchool/{college}", method = RequestMethod.GET)
 public List<Student> getStudents(@PathVariable String college) {
  System.out.println("Getting Student details for " + college);
  

  List<Student> studentList = dao.getStudent(college);
  System.out.println("size: " + studentList.size());
  if (studentList == null) {
   studentList = new ArrayList<Student>();
   Student std = new Student("Not Found", "N/A","N/A");
   studentList.add(std);
  }
  return studentList;
 }
}

Data Access Layer is as given below :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.example.hystrix.springhystrixstudentservice.dao;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.example.hystrix.model.Student;

@Repository
public class StudentDAOImpl {

 @Autowired
 public  JdbcTemplate template;

 

 
 public List<Student> getStudent(String college)  {
  String sql = "select * FROM student where college=?";
  System.out.println("college from dao" +college);
  List<Student> listStudent = new ArrayList<Student>();

  List<Map<String, Object>> rows = template.queryForList(sql, new Object[]{college});
  
  
  for (Map row : rows) {
   Student stud = new Student();
   stud.setId((String)(row.get("id")));
   stud.setName((String)row.get("name"));
   stud.setCollege((String)row.get("college"));
   listStudent.add(stud);
  }

  return listStudent; 
 }
 
}

Spring boot main class as given below :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package com.example.hystrix.springhystrixstudentservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

//@EnableDiscoveryClient
@EnableEurekaClient
@SpringBootApplication
public class SpringHystrixStudentServiceApplication {

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

application.properties is as given below : 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
server.port = 8112
spring.datasource.url = jdbc:mysql://localhost:3306/studentdb
spring.datasource.username = root
spring.datasource.password = admin!@#
# Keep the connection alive if idle for a long time (needed in production)
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = update
eureka.client.serviceUrl.defaultZone=http://localhost:8111/eureka
spring.application.name=student-producer

pom.xml :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>com.example.hystrix</groupId>
 <artifactId>spring-hystrix-student-service</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>SpringBootHelloWorld</name>
 <description>Demo project for Spring Boot</description>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.4.1.RELEASE</version>
  <relativePath /> <!-- lookup parent from repository -->
 </parent>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

 </properties>

 <dependencies>

  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-eureka</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>
 
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.6</version>
  </dependency>

 </dependencies>

 <dependencyManagement>
  <dependencies>
   <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>Camden.SR6</version>
    <type>pom</type>
    <scope>import</scope>
   </dependency>
  </dependencies>
 </dependencyManagement>


 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>

</project>

Consumer Microservice is as given below:

 Controller:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.example.hystrix.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.example.hystrix.service.StudentService;

@RestController
public class CollegeController {

 @Autowired
 StudentService service;
 @Autowired
 private DiscoveryClient discoveryClient;

 @RequestMapping(value = "/student/getSchoolDetails/{schoolname}", method = RequestMethod.GET)
 public String getStudents(@PathVariable String schoolname) {

  List<ServiceInstance> instances = discoveryClient
    .getInstances("student-zuul-service"); 
  ServiceInstance serviceInstance = instances.get(0);

  String baseUrl = serviceInstance.getUri().toString();
  System.out.println("URI IS :"+serviceInstance.getUri()+"base url is : "+baseUrl);
  baseUrl = baseUrl + "/getStudentDetailsForSchool/{college}";
  return service.getStudentData(baseUrl, schoolname);
 }

}

Service class is as below:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.example.hystrix.service;

import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@Service
public class StudentService {
 @Autowired
 RestTemplate restTemplate;
 
 @HystrixCommand(fallbackMethod = "getStudentData_Fallback")
 public String getStudentData(String baseUrl, String college) {
  //http://localhost:8112/getStudentDetailsForSchool/{college}
  
  baseUrl="http://localhost:8112/getStudentDetailsForSchool/{college}";
  String response = restTemplate
    .exchange(baseUrl
    , HttpMethod.GET
    , null
    , new ParameterizedTypeReference<String>() {
   }, college).getBody();

  

  return "Circuit Breaker is not active for : "+ response +" at : "+ new Date();
 }
 
 @SuppressWarnings("unused")
 private String getStudentData_Fallback(String baseUrl,String schoolname) {
  System.out.println("Student Service is down!!! fallback route enabled...");
  return "CIRCUIT BREAKER ENABLED!!!No Response From Student Service at this moment. Service will be up soon - " + new Date();
 }

 @Bean
 public RestTemplate restTemplate() {
  return new RestTemplate();
 }
}

Spring  Boot Main Application:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package com.example.hystrix;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@EnableAutoConfiguration
@SpringBootApplication
@EnableHystrixDashboard
@EnableCircuitBreaker
@EnableEurekaClient
public class SpringHystrixSchoolServiceApplication {

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

application.properties :
1
2
3
server.port = 8113
spring.application.name=student-consumer
eureka.client.serviceUrl.defaultZone=http://localhost:8111/eureka

pom.xml :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>org.zuul</groupId>
 <artifactId>student-zuul-service</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>SpringBootHelloWorld</name>
 <description>Demo project for Spring Boot</description>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.4.1.RELEASE</version>
  <relativePath /> <!-- lookup parent from repository -->
 </parent>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  
 </properties>

 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-zuul</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-eureka</artifactId>
  </dependency>

 </dependencies>

 <dependencyManagement>
  <dependencies>
   <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>Camden.SR6</version>
    <type>pom</type>
    <scope>import</scope>
   </dependency>
  </dependencies>
 </dependencyManagement>


 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>

</project>

ZUUL -API Gateway  :

Controller :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package org.zuul;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
import org.zuul.filter.ErrorFilter;
import org.zuul.filter.PostFilter;
import org.zuul.filter.PreFilter;
import org.zuul.filter.RouteFilter;

@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class SpringBootHelloWorldApplication {

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

 @Bean
 public PreFilter preFilter() {
  return new PreFilter();
 }

 @Bean
 public PostFilter postFilter() {
  return new PostFilter();
 }

 @Bean
 public ErrorFilter errorFilter() {
  return new ErrorFilter();
 }

 @Bean
 public RouteFilter routeFilter() {
  return new RouteFilter();
 }
}

application.properties 
1
2
3
4
5
zuul.routes.student.url=http://localhost:8112
eureka.client.serviceUrl.defaultZone=http://localhost:8111/eureka
ribbon.eureka.enabled=false
server.port=8114
spring.application.name=student-zuul-service

Order in which application will run given below :

1)eureka-server
2)spring-hystrix-student-service
3)spring-student-zuul-service
4)spring-hystrix-college-service

below is the screenshot :
-> eureka registry started: Producer and Consumer microservice registered with Eureka Registry.



output returned by consumer



Hope you enjoyed article. For any query ping me on npjava90@gmail.com














Sunday 11 March 2018

Spring Boot Rest service with spring jdbc

Hi Friends,I am going to introduce Rest Service using Spring Boot.

Following technology being used:
1)Spring Boot 1.4.1.RELEASE
2)Spring 4.0
3)Maven 4.0
4)JDK 1.7

Project Structure:


Dependency Management:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>org.demo</groupId>
 <artifactId>test</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>SpringBootHelloWorld</name>
 <description>Demo project for Spring Boot</description>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.4.1.RELEASE</version>
  <relativePath /> <!-- lookup parent from repository -->
 </parent>

Typical Spring boot application is as given below :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package org.main;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@EnableAutoConfiguration
@SpringBootApplication(scanBasePackages={"org.test"})
public class main {

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

5 Endpoints are exposed in below rest controller .summary of each is as given below :
Endpoints Description
localhost:8098/student/getAll API that returns all student
localhost:8098/student/get/{id} Api that return student based on id 
localhost:8098/student/add/{id} API that adds student
localhost:8098/student/updte/{id} API that updates student
localhost:8098/student/delete/{id} API that deletes student

Rest Controller :


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package org.test.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;
import org.test.bean.Student;
import org.test.dao.StudentDAOImpl;

@EnableAutoConfiguration
@RestController
public class StudentController {

 @Autowired
 private StudentDAOImpl dao;
 
 @GetMapping("/student/getAll")
 public ResponseEntity<List<Student>> getAllStudents() 
 {
  
 List<Student> listStudents= dao.getAllStudents();
 if(listStudents.size()==0)
  return new ResponseEntity<List<Student>>(HttpStatus.NOT_FOUND);
 
 return new ResponseEntity<List<Student>>(listStudents,HttpStatus.OK);
 }
 @GetMapping("/student/get/{id}")
 public ResponseEntity<Student> getStudent(@PathVariable("id") String id) 
 {
 Student stud = dao.getStudent(id); 
 if(stud==null)
  return new ResponseEntity<Student>(HttpStatus.NOT_FOUND);

 return new ResponseEntity<Student>(stud,HttpStatus.OK);
 
 }
 @PostMapping("/student/add/{id}")
 public ResponseEntity<?> addStudent(@RequestBody Student student, UriComponentsBuilder ucBuilder) 
 {
 Student stud = dao.addStudent(student); 
 if(stud==null)
  return new ResponseEntity<Student>(HttpStatus.NOT_FOUND);
 HttpHeaders headers = new HttpHeaders();
    headers.setLocation(ucBuilder.path("/student/user/{id}").buildAndExpand(student.getId()).toUri());
 return new ResponseEntity<String>(headers,HttpStatus.CREATED);
 
 
 }
 
 @PutMapping("/student/updte/{id}")
 public ResponseEntity<?> updateStudent(@PathVariable("id")String id ,@RequestBody Student student) 
 {
 
 int rowcount=dao.updateStudent(id,student);
 
 if(rowcount==0)
  return new ResponseEntity(new CustomMessage("Unable to upate. Student with id " + id + " not found."),HttpStatus.NOT_FOUND);
 else 
 return new ResponseEntity<Student>(student,HttpStatus.OK);
 
 }
 @DeleteMapping("/student/delete/{id}")
 public ResponseEntity<?> deleteStudent(@PathVariable("id") String id) 
 {
 Student obj = dao.getStudent(id); 
 if(obj==null)
  return new ResponseEntity(new CustomMessage("Unable to delete Student with id " + id + " not found."),HttpStatus.NOT_FOUND);
  

 dao.deleteStudent(id);
 return new ResponseEntity<Student>(HttpStatus.NO_CONTENT); 
 } 
}

DAO layer is given below :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package org.test.dao;

import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.test.bean.Student;

@Repository
public class StudentDAOImpl {

 @Autowired
 public  JdbcTemplate template;

 public Student addStudent(Student student) {
  // TODO Auto-generated method stub
  
  String sql="insert into student(id,name,college,status) values(?,?,?,'A')"; 
        template.update(sql,new Object[]{student.getId(),student.getName(),student.getCollege()});
  return student;
 }

 public int updateStudent(String id, Student stud) {
  // TODO Auto-generated method stub
        int[] types = {Types.VARCHAR, Types.VARCHAR,Types.VARCHAR};
  String sql = "update student set name = ? ,college =? where id = ?";
  int rows = template.update(sql,new Object[]{stud.getName(),stud.getCollege(),id},types);
  
        System.out.println(rows + " row(s) updated.");        
  return rows;
 }

 public void deleteStudent(String id) {
  String sql="delete from student where id=?";
  template.update(sql,id);  
 }

 public Student getStudent(String id) {
  
  String sql = "SELECT * FROM student WHERE id = ?";

  Student customer = (Student) template.queryForObject(
    sql, new Object[] { id },
    new BeanPropertyRowMapper(Student.class));

  return customer;  
 }

 public List<Student> getAllStudents() {
  String sql = "select * FROM student";

  List<Student> listStudent = new ArrayList<Student>();

  List<Map<String, Object>> rows = template.queryForList(sql);
  for (Map row : rows) {
   Student stud = new Student();
   stud.setId((String)(row.get("id")));
   stud.setName((String)row.get("name"));
   stud.setCollege((String)row.get("college"));
   listStudent.add(stud);
  }

  return listStudent; 
 }
 
}

Test the API:
I will use external client POSTMAN to test the endpoints exposed .

1. Get All Students



2. Get Specific Student


3.Add student : one need to provide request body and content type as "application/json'.


4.Delete Student : No Response in Response body . HttpStatus.NO_CONTENT is returned .



Hope you like this article .for any query ping me on  npjava90@gmail.com

Spring Boot SSL configuration -Tomcat Server

Hi Friends hope you all are doing well. Today I am going to demonstrate about how to configure SSL in Spring boot web Application. Need o...