Thursday 30 January 2014

Spring Annotations

Introduction:

In Spring, XML based configurations is the most popular configuration style. Spring uses annotations as an alternative to XML for declarative configuration.

To make annotations and work in spring, use the <context:component-scan> tag in spring bean configuration file. So that spring will scan and find out the beans and register in the Spring Container.

Syntax:

Ex:

Note: If it requires adding multiple packages to scan, use comma separator.

Auto Components Scan Annotation Types:
In Spring, there are 4 types of auto components scan annotation types
  • @Component – Indicates an auto scan component.
  • @Repository – Indicates DAO component in the persistence layer.
  • @Service – Indicates a Service component in the business layer.
  • @Controller – Indicates a controller component in the presentation layer.

<context:annotation-config> is used to activate annotations in beans already registered in the application context.

Component-scan vs annotation-config:
<context:annotation-config>: Only registers 4 BeanPostProcessors that are part of the Spring Framework and have specific configuration objectives.
  • CommonAnnotationBeanPostProcessor: Recognizes and processes the JSR 250 common annotations (@PostConstruct, @PreDestroy, @Resource).
  • AutowiredAnnotationBeanPostProcessor: Recognizes the Autowired related annotations (@Autowired, @Value, @Inject, @Qualifier, etc)
  • RequiredAnnotationBeanPostProcessor: Recognizes the @Required annotation
  • PersistenceAnnotationBeanPostProcessor: Recognizes the @PersistenceUnit and @PersistenceContext annotations (related to JPA).
All of these annotations are typically placed either on a class field, constructor or method. <context:component-scan>: is a super set of the <context:annotation-config> tag. It registers the same bean post processors and also will perform component scanning. It looks for classes in the given base-package that are annotated with a category of annotations (@Component, @Repository, @Controller, etc). The purpose of using is to provide an alternative way to 'discover' Spring components other than using XML.

Spring related Annotations:

Below are the few important spring related annotations and their package.
Spring Annotation
Package
@Controller
org.springframework.stereotype.Controller
@RequestMapping
org.springframework.web.bind.annotation.RequestMapping
@RequestParam
org.springframework.web.bind.annotation.RequestParam
@PathVariable
org.springframework.web.bind.annotation.PathVariable
@ModelAttribute
org.springframework.web.bind.annotation.ModelAttribute
@SessionAttributes
org.springframework.web.bind.annotation.SessionAttributes
@PreAuthorize
org.springframework.security.access.prepost.PreAuthorize

@Controller Annotation:

The @Controller annotation indicates that a particular class serves the role of a controller. The controller class is no longer need to extends any of base controllers. When we @Controller annotation, its mandatory to use @RequestMapping annotation. This annotation is used to map a particular http/https request.

@RequestMapping Annotation:

This annotation can be used at both class level and method level. In case of multi-action controller, it’s recommended to use this annotation at method level and also at class level if required.

Syntax at class level: @RequestMapping("/") 
Syntax at method level: @RequestMapping(value = “/”, method = RequestMethod.[GET/POST]) 

We can use wildcard characters like * for path pattern matching. 

Simple scenario:
@Controller
@RequestMapping("/blogspot")
public class blogspotController {

 @RequestMapping(value="/properties")
 public String findAllProperties(){

 }
}
Testing URL: /blogspot/properties

Request parameter binding:
@RequestMapping(value="/properties")
public String findByProperty(@RequestParam("propertyId") String propertyId){
  
}
Testing URL: /blogspot/properties?propertyId =<some_id>

Extracting path variables:
@RequestMapping(value="/blogspot/{propertyId}")
public String findByProperty(@PathVariable String paropertyId){

}
(OR)
@RequestMapping(value="/blogspot/{propertyId}")
public String findByProperty(@PathVariable("propertyId") String somePropertyId){

}
Testing URL: /blogspot/properties/propertyId/23

Extracting multiple path variables:
@RequestMapping(value="/properties/{propertyId}/owner/{ownerId}")
public String findByProperty( @PathVariable String propertyId,  @PathVariable String ownerId){

}
Testing URL: /blogspot/ properties/23/owner/39

Extracting regular expressions:
@RequestMapping(value="/{textualPart:[a-z-]+}.{numericPart:[\\d]+}")
public String regularExpression( @PathVariable String textualPart, @PathVariable String numericPart){

}
Testing URL: /blogspot/text_chars.123

@RequestParam Annotation:

It’s a method argument annotation. This @RequestParam annotation can be used for getting the parameters from the request(query parameters). The scope of the variable passed is method scope. Syntax:
@RequestParam(value = “requestParam”, required = true/false, defaultValue = "defaultVal") dataTye variableName)
Ex:
public void printPageInfo(@RequestParam(value = "pageNumber", required = false, defaultValue = "1")  Integer pageNumber)

@PathVariable Annotation:

It’s a method argument annotation. The @PathVariable annotation can be used for getting the value of URI template variable. Syntax:
@PathVariable("pathVarName") dataTyep variableName)
Ex: If we want to create a controller that would allow users to see view pages by using a URL as below http://parameshk.blogspot.in/search/label/Java - display details for java http://parameshk.blogspot.in/search/label/Spring - display details for spring
@Controller
@RequestMapping("/search")
public class ShowPagesController {
    @RequestMapping("/label/{labelName}") // Handle any request of the form "/label/XXXXX"
    public String showProduct(Model model, @PathVariable("labelName") String labelName) {
    }
}

@ModelAttribute Annotation:

It supports RequestMapping annotated handler classes. It binds a method parameter or method return value to a named model attribute that exposed to a web view. Uses of @ModelAttribute: Useful to read data from an existing model by assigning it to handler method parameters. If a view/jsp want to populate some values while onload, we can inject the data to jsp by using this annotation. Ex: Below is the code snippet, which binds Employee object to a view page. Code snippet in controller:
@RequestMapping(value="/property-details")  
public ModelAndView processPerson(@ModelAttribute Property prop) {  
    ModelAndView modelAndView = new ModelAndView();  
    modelAndView.setViewName("property-details");  
    modelAndView.addObject("property", prop);  
    return modelAndView;  
}
Code snippet in jsp/view page:
Property Details:
Property Name: ${ property.name}
Property Location: ${ property.location}
Property Owner: ${ property.owner}

@ SessionAttributes Annotation:

The @SessionAttributes annotation is used to store the model object in the session. It is used on the Controller class level to declare used session attributes. All Model attributes having names or types defined in this annotation will be automatically persisted and restored between the subsequent requests. It’s a very small declaration instead of using HttpSession's getAttribute() & setAttribute() calls. Model attributes are persisted at the end of request handling by AnnotationMethodHandlerAdapter, after calling the handler method responsible for request handling and after determining the ModelAndView for the response. Their names in Model are used as their names in the persistent storage. Ex: @SessionAttributes("form") will trigger persisting Model attribute named "form" as HttpSession attribute named "form". Persisted Model attributes will be removed only when SessionStatus.setComplete() method called in handler methods. Ex:
@Controller
@RequestMapping(value="/dashboard", method=RequestMethod.POST)
@SessionAttributes("property")
public class LoginController {
    @RequestMapping(value="/authenticate",method=RequestMethod.POST)
    public String authenticate(@RequestParam String propertyId, Model model){
        Property property = new Property();
        property.setPropertyId(propertyId);
        property.setName("PPB_1");
        property.setLocation("USA");
        model.addAttribute("property", property);
        return "xxxxx";
    }
}
Note: To store multiple objects in @SessionAttributes use comma separator.

RESTful Web Service - JAX-RS Annotations:

  • Jersey, the reference implementation of JAX-RS, implements support for the annotations defined in JSR 311, making it easy for developers to build RESTful web services by using the Java programming language.
  • REST is an architectural style which is based on web-standards and the HTTP protocol.
  • In REST based architecture everything is a resource. A resource is accessed via a common interface based on the HTTP standard methods.
  • In a REST based architecture you typically have a REST server which provides access to the resources and a REST client which accesses and modify the REST resources.
  • Every resource should support the HTTP common operations. Resources are identified by global IDs (which are typically URIs).
  • REST allows that resources have different representations, e.g. text, xml, json etc. The rest client can ask for specific representation via the HTTP protocol (content negotiation).
JAX-RS Annotation
Package
@Path
javax.ws.rs.Path
@Produces
javax.ws.rs.Produces
@Consumes
javax.ws.rs.Consumes
@GET
javax.ws.rs.GET
@POST
javax.ws.rs.POST
@PUT
javax.ws.rs.PUT
@DELETE
javax.ws.rs.DELETE
@FormParam
javax.ws.rs.FormParam
@PathParam
javax.ws.rs.PathParam
@QueryParam
javax.ws.rs.QueryParam

@Path Annotation:

It’s a both class & method level annotation. This identifies the URI path template to which the resource responds. The @Path annotation's value is a partial URI path template relative to the base URI of the server on which the resource is deployed, the context root of the WAR, and the URL pattern to which the Jersey helper servlet responds.

Syntax:
    @Path("/uri")

The @Path annotation is not limited to simple path expressions. We can also have the ability to insert regular expressions into @Path's value.

Syntax: @Path (“uri/{variable[:regular-expression]}”)
Ex:
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;

@Path("/properties")
public class UserRestService {

 @GET
 public Response getProperties() {
  //TODO provide method body
 }
 //Target Url: /properties

 @GET
 @Path("/ppb")
 public Response getPropertyPPB() {
  //TODO provide method body
 }
 //Target Url: /properties/ppb
 
 @GET
 @Path("{name}")
 public Response getPropertyByName(@PathParam("name") String name) {
  //TODO provide method body
 }
 //Target Url: /properties/abcdefg

 @GET
 @Path("{id : \\d+}") //id is regular expression which accepts only numbers
 public Response getPropertyById(@PathParam("id") String id) {
  //TODO provide method body
 }
 //Target Url: /properties/1234

 @GET
 @Path("/propertyname/{propertyname : [a-zA-Z][a-zA-Z_0-9]+}")
 public Response getPropertyByPropertyName(@PathParam("propertyname") String propertyname) {
  //TODO provide method body
 }
 //Target Url: /properties/propertyname/myproperty123

}

@Consumes Annotation:

The @Consumes annotation is used to specify which MIME media types of representations, a resource can accept/ consume from the client. @Consumes annotation can be applied at both the class and method levels. If it’s applied at class level, by default all the methods will accept the same MIME type. If it’s applied at the method level, overrides the class level annotation if applied. The possible MIME types which can be used for this annotation can be available in the class javax.ws.rs.core.MediaType.

Syntax: 
   @Consumes(MediaType.XXX) @Consumes({MediaType.XXX, MediaType.YYY, …})

@Produces Annotation:

The @Produces annotation is used to specify the MIME media types of representations a resource can produce and send back to the client. @Produces annotation can be applied at both the class and method levels. If it’s applied at class level, by default all the methods will accept the same MIME type. If it’s applied at the method level, overrides the class level annotation if applied. The possible MIME types which can be used for this annotation can be available in the class javax.ws.rs.core.MediaType.

Syntax: 
    @Produces (MediaType.XXX) @Produces ({MediaType.XXX, MediaType.YYY, …})

@GET, @PUT, @POST, @DELETE & @HEAD Annotations:

@GET, @PUT, @POST, @DELETE and @HEAD are resource method designator annotations defined by JAX-RS and which correspond to the similarly named HTTP methods. In the example above, the annotated Java method will process HTTP GET requests. The behavior of a resource is determined by which of the HTTP methods the resource is responding to.
  • GET defines a reading access of the resource without side-effects. The resource is never changed via a GET request, e.g. the request has no side effects (idempotent).
  • PUT creates a new resource, must also be idempotent.
  • DELETE removes the resources. The operations are idempotent, they can get repeated without leading to different results.
  • POST updates an existing resource or creates a new resource.

@QueryParam Annotation:

Binds the value of a HTTP query parameter to a resource method parameter or resource class field or resource class bean property. A default value can be specified using the @DefaultValue annotation. Syntax:
@QuaryParam(“param1”) @DefaultValue(“defaultVal”) datatype varName
Ex:
@QuaryParam(“param1”) @DefaultValue(“defaultVal”) datatype varName

Ex:
@GET
@Path("eligibleBooks")
public ProductInfos getEligibleProducts(
 @QueryParam("category") @DefaultValue("JAVA") String category,
 @QueryParam(bookId) String bookId, 
 @QueryParam("bookName") String bookName,
 @QueryParam("accountType") String accountType,
 @QueryParam("countryCode") @DefaultValue("US") String countryCode) {
    
 //TODO method body
}

Target URL: /eligibleBooks?category=JAVA&bookId=1234&bookName=abcd123&accountType=technology&countryCode=IN

No comments:

Post a Comment