Monday, September 28, 2015

Building a Tree Grid using GXT / GWT

There is a large debate among GWT developpers on whether to use native GWT for applications and do everything from scratch or to make use of the large set of ready to use components and widgets provided by GXT. Personally, I prefer GWT as I do not like to be tied to any particular way of styling components. Based on my experience, GXT provide a great set of widgets that proved to be extremely useful; however, customizing them can be very time consuming. GXT components' performance is inferior to native GWT components. That being said, we can not deny that GXT can help developpers save time on developping some components which are considered standard in web UIs.  Building a tree grid is an example. A tree grid can be useful to represent data in a hierarchical fashion. In this tutorial, we are going to build a treegrid using GXT.

Requirements:
- Eclipse with GWT plugin
- GXT library   (Free for personal use or for open source projects)

The first thing we need to do is to create a google web application project. Go to File -> New -> Other  -> Google  and click on  Web application project. The project has the following structure:


Once the project is created, we need to add GXT to referenced libraries and also to GWT module configuration file. Right  click on the project, and then go to build path -> configure build path. Click on "Add External JARs" and add the Jar of GXT.



The GWT module confiugration describes the libraries that will be used in the project, the entry point( which can be translated as Welcome page), and where the translatable code lies.















Now, we are going to create our widget using the following components:

- TreeGrid: the actual treegrid widget
- ColumnConfig: object used for configuring columns
- TreeStore: object that serves as data model for the widget
- PropertyAccess<T>: interface that links the object data to the data model. The methods need to have the same name as the object T properties.


We are going to create a widget called MyTreeGrid that represents the data of an object named "Concept".
  
public class Concept {
 
 private String conceptName;
 private String conceptType;
 private String conceptOwner;
 
 
 
 public Concept(String conceptName, String conceptType, String conceptOwner){
  this.conceptName = conceptName;
  this.conceptType = conceptType;
  this.conceptOwner = conceptOwner;
 }
 /**
  * @return the conceptName
  */
 public String getConceptName() {
  return conceptName;
 }
 /**
  * @param conceptName the conceptName to set
  */
 public void setConceptName(String conceptName) {
  this.conceptName = conceptName;
 }
 /**
  * @return the conceptType
  */
 public String getConceptType() {
  return conceptType;
 }
 /**
  * @param conceptType the conceptType to set
  */
 public void setConceptType(String conceptType) {
  this.conceptType = conceptType;
 }
 /**
  * @return the conceptOwner
  */
 public String getConceptOwner() {
  return conceptOwner;
 }
 /**
  * @param conceptOwner the conceptOwner to set
  */
 public void setConceptOwner(String conceptOwner) {
  this.conceptOwner = conceptOwner;
 } 

}

We can use the same object to hold data for the second level of the hierarchy, but for clarity sake, we are going to use an object that extends "Concept".

public class ConceptMetaInformation extends Concept{
 public ConceptMetaInformation(String metaType, String location){
  super(metaType, location, "");

 }

}

Next, we need to create our PropertyAccess interface that will serve as a glue between the object and the view:


public interface Properties extends PropertyAccess<Concept>{
    ValueProvider<Concept> conceptName();
 
 ValueProvider<Concept> conceptType();
 
 ValueProvider<Concept> conceptOwner();

}

Note: methods need to have the same name as object properties.

Finally, we can create our widget:
public class MyTreeGrid implements IsWidget {
       TreeGrid<Concept> grid;
     ColumnConfig<Concept, String>  nameColumn;
  ColumnConfig<Concept, String> typeColumn;
  ColumnConfig<Concept, String>  ownerColumn;
  TreeStore<Concept> store;
  
//sample data
  Object[][] sampleValues = {
    {new Concept("Car","Transportation","Z.amine"), new ConceptMetaInformation("Location", "MENA"), new ConceptMetaInformation("Revenues", "150 000$")},
    {new Concept("Computer","I.T","H.John"), new ConceptMetaInformation("Location", "Europe"), new ConceptMetaInformation("Revenues", "180 000$")},
    {new Concept("Cookies","Food","R.David"), new ConceptMetaInformation("Location", "North America"), new ConceptMetaInformation("Revenues", "200 000$")},
    {new Concept("Electric Appliance","Home","T.Short"), new ConceptMetaInformation("Location", "China"), new ConceptMetaInformation("Revenues", "500 000$")},
    {new Concept("Air conditioner","Home","F.Jospeh"), new ConceptMetaInformation("Location", "Australia"), new ConceptMetaInformation("Revenues", "120 000$")}
  };
 
 @Override
 public Widget asWidget() {
  Properties properties = GWT.create(Properties.class);
  // TODO Auto-generated method stub
   store = new TreeStore<Concept>(new ModelKeyProvider<Concept>() {
   @Override
   public String getKey(Concept item) {
    if(item instanceof ConceptMetaInformation){
     return String.valueOf(item.getConceptName().hashCode()) + item.getConceptType().hashCode();
    }else {
     return String.valueOf(item.getConceptName().hashCode());
    }
    
   }
   });
   
   FillStore();
   
   nameColumn =  new ColumnConfig<Concept, String> (properties.conceptName(), 180); 
   typeColumn =  new ColumnConfig<Concept, String> (properties.conceptType(), 180); 
   ownerColumn =  new ColumnConfig<Concept, String> (properties.conceptOwner(), 180); 
   
   List<ColumnConfig<Concept, ?>> columns = new ArrayList<ColumnConfig<Concept, ?>>();
   
   columns.add(nameColumn);
      columns.add(typeColumn);
      columns.add(ownerColumn);
 
  ColumnModel<Concept> columnsModel = new ColumnModel<Concept>((List<ColumnConfig<Concept, ?>>) columns);
  
  grid = new TreeGrid<Concept>(store, columnsModel, nameColumn);
  grid.setHideHeaders(true);
  grid.setBorders(false);
  
  grid.setSelectionModel(new TreeGridSelectionModel<Concept>());
  grid.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
  
  return grid;
 }
 
 private void FillStore(){
  for(Object[] conceptInfo: sampleValues){
   Concept concept = (Concept) conceptInfo[0];
   ConceptMetaInformation location = (ConceptMetaInformation) conceptInfo[1];
   ConceptMetaInformation revenues = (ConceptMetaInformation) conceptInfo[2];
   store.add(concept); 
   store.add(concept, location); 
   store.add(concept, revenues); 
  }
 }
}

We can test our widget in our entry point class:
public class TreeGrid implements EntryPoint {
 /**
  * This is the entry point method.
  */
 public void onModuleLoad() {
  MyTreeGrid treegrid = new MyTreeGrid();
  RootPanel.get("treegrid").add(treegrid.asWidget());

 }
}
Result:


we have an out of the box tree grid that we can use as needed. It can be customized with editors for each cell if needed. 

Friday, September 11, 2015

Generating Rest Services documentation using Swagger



We have seen in "How to create a Restful application using Spring", how to build a Rest API using Spring Framework.
After we have built our Rest APIs, we want the developpers and users to have an up-to-date description of  the available operations and resources. The best way to do it is to auto-generate your documentation from code. There are lots of ways for achieving this; one of them is Swagger which is considered one of the best frameworks for this purpose. In this post, we will walk step by step through how to generate documentation for a Rest application built using Spring MVC.

Requirements:
SpringFox ( Swagger Integration for Spring MVC)
Swagger UI
Maven, Spring, Eclipse,..


Let's suppose we have two resources: Person, Concept, and a controller for each resource: PersonController, and ConceptController. The application structure looks like:



We have added the following dependencies for swagger libraries to our pom.xml:



Now we need to configure Swagger, for this we will create a configuration class:
  
@EnableSwagger2
public class SwaggerConfiguration {
  @Bean
   public Docket myApi() {
   return new Docket(DocumentationType.SWAGGER_2)
   .apiInfo(getApiInfo());
  }
  private ApiInfo getApiInfo(){
   //We do not use all info
   ApiInfo info = new ApiInfo("My Rest API", "Auto generated Rest API Documentation","1.0","","","","");
   return info;
  }
}



@EnableSwagger2 tells Spring to generate an api description in JSON at v2/api-docs endpoint
@Bean is the bean for the Docket for configuring the Documentation description. We have only used API info, which configures the Info section of the documentation. More configuration options are described at: http://springfox.github.io/springfox/docs/snapshot/

Next, we need to add some description to our operations, let's take the example of ConceptController:
  
@Api(value="Concept")
@Controller
@RequestMapping("/concept")
public class ConceptController {
 @ApiOperation(value = "Fetch all Concepts")
 @RequestMapping(method= RequestMethod.GET)
 public @ResponseBody Concept displayConcepts() throws Exception {
  Concept concept = new Concept();
  concept.setConceptName("Test Concept");
  concept.setConceptOwner("Me");
  concept.setConceptType("Sample");
  
  return concept;
 }
 @ApiOperation(value = "Creates a new Person in the database")
 @RequestMapping(method= RequestMethod.POST)
 public Concept createConcept(){
  
  
  return null;
 }

}


We have added @Api to the class in addition  to Spring Annotations. This is for telling Swagger that this represents an API with a title Concept.

We have also added @ApiOperation to each operation for telling Swagger to add the description in value to operations.

Both annotations are optional.

Now, if we run our application using Jetty and navigate to localhost:8080/v2/api-docs:

We can see that Swagger generates a description of our API in JSON format. This description is used by Swagger UI, which a JS library that takes this JSON as an input and creates a good looking documentation

In order to display the docs, we are going to download Swagger UI and add it to application resources, and create a html page in which we are going to load the Swagger JS script:




Before navigating to our doc page, we need to add: <mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" /> to our mvc-dispatcher-servlet.xml in order to serve static resources without a controller.

Finally, we can navigate to our docs:


The user can expand operations for more details, and even try them.


Full example at: https://github.com/zak905/swaggerexample

Thursday, September 3, 2015

Introduction to Java 8 Streams

Java 8 has been released a while ago, but lots of developpers still do not make use of its full potential. One of key features of Java 8 that can change how developpers look at collections is: Streams.

Streams introduce a new programming style and let you process collections in a declarative way rather than using loops or iterators.

Let's suppose we have a list of strings and we want to : retrieve strings that are less than 4 charachters, make them upper case, sort the result, and finally print it.

List myList = Arrays.asList("yet","another", "proof", "that", "java8", "streams","rocks"); 

The conventional way of doing it is to loop through the list and retrieve one element at a time, test if they fill the condition, turn them upper case, store them in a new list, sort the list and finally print it. 
 List result = new ArrayList();
  for(int i = 0; i < myList.size(); i++){
   if(myList.get(i).length() <= 4){
    result.add(myList.get(i).toUpperCase()); 
   }
  }
  Collections.sort(result);
  

  for(int i = 0; i < result.size(); i++)
       System.out.println(result.get(i));


Using streams, the process is much shorter and can be written as:

myList.stream()
  .filter( s -> s.length() <= 4)
  .map(s -> {return s.toUpperCase();})
  .sorted()
  .forEach(System.out::println);
Result :
THAT
YET
Another useful feature of Streams API is when the developpers needs to apply a formula such as sum or average or any other mathematical formula.

Suppose we have the following object:

public class Tag {
	
	public enum TYPE{
		NEWS, SPORTS
		
	}
	
	private String name;
	
	private int count;
	
	private TYPE type;
	
	public Tag(String name, int count, TYPE type) {
		this.name = name;
		this.count = count;
		this.type = type;
	}
	
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
	
	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the count
	 */
	public int getCount() {
		return count;
	}

	/**
	 * @param count the count to set
	 */
	public void setCount(int count) {
		this.count = count;
	}

	/**
	 * @return the type
	 */
	public TYPE getType() {
		return type;
	}

	/**
	 * @param type the type to set
	 */
	public void setType(TYPE type) {
		this.type = type;
	}
	
	@Override
	public String toString(){
		return "{name:"+name+", count:"+count+"}";
	}
	
}
Let's suppose we have a list of Tags and we want to calculate the sum or average of the "count" property.
	List tagsList = Arrays.asList(
				new Tag("tag1", 10, Tag.TYPE.NEWS),
				new Tag("tag2", 20, Tag.TYPE.SPORTS), 
				new Tag("tag3", 40, Tag.TYPE.SPORTS));
Once again, the conventional way to do it is loop through all elements apply the desired formula. Using Stream, it can be done in the following way:
		int countSum = tagsList.stream()
		.mapToInt(Tag::getCount)
		.sum();
Average:
		tagsList.stream()
		.mapToInt(Tag::getCount)
		.average()
		.ifPresent(System.out::println);
Another very useful feature of Streams is grouping elements by a common property:
		
		Map<TYPE, List> map = tagsList.stream()
		.collect(Collectors.groupingBy(Tag::getType));

System.out.println(map);
Result:
{NEWS=[{name:tag1, count:10}], SPORTS=[{name:tag2, count:20}, {name:tag3, count:40}]}


The list is still long, and the possibilities are endless. But since this is just an introduction, we will stop here. We will go through more advanced stuff later on.

Full example at: https://github.com/zak905/java8features/tree/master/src/opencode/java8features/streams