Showing posts with label Spring Framework. Show all posts
Showing posts with label Spring Framework. Show all posts

Wednesday 10 June 2020

What is Feign Client and How to use it?


Feign client what does it mean and what it exactly does and compared to the rest template how does it outstands itself and make flexible for the developers will be seen in this tutorial.


Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable annotation support including Feign annotations and JAX-RS annotations.Feign also supports pluggable encoders and decoders. Spring Cloud adds support for Spring MVC annotations and for using the same HttpMessageConverters used by default in Spring Web. Spring Cloud integrates Ribbon and Eureka to provide a load-balanced HTTP client when using Feign.


This Feign client internally creates the rest template and call the corresponding service.
One of the advantages of using Feign over RestTemplate is that, we do not need to write any implementation to call the other services. So there is no need to write any unit test as there is no code to test in the first place. However, it is advised that we write Integration tests.


There are also certain advantages such as Feign integrates with Ribbon and Eureka Automatically. Feign provides a very easy way to call RESTful services. we can also use Eureka Client ID instead of the URL and then URLs are not hardcoded.


We can see step by step procedure of calling the rest service using the feign client.
1. Download the Spring war project from the https://start.spring.io/
2. Add the following dependency.

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>

3. Create an Interface and add the methods need to be invoked.
EmployeeClient.java

package com.example.demo;
import java.util.List;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(value="employees",url = "http://localhost:7010/employees/")

public interface EmployeeClient {

@RequestMapping(method = RequestMethod.GET, value = "/all")
Employees getEmployees();

@GetMapping(value = "/employee/{id}")
List<Employee> getIdEmployees(@PathVariable(name= "id") Integer empId);

}

Here @FeignClient(value="employees",url = "http://localhost:7010/employees/")
Value is the logical name of the application which needs to be invoked. You can also mention the url in some cases this is the base url of the application.
getIdEmployees(Interger empId) is the method defined in my service class. @GetMapping is the path of the service in the class. Once this done next steps is to enable the Feign Client and call it through the controller.


4. DemoApplication.java
package com.example.demo;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;


@SpringBootApplication
@EnableFeignClients
@RequestMapping(path = "/feign")
public class DemoApplication {

@Autowired
private EmployeeClient employeeDao;

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

@GetMapping(path = "/", produces = "application/json")
public Employees getEmployees() {
System.out.println("Got**********"+employeeDao.getEmployees());
return employeeDao.getEmployees();
}

@GetMapping(path = "/employee/{id}", produces = "application/json")
public ResponseEntity<List<Employee>> getIdEmployees(@PathVariable Integer id) {
System.out.println("Got Id" + id);
List<Employee> employees = employeeDao.getIdEmployees(id);
System.out.println("Got Response as "+ employees);
return new ResponseEntity<List<Employee>>(employees, HttpStatus.OK);
}

}


Here with the annotation @EnableFeignClients we have enabled the feign client. Inject the Interface here and call the corresponding method. You can see the getIdEmployees method above for reference.

Now in the Service Layer or Service Needs to be called.

5. EmployeeController.java

@RestController
@RequestMapping(path = "/employees")
public class EmployeeController
{
@Autowired
private EmployeeDAO employeeDao;

@GetMapping(path="/all", produces = "application/json")
public Employees getEmployees()
{
return employeeDao.getAllEmployees();
}

@GetMapping(path="/employee/{id}", produces = "application/json")
public List<Employee> getIdEmployees(@PathVariable Integer id)
{
System.out.println("Called GetIdEmployee>>>>>"+id);
return employeeDao.getEmployeeId(id);
}
}



6. EmployeeDAO.java


@Repository
public class EmployeeDAO {
private static Employees list = new Employees();

static {
list.getEmployeeList().add(new Employee(1, "Syed", "rizwan", "syed@gmail.com"));
list.getEmployeeList().add(new Employee(2, "Ghouse", "basha", "ghouse@gmail.com"));
list.getEmployeeList().add(new Employee(3, "Shahin", "Kameron", "shahin@gmail.com"));
}

public Employees getAllEmployees() {
return list;
}

public void addEmployee(Employee employee) {
list.getEmployeeList().add(employee);
}

public List<Employee> getEmployeeId(int id) {
System.out.println("********* Id" + id);
Map<Integer, List<Employee>> idMap = list.getEmployeeList().stream().filter(emp -> emp.getId().equals(id))
.collect(Collectors.groupingBy(Employee::getId));
System.out.println("********* Map" + idMap);
return idMap.get(id);

}
}



Make Sure you create this employee pojo in both applications. Happy Learning !!! 

Thursday 1 August 2019

Implementing OAuth 2.0 Authentication using SpringBoot

The OAuth 2.0 provider mechanism is responsible for exposing OAuth 2.0 protected resources. The configuration involves establishing the OAuth 2.0 clients that can access its protected resources independently or on behalf of a user.

The provider role in OAuth 2.0 is actually split between Authorization Service and Resource Service, and while these sometimes reside in the same application, with Spring Security OAuth you have the option to split them across two applications, and also to have multiple Resource Services that share an Authorization Service. 

Now we start looking in to how to Implement this oauth2.0.

Maven Dependencies.

Here is my pom.xml

Since we are going to have the authorization server and client on the same application added the below dependencies.

<dependencies>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency> -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>


The following endpoints are required in the Spring Security filter chain in order to implement OAuth 2.0 Authorization Server:

1. Authorization end point. Where we get authorize by giving the proper username and password. /oauth/authorize

2.Token Endpoint.This is where we get the Token from the server./oauth/token

Authorization Server.

As you configure the Authorization Server, you have to consider the grant type that the client is to use to obtain an access token from the end-user (e.g. authorization code, user credentials, refresh token). The configuration of the server is used to provide implementations of the client details service and token services and to enable or disable certain aspects of the mechanism globally.

Create a class that extends AuthorizationServerConfigurerAdapter. Use the anotations @Configuration for making it as the configuration.
@EnableAuthorizationServer for the authorization.

Here we need to have configurer method for the below purpose.

ClientDetailsServiceConfigurer: a configurer that defines the client details service. Client details can be initialized, or you can just refer to an existing store.

eg:
@Override
    public void configure(
        ClientDetailsServiceConfigurer clients
    ) throws Exception {
        clients.inMemory()
            .withClient("client")
                .authorizedGrantTypes("password")
                .secret("{noop}secret")
                .scopes("all");
    }

AuthorizationServerSecurityConfigurer: defines the security constraints on the token endpoint.
eg:
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')").checkTokenAccess(
"hasAuthority('ROLE_TRUSTED_CLIENT')");
}


AuthorizationServerEndpointsConfigurer: defines the authorization and token endpoints and the token services.
eg:

@Override
    public void configure(
        AuthorizationServerEndpointsConfigurer endpoints
    ) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }

Here is my Authorization code.

package com.searchendeca.oauthdemo.server;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder passwordEncoder;

@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients();
}

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("client")
.secret(passwordEncoder.encode("123456"))
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.authorities("READ_ONLY_CLIENT")
.scopes("all")
.resourceIds("oauth2")
.redirectUris("http://localhost:8081/login")
.accessTokenValiditySeconds(5000)
.refreshTokenValiditySeconds(50000);
}
//in the above method you can use the jdbc confguration and fetch the data from it. I am using the Inmemory database.

}

The above configuration also avaliable in the XML as well.

Resource Server

A Resource Server (can be the same as the Authorization Server or a separate application) serves resources that are protected by the OAuth2 token. Spring OAuth provides a Spring Security authentication filter that implements this protection.

eg:
@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests().antMatchers("/login").permitAll().and()
        // default protection for all resources (including /oauth/authorize)
            .authorizeRequests()
                .anyRequest().hasRole("USER")
        // ... more configuration, e.g. for form login
    }
here is Resource Server configuration.
package com.searchendeca.oauthdemo.server;


import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;

@Configuration
@EnableResourceServer
public class ResourceServer extends ResourceServerConfigurerAdapter 
{
@Override
public void configure(HttpSecurity http) throws Exception {
http
        .authorizeRequests()
        .antMatchers("/").permitAll()
        .antMatchers("/api/v1/**").authenticated();
}
}

Now we have to configure the security configuration as we did for the basic authentication.Here is my file.

package com.searchendeca.oauthdemo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@Order(1)
public class ServerConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatchers()
          .antMatchers("/login", "/oauth/authorize")
          .and()
          .authorizeRequests()
          .anyRequest().authenticated()
          .and()
          .formLogin().permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
        .inMemoryAuthentication()
            .withUser("syed")
            .password(passwordEncoder().encode("123456"))
            .roles("USER");
    }
     
    @Bean
    public BCryptPasswordEncoder passwordEncoder(){ 
        return new BCryptPasswordEncoder(); 
    }
}

When ever it asks for the authentication we can give the username as syed and password as 123456. 

Rest Controller.

package com.searchendeca.oauthdemo.controller;

import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class RestController 
{
@Secured("ROLE_USER")
    @GetMapping(value = "/user/hello")
    public ResponseEntity<String> welcomeAppUser(@AuthenticationPrincipal User user) {
        return ResponseEntity.ok("Welcome User " + user.getUsername());
    }
}


Now its done build the application.

Access the 
Url: http://localhost:8080/oauth/authorize?client_id=client&response_type=code&scope=all

This is what we mentioned in the Authorization Server.you will get the login window give the username as syed and password as 123456. 

Once you give the next window takes to the authorization window give approve and it will give the code note it down.

eg We got http://localhost:8081/login?code=0Tccin

Next in the post man pass all this information.

Getting the access token.

http://localhost:8080/oauth/token

pass the below as headers.

Content-Type:application/x-www-form-urlencoded
authorization: Basic Y2xpZW50OjEyMzQ1Ng== // this is nothing but the base64 of client:123456 which we have mentoned in the authorization server.

Pass the below as formdata in body.

grant_type:authorization_code
code:0Tccin
redirect_uri:http://localhost:8081/login

you will get the response like below.

{
    "access_token": "afe1c541-b366-4439-bffb-1f06493c5a8e",
    "token_type": "bearer",
    "refresh_token": "7b5fbaea-cc34-4b23-a4ad-fab74ef646d0",
    "expires_in": 4999,
    "scope": "read_profile_info"
}


Pass the access token to the controller service.

http://localhost:8080/api/users/hello

with the below headers.

Authorization:Bearer afe1c541-b366-4439-bffb-1f06493c5a8e

Output: Welcome User syed

Happy Learning !!!!

Wednesday 31 July 2019

Basic Authentication using the Spring boot

Spring Security
Spring Security provides comprehensive security services for J2EE-based enterprise software applications. 

Terms to get familiar in spring security.

Principal:means a user, device or some other system which can perform an action in your application.

Authentication:It is the process of establishing a principal is who they claim to be.

Authorization:It refers to the process of deciding whether a principal is allowed to perform an action within your application.

UserRoles: User Roles are created to make sure the services which are created are not accessed by all the users. It is like we provide the restriction to the user, so he / she cannot access the particular service.

class WebSecurityConfigurerAdapter:Provides a convenient base class for creating a WebSecurityConfigurer instance. The implementation allows customization by overriding methods.

Now we can jump in to creating the basic authentication using the Spring boot.

Create a project from spring initializer, add the dependencies like web and security.

Here is My Pom.xml.

<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.searchendeca</groupId>
<artifactId>securehttp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>securehttp</name>
<description>Demo project for Spring Boot</description>

<properties>
<java.version>1.8</java.version>
</properties>

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

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

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

</project>

Here is my Security Configuration.

package com.searchendeca.securehttp.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user1").password("user1").roles("USER");
        auth.inMemoryAuthentication().withUser("user2").password("user2").roles("USER", "ADMIN");
        auth.inMemoryAuthentication().withUser("user3").password("user3").roles("USER");
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.httpBasic().
                realmName("spring-app").
                and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).
                and().csrf().disable().
                authorizeRequests().antMatchers("/user/**").permitAll().anyRequest().authenticated();

    }

    @Bean
    public NoOpPasswordEncoder passwordEncoder()
    {
        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    }
}

Controller Class.

@RestController
public class RestApiController {

 @RolesAllowed({"ROLE_USER", "ROLE_ADMIN"})
 @GetMapping(value = "/user/message")
    public String greetUser() {
        return "Welcome User ";
    }
}
The Above main class can be accessed by both user and admin respectively.
Main Class.
package com.searchendeca.securehttp;

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

@SpringBootApplication
@ComponentScan(basePackages = "com.searchendeca.*")
public class SecurehttpApplication {

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

}

Deploy the application in Tomcat

Execute and access the below Url:http://localhost:8080/user/message It asks for the user name and password, once if you enter username and password then you will be able to see the service working else you will not see this .

you can also encrypt the password in the following format(username:password) with base64 and pass as header Authorization.

eg: Authorization:Basic c3llZDp0ZXN0MTIz

Still it will work in the same way. Once you include the spring security module you can see while server startup. Using generated security password: 6a1abb58-cfd9-4e7a-bb1f-ae9f0950c8b6

If you are not defining the configure method then you can access the resources by giving the username as user and password as encrypted that was updated during the server startup.

Happy Learning!!!

Monday 29 July 2019

Working with profiles in Spring Boot

When ever we work in any application maintaing the environment specific files are very much required. In spring this can be achieved by using the profiles.

Look at the Following example. I am trying to fetch the url property and print it using the controller. To achieve this create a property files named, in the following path /src/main/resources.

application-dev.properties

url=http://mydevhost:8080/home

application-stage.properties

url=http://myStagehost:8080/home

In the application.properties define the following .

url=http://myhost:8080/home

spring.profiles.active=stage

Create a service class where you read this value as below.

package com.searchendeca.application.services;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

@Service
public class DemoService {
@Value("${url}")
private String Url;

public String getUrl() {
return Url;
}

public void setUrl(String url) {
Url = url;
}

}


Below is my Main class.

package com.searchendeca.application.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.searchendeca.application.services.DemoService;

@SpringBootApplication
public class DemoApplication {
@Bean
public DemoService getDemoService() {
return new DemoService();
}

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

@Controller
class Example {
@RequestMapping("/")
@ResponseBody
public String hello() {
return getDemoService().getUrl();
}
}

}

Now acces the Url: http://localhost:8080/

Below is the output.

http://myStagehost:8080/home

In some cases we can differentiate using the @profile anotation, this will work only the profile is passed as part of the VM argument or the application.properties

Happy Learning!!!


Tuesday 23 July 2019

Configuring Spring MVC Through Java

In our Earlier posts we have seen how to set up the MVC application through the XML based, now in this blog we are going to see how to configure only through the java based.

For this on top of the existing setup we have from last tutorial.

Perform the Following changes to the application .

1.Here is my web.xml

In My Web.xml I need to define the contextconfig location to the AppConfig.java

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
        instead of the default XmlWebApplicationContext -->
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>
    <!-- Configuration locations must consist of one or more comma- or space-delimited
        fully-qualified @Configuration classes. Fully-qualified packages may also be
        specified for component-scanning -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.searchendeca.configuration.AppConfig</param-value>
    </context-param>
    <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- Declare a Spring MVC DispatcherServlet as usual -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
            instead of the default XmlWebApplicationContext -->
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>
                org.springframework.web.context.support.AnnotationConfigWebApplicationContext
            </param-value>
        </init-param>
        <!-- Again, config locations must consist of one or more comma- or space-delimited
            and fully-qualified @Configuration classes -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>com.searchendeca.configuration.AppConfig</param-value>
        </init-param>
    </servlet>
    <!-- map all requests for /app/* to the dispatcher servlet -->
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>


2.Here is my pom.xml

<?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/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>
<groupId>com.searchendeca.application</groupId>
<artifactId>springmvc</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Simple webapp</name>
<description>The bare minimum for a functional webapp.</description>
<url>https://github.com/mkspcd/MavenArchetypes</url>

<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>


<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>


<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>


</dependencies>

<properties>
<servlet.api.version>3.1.0</servlet.api.version>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

<build>
<finalName>simple-webapp</finalName>
</build>
</project>


3.AppConfig.java

package com.searchendeca.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;


@Configuration
@EnableWebMvc
@ComponentScan(basePackages="com.searchendeca.springmvc")
public class AppConfig extends WebMvcConfigurerAdapter{


/*@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    }*/
@Bean
public UrlBasedViewResolver getITRVR() {
UrlBasedViewResolver irvr = new UrlBasedViewResolver();
irvr.setViewClass(JstlView.class);
irvr.setPrefix("/WEB-INF/jsp/");
irvr.setSuffix(".jsp");
return irvr;
}

}


4.CustomDispatcherServlet.java

package com.searchendeca.configuration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

@Configuration
public class CustomDispatcherServlet implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext dispatcherServletContext = new AnnotationConfigWebApplicationContext();
        dispatcherServletContext.register(AppConfig.class);
        DispatcherServlet dispatcherServlet = new DispatcherServlet(dispatcherServletContext);
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", dispatcherServlet);
        dispatcher.setLoadOnStartup(1);
        // Add servlet mapping url. All url end with .html will be processed by this servlet.
        dispatcher.addMapping("/");
    }

}

5.Helloworld.java

package com.searchendeca.springmvc;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class HelloWorld {
@RequestMapping(value="/welcome")
public String greetmessage(Model model) {
model.addAttribute("message", "Hello Syed Welcome!");
System.out.println("Syed");
return "index";
}

}


6.Index.jsp

<%@ page language="java" pageEncoding="UTF-8" %>

${message}


Output:Hello Syed Welcome!


Happy Learning !!!!

Monday 22 July 2019

Spring MVC Framework

Web MVC framework

The Spring Web model-view-controller (MVC) framework is designed around a DispatcherServlet
that dispatches requests to handlers, with configurable handler mappings, view resolution, locale, time zone and theme resolution as well as support for uploading files.

"Open for extension…" A key design principle in Spring Web MVC and in Spring in general is the
"Open for extension, closed for modification" principle.

Features of Spring Web MVC

Clear separation of roles.
Powerful and straightforward configuration of both framework and application classes as JavaBeans
Adaptability, non-intrusiveness, and flexibility
Reusable business code, no need for duplication
Customizable binding and validation.
Customizable handler mapping and view resolution
Flexible model transfer
Customizable locale, time zone and theme resolution.
A simple yet powerful JSP tag library known as the Spring tag library that provides support for features
such as data binding and themes.
If you do not want to use Spring’s Web MVC, but intend to leverage other solutions that Spring
offers, you can integrate the web MVC framework of your choice with Spring easily.

The DispatcherServlet

Spring’s web MVC framework is, like many other web MVC frameworks, request-driven, designed
around a central Servlet that dispatches requests to controllers and offers other functionality that
facilitates the development of web applications.

Now we can look into how to Create a sample mvc web application using STS.

Open the STS and select the 

File-> New Maven Project.

Leave the selected options available.



In the architypes selection select the web



Give the maven artifact and package details.



click finish to create the project.

The Project structure will be like below.



Now its our time to add the dependencies .Add the Following dependencies. Navigate to pom and paste the below Maven dependencies.

<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
</dependencies>

We have added the dependencies, now We need to update the web.xml.
As we already know that the "DispatcherServlet" is required for the dispatching the requests the corresponding controllers. Define in the following way .
<?xml version="1.0" encoding="UTF-8"?>

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

<display-name>Simple web application</display-name>

<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

</web-app>

Now we have defined the web.xml contents . Next is to Create the servlet-config.xml. By Default sprinng looks fot the <ServletName>-servlet.xml. Hence my servlet file name will be like spring-servlet.xml.

Here is my config file.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">

// we are defining that it works based on the mvc annotation-driven hence we are mentioning like this.
<mvc:annotation-driven />
//Scans for the controller classes.
<context:component-scan
base-package="com.searchendeca.springmvc" />
<mvc:default-servlet-handler />

 //View resolver is used to resolve the view. This is very much required what the outout must be.
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>

</beans>

Create a Controller

Always create the java classes in src/main/java.

package com.searchendeca.springmvc;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloWorld {
@RequestMapping("/")
public String greetmessage(Model model) {
model.addAttribute("message", "Hello Syed Welcome!");
return "index";
}

}

From the above controller we are defining the mapping be '/' and dispatcher servlet fwds the request for / and in the model attribute we are setting and sending it .

In the view resolver we have defined as the /WEB-INF/jsp/ for the location of jsp. Create a folder there and save the jsp as index.jsp.

<%@ page language="java" pageEncoding="UTF-8" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
    ${message}
</body>
</html>

This will print the jsp message. If you access with any other context you will get 404. Happy Learning!!!