Featured FREE Whitepapers

What's New Here?

android-logo

Applying decorator pattern to decorate views on Android

Hi there! Today i’m gonna show how to apply the design pattern decorator to android’s views making use of its dependency injection’s concept. I thought it was a nice, clear and simple way to decorate views and that’s my motivator to share it with you. I’m assuming you know the decorator pattern already and are looking for real examples involving android. If you are trying to understand the concept behind it, this is also a good article but you may need to learn the fundamentals first. There are a bunch of good books out there. I personally recommend head first. In this example i’ll try to show how to decorate a view with icons dynamically. Something similar to eclipse’s tree decoration while some compile error or warning appears on the package structure. We will end up with something like that:Error/warning tree decoration in eclipseOur view decoration example in Android  Let’s visualize the structure by defining the UML-diagramFirst create a blank android’s project Put some icons of your choice in the folder drawable-yourChoice. In my example i took the drawable-xhdpi. I took the icons directly from my eclipse package. You may use your own icons.   Layouting the view Ok, now copy this code into your activity_main.xml layout: < RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" >< ImageView android:id="@+id/middle" android:layout_width="200dp" android:layout_height="200dp" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:src="@drawable/ic_launcher" / >< ImageView android:id="@+id/leftTop" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignLeft="@+id/middle" android:layout_alignTop="@+id/middle" / >< ImageView android:id="@+id/rightTop" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignRight="@+id/middle" android:layout_alignTop="@+id/middle" / >< ImageView android:id="@+id/leftBottom" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignBottom="@+id/middle" android:layout_alignLeft="@+id/middle" / >< ImageView android:id="@+id/rightBottom" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignBottom="@+id/middle" android:layout_alignRight="@+id/middle" / >< ImageView android:id="@+id/middleTop" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignTop="@+id/middle" android:layout_centerHorizontal="true" / >< / RelativeLayout > The common decorator interface Well ok, let’s start by defining the common decorator interface: /** * The common decorable interface to be used while implementing decorators. * @author Ricardo Ferreira * @version 1.0 * @since 07/04/2014 */ public interface Decorable { /** implements the concrete decorator's behavior */ void decorate(); } Defining the decorators contract This class defines what kind of object we want to decorate. In our case an android’s view which belongs to the Android’s API itself: import java.util.Arrays; import android.content.Context; import android.view.View; /** * Used to define the decorator's contract. In this case to decorate a view with icons * @author Ricardo Ferreira * @version 1.0 * @since 07/04/2014 */ public abstract class AbstractIconDecorator implements Decorable{ protected View view; protected View[] views; protected int drawableId; protected Context context; /** * Concrete classes must call this constructor to conform the decorator's contract. * @param context the app's context * @param view the view to be decorated * @param drawableId the drawable id dependency over R.drawable.yourId to be set * as background to the view of this constructor. */ public AbstractIconDecorator(Context context, View view, int drawableId){ super(); this.view = view; this.context = context; this.drawableId = drawableId; decorate(); } /** * Concrete classes must call this constructor to conform the undo decorator's contract. * @param context context the app's context * @param views the views to be undone. */ public AbstractIconDecorator(Context context,View[] views){ super(); this.context = context; this.views = Arrays.copyOf(views, views.length); decorate(); } } Implementing a master icon decorator This is a very nice implementation that takes advantage of android’s concept of dependency injection over the resource class R.drawable.myId. Using it, we don’t have to implement a lot of decorators. Instead of it, we implement just one and inject our dependencies according to our needs as you will see. import android.content.Context; import android.view.View; /** * Use this class to decorate views with icons thru dependency injection passing R.drawable.yourId * @author Ricardo Ferreira * @version 1.0 * @since 07/04/2014 */ public class IconDecorator extends AbstractIconDecorator{/** * Creates an universal icon decorator to be used while dealing with view's decoration. * @param context the app's context * @param view the view to be decorated * @param drawableId the drawable id dependency over R.drawable.yourId to be set * as background to the view of this constructor. */ public IconDecorator(Context context,View view, int drawableId){ super(context, view, drawableId); } @Override public void decorate() { view.setBackground(context.getResources().getDrawable(drawableId)); } } Implementing an undo decorator to revert decorations This is a special kind of decoration. I will decorate the main icon(the android’s green robot icon) with “nothing” making all decorations disappear. /** * Use this decorator to undo decoration by passing the view to be undone. * @author Ricardo Ferreira * @version 1.0 * @since 07/04/2014 */ public class ClearIconDecorator extends AbstractIconDecorator{/** * Creates an undo decorator. * @param context the app's context * @param views the views that has been decorated to be undone. */ public ClearIconDecorator(Context context,View[] views){ super(context,views); } @Override public void decorate() { for (View view : views) { view.setBackground(null); } } } The main activity Now the final step before running it. In this example i am simulating the decoration over clicks. But in your professional applications those decorations may occur while something go wrong or right or you may need to give some visual user feedbacks while doing something. Use your imagination! import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener;public class MainActivity extends Activity implements OnClickListener{private View middle; private View leftTop; private View leftBottom; private View rightBottom; private View rightTop; private View middleTop; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); middle = findViewById(R.id.middle); leftTop = findViewById(R.id.leftTop); leftBottom = findViewById(R.id.leftBottom); rightBottom = findViewById(R.id.rightBottom); rightTop = findViewById(R.id.rightTop); middleTop= findViewById(R.id.middleTop); leftTop.setOnClickListener(this); leftBottom.setOnClickListener(this); rightBottom.setOnClickListener(this); rightTop.setOnClickListener(this); middle.setOnClickListener(this); middleTop.setOnClickListener(this); }@Override public void onClick(View view) { switch (view.getId()) { case R.id.leftTop: new ErrorIconDecorator(view); break; case R.id.leftBottom: new WarningIconDecorator(view); break; case R.id.rightTop: new InfoIconDecorator(view); break; case R.id.rightBottom: new QuickFixIconDecorator(view); break; case R.id.middleTop: new IconDecorator(this,view, R.drawable.newpack_wiz); break; case R.id.middle: final View[] views = new View[]{leftTop,leftBottom,rightTop,rightBottom,middleTop}; new UndoIconDecorator(views); break; default: break; } } // you may define specific decorators to your convenience... // ... or you may use directly the universal decorator IconDecorator(...). // It is up to your. Here i'm showing both examples public class WarningIconDecorator{ public WarningIconDecorator(View view){ new IconDecorator(MainActivity.this, view, R.drawable.warning_obj); } } public class ErrorIconDecorator { public ErrorIconDecorator(View view){ new IconDecorator(MainActivity.this, view, R.drawable.error); } } public class InfoIconDecorator { public InfoIconDecorator(View view){ new IconDecorator(MainActivity.this, view, R.drawable.information); } } public class PackageDecorator { public PackageDecorator(View view){ new IconDecorator(MainActivity.this, view, R.drawable.package_obj); } } public class QuickFixIconDecorator { public QuickFixIconDecorator(View view){ new IconDecorator(MainActivity.this, view, R.drawable.quickfix_error_obj); } } public class ErrorWarningDecorator { public ErrorWarningDecorator(View view){ new IconDecorator(MainActivity.this, view, R.drawable.errorwarning_tab); } } public class UndoIconDecorator{ public UndoIconDecorator(View[] views){ new ClearIconDecorator(MainActivity.this, views); } } } So that’s all. Hope you like it.Reference: Applying decorator pattern to decorate views on Android from our JCG partner Ricardo Ferreira at the Clean Code Development – Quality Seal blog....
android-logo

How to customize / change ActionBar font, text, color, icon, layout and so on with Android

Hi there! Today i’m gonna share a very common task with you. How to customize an ActionBar on Android. We will change layout, font, textsize, textcolor, add listener to it, navigate back, hide title and home icon. At the end we will have something like this:          Well, lets start by changing some API provided settings. Downloading Font First of all, go to 1001freefonts and donwload a font you want to apply to your text. It is free! After downloading, create a folder called font into the folder assets in your projetct’s root. (create it, if not exists already) It looks like this: projectname>assets>font>yourfont.fftCreating custom colors We want to change the color of our font also. So for this reason, create two colors in your strings.xml file like this: <color name="selected">#824986</color>     <color name="unselected">#E4DFEC</color> Creating custom ActionBar Layout As we want to customize our actionBar, we will need to create a customized layout for it. So in your layout folder, create a new layout.xml file called custom_action_bar.xml like this: < ?xml version="1.0" encoding="utf-8"? > < LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/actionBar" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:paddingLeft="5dp" android:paddingTop="7dp" android:orientation="horizontal" > < TextView android:id="@+id/titleFragment1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Syntax" android:textSize="20sp" android:textColor="@color/selected" / >< TextView android:id="@+id/titleFragment2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:text="ionary" / > < / LinearLayout> Create createCutomActionBarTitle() in your Activity Create this method and enable setDisplayShowCustomEnable to true and setDisplayShowTitleEnable to false. Then inflate the above created custom_action_bar.xml file. Read your new downloaded font and set it to the textviews. At least add it to the actionBar. Done with the layout.     private void createCutomActionBarTitle(){         this.getActionBar().setDisplayShowCustomEnabled(true);         this.getActionBar().setDisplayShowTitleEnabled(false);        LayoutInflater inflator = LayoutInflater.from(this);         View v = inflator.inflate(R.layout.custom_action_bar, null);        Typeface tf = Typeface.createFromAsset(getAssets(),"font/yourfont.ttf");         ((TextView)v.findViewById(R.id.titleFragment1)).setTypeface(tf);         ((TextView)v.findViewById(R.id.titleFragment2)).setTypeface(tf);        //assign the view to the actionbar         this.getActionBar().setCustomView(v);     } Adding behaviors and navigate back funcions A disavantage of customized actionBars is that you have to worry about everything. Including default behaviors like navigating back and enabling actions on the new inserted TextViews. We will do this now. Normally you navigate from activity to activity and after doing something you’d like to give the possibility to the users to navigate back over touching the actionBars title. To do so, enhance the method createCustomActionBarTitle like this: private void createCutomActionBarTitle(){ this.getActionBar().setDisplayShowCustomEnabled(true); this.getActionBar().setDisplayShowTitleEnabled(false);LayoutInflater inflator = LayoutInflater.from(this); View v = inflator.inflate(R.layout.action_bar_contribution, null);Typeface tf = Typeface.createFromAsset(getAssets(),"font/fat_tats.ttf"); TextView frag1 = (TextView)v.findViewById(R.id.titleFragment1); frag1.setTypeface(tf); TextView frag2 = (TextView)v.findViewById(R.id.titleFragment2); frag2.setTypeface(tf); frag1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(YourCurrentActivity.this, YourTargetActivity.class)); finish(); } }); frag2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(YourCurrentActivity.this, YourTargetActivity.class)); finish(); } });//assign the view to the actionbar this.getActionBar().setCustomView(v); } Adding MetaData to the Manifest file We are almost done. To be able to navigate back, we need to write an entry in the manifest file. The “YourTargetActivity” is the activity that will be called, wenn we press the actionBars title. In our case it would look like this: < activity android:label="yourActivityLabelName" android:name="your.package.YourActivity" android:parentactivityname="your.package.YourTargetActivity" android:screenorientation="landscape" android:windowsoftinputmode="stateHidden" > < meta-data android:name="android.support.PARENT_ACTIVITY" android:value="your.package.YourTargetActivity" > < / meta-data> < / activity> That’s all! hope you like it! The application to download is here:Reference: How to customize / change ActionBar font, text, color, icon, layout and so on with Android from our JCG partner Ricardo Ferreira at the Clean Code Development – Quality Seal blog....
java-logo

Builder Design Pattern Applied

Hi there! Today i’m gonna share the first of a brand new design pattern series i made. The builder design pattern is a very useful and common pattern while developing serious apps. In this post i’ll give a tiny builder pattern framework, so you can always come back here and get it to work with. A mnemonic, while dealing with builder pattern, is to think about customization. I always think about it, when i’m figuring out if i should use it or if i better take a factory. That’s the way it works better for me. try yourself.   The UML Here is how the little framework looks like. Simple, nice and straightforward.The code behind it The code is also very simple, small, clean and self-explanatory. I like to code expressive, so i don’t need to comment a lot. In this sample here i did, because it has a tutorial character. While developing i created some convention to my self. I think it is very important to do so. It is like applying the right grammar on a language while developing. For example: If i’m using the Builder Pattern, i always put the suffix Builder at the end. Well you may say or think now: what? But thats in fact a very, very, important info for beginners and expirienced developers. They will automatically see the idea behind it and will try not to break the pattern. In fact expirienced developers will love it and try to continue a good work, because they know, that the developer who wrote this, knows what he did and for sure there was a reason for it. So always try to be clear enough and give the right information on the right places. Someone else will thank you later.  But now to the code… // 1. EXAMPLE: PARTS OF THE CUSTOMIZABLE PRODUCT WE WANT public interface Part { // DEFINE THE METHODS YOUR PARTS WILL HAVE... void anyMethodNameYouLike(); }// 2. THE BUILDER METHOD WILL ADD // PARTS RETURNING THE BUILDER ITSELF public interface BuildContract < B > { B mount(Part part); }// 3. DEFINE THE BUILDER'S CONTRUCTION METHOD // WHICH BUILDS AND RETURNS THE FINAL PRODUCT "T" public interface Builder < T > extends BuildContract < Builder < T > > { T build(); } A real example Nothing better then that to fix it and understand it better. Let´s implement a cake bakery. A colleague of yours wants to open a bakery and asked you to program a bakery’s software for him. Let’s do it..! And by the way, I commend you heartily, using a UML diagram tool is as visualization mechanism to show your ideas and improve your design skills. Lets start by the UML:The analogy Let’s now use our tiny framework and make the analogy for our bakery. Ingredient is the Part, Recipe is the BuilderContract and  Builder is the builder itself. Cake is the final, customizable product. CakeBuilder is the class which actually creates the product after customization (after the addition of as many parts – ingredients – as you want). The client would be the final client or your colleague taking the order. Just use or imagination… Let’s dive into code now… The Ingredients (Parts) The parts in our example are the ingredients. Let’s implement some ingredients to use it later to make a cake. // 1. EXAMPLE: PART TO CUSTOMIZATE "INGREDIENTS" public interface Ingredient { // INGREDIENTS WILL HAVE... void printName(); String getUnitPrice(); void printCalories(); } public class LightMilk implements Ingredient {private int deciLiter; private int calories; private String unitPrice; public LightMilk(int deciLiter){this.deciLiter=deciLiter;} public LightMilk(int deciLiter, int calories, String unitPrice) { super(); this.deciLiter = deciLiter; this.calories = calories; this.unitPrice = unitPrice; }@Override public void printName() {System.out.printf(" Light Milk");} @Override public String getUnitPrice() {return unitPrice;} @Override public void printCalories() {System.out.printf(" 76kc");} public int getDeciLiter() {return deciLiter;} public void setDeciLiter(int deciLiter) {this.deciLiter = deciLiter;} public int getCalories() {return calories;} public void setCalories(int calories) {this.calories = calories;} public void setUnitPrice(String unitPrice) {this.unitPrice = unitPrice;} } public class Sugar implements Ingredient {private int gram; private int calories; private String unitPrice; public Sugar(int deciLiter){this.gram=deciLiter;} public Sugar(int gram, int calories, String unitPrice) { super(); this.gram = gram; this.calories = calories; this.unitPrice = unitPrice; }@Override public void printName() {System.out.printf(" Sugar");} @Override public String getUnitPrice() {return unitPrice;} @Override public void printCalories() {System.out.printf(" 40kc");} public int getGram() {return gram;} public void setGram(int gram) {this.gram = gram;} public int getCalories() {return calories;} public void setCalories(int calories) {this.calories = calories;} public void setUnitPrice(String unitPrice) {this.unitPrice = unitPrice;} } public class Choco implements Ingredient { private int gram; private int calories; private String unitPrice; public Choco(int gram, int calories, String unitPrice) { super(); this.gram = gram; this.calories = calories; this.unitPrice = unitPrice; } public int getGram() {return gram;} public void setGram(int gram) {this.gram = gram;} public int getCalories() {return calories;} public void setCalories(int calories) {this.calories = calories;} public void setUnitPrice(String unitPrice) {this.unitPrice = unitPrice;}@Override public void printName() {System.out.printf(" Chocolate");} @Override public void printCalories() {System.out.printf(" 389kc");} @Override public String getUnitPrice() {return unitPrice;} } public class NoSugar implements Ingredient {private int gram; private int calories; private String unitPrice; public NoSugar(int deciLiter){this.gram=deciLiter;} public NoSugar(int gram, int calories, String unitPrice) { super(); this.gram = gram; this.calories = calories; this.unitPrice = unitPrice; }@Override public void printName() {System.out.printf(" No Sugar");} @Override public String getUnitPrice() {return unitPrice;} @Override public void printCalories() {System.out.printf(" 0kc");} public int getGram() {return gram;} public void setGram(int gram) {this.gram = gram;} public int getCalories() {return calories;} public void setCalories(int calories) {this.calories = calories;} public void setUnitPrice(String unitPrice) {this.unitPrice = unitPrice;} } public class Milk implements Ingredient {private int deciLiter; private int calories; private String unitPrice; public Milk(int deciLiter){this.deciLiter=deciLiter;} public Milk(int deciLiter, int calories, String unitPrice) { super(); this.deciLiter = deciLiter; this.calories = calories; this.unitPrice = unitPrice; }@Override public void printName() {System.out.printf(" Milk");} @Override public String getUnitPrice() {return unitPrice;} @Override public void printCalories() {System.out.printf(" 128kc");} public int getDeciLiter() {return deciLiter;} public void setDeciLiter(int deciLiter) {this.deciLiter = deciLiter;} public int getCalories() {return calories;} public void setCalories(int calories) {this.calories = calories;} public void setUnitPrice(String unitPrice) {this.unitPrice = unitPrice;} } The Builder’s Contract This is the Recipe in our example. // 2. THE BUILDER METHOD WILL ADD // INGREDIENTS RETURNING THE BUILDER ITSELF public interface Recipe < B > { B addIngredient(Ingredient ingredient); } // 3. DEFINE THE BUILDER CONTRUCTION METHOD // WHICH BUILDS AND RETURNS THE FINAL PRODUCT "T" public interface Builder < T > extends Recipe < Builder < T > > { T build(); } import java.util.ArrayList; import java.util.List; // 4. IMPLEMENT THE BUILDER ACC. TO YOUR NEEDS public class CakeBuilder implements Builder < Cake > { // IN THIS CASE THE PARTS ARE THE INGREDIENTS private List < Ingredient > ingredients=new ArrayList < Ingredient > ( ); @Override public Cake build() { if(!ingredients.isEmpty()){ // THE FINAL PRODUCT IS A CHOCO-MUFFIN return new Cake(ingredients); } return new Cake(null); } @Override // BECAUSE I ALWAYS GET A BUILDER BACK, I'M ABLE TO // ADD A LOT OF PARTS BEFORE I CALL "BUILD()" public Builder < Cake > addIngredient(Ingredient ingredient) { if(ingredient!=null){ ingredients.add(ingredient); } return this; } } The product In our example the product to build is a cake. import java.util.List;public class Cake { public Cake(List < Ingredient > ingredients){ String muffin = ""; if(ingredients==null){ System.out.println(" zero cake "+muffin); return; } // PRINT OUT MUFFIN INGREDIENTS System.out.printf(" Cake with: "); for (Ingredient ingredient : ingredients) { ingredient.printName(); } // PRINT OUT PART PRICES for (Ingredient ingredient : ingredients) { muffin+=" "+ingredient.getUnitPrice();//NOPMD } System.out.println(" - Price: "+muffin); } public void printResult(){ System.out.println(" Cake is ready!"); } } Testing it Finally the client test. Here we can see the usage of it: // 5. TESTING THE CHOCO-BUILDER public class Client { public static void main(String[] args) { Builder < Cake > chocoMuffinBuilder = new CakeBuilder(); chocoMuffinBuilder.addIngredient(new Choco(10, 23, "3.39")); chocoMuffinBuilder.addIngredient(new Milk(34, 67, "1.57")); chocoMuffinBuilder.addIngredient(new Sugar(34, 67, "2.00")); final Cake chocoMuffin = chocoMuffinBuilder.build(); chocoMuffin.printResult(); } } That’s all! Hope you like it!Reference: Builder Design Pattern Applied from our JCG partner Ricardo Ferreira at the Clean Code Development – Quality Seal blog....
java-logo

Game AI – An Introduction to Behaviour Trees

Game AI is a very broad subject and while there is a lot of material out there, I didn’t find something that introduces the concepts gently and at a slower, more understandable pace. This article will try to explain how to design a very simple but extendable AI system loosely based on the concept of Behaviour Trees. What is AI? Artificial Intelligence is the human-like behaviour exhibited by the entities participating in the game. It’s more the illusion of intelligence and thoughtful action performed by the entities than an actual intelligent reasoning driven behaviour. The goal is to try to fool the player into thinking that the other “intelligent” entities are controlled by humans and not by a machine. It’s easier said than done, but we can use a lot of tricks to achieve some really good, seemingly random and “intelligent” behaviours. An Example Before we jump right into the fun bit, let’s draft up a plan of what we want to achieve. Again, I will use droids as an example. Imagine an arena where droids will battle it out amongst them and whichever droid is the last one standing is the winner. The arena will be a board and droids will be placed randomly on it. We’ll make it a turn based game so we can follow the whole AI unfold, but it can be easily turned into a realtime game. The rules are simple:The board is a rectangle A droid can move one tile per turn in either direction to any of the adjacent unoccupied tiles A droid has a range and can fire at droids within its range The droids will have the usual attributes: damage they inflict and hit pointsFor the sake of simplicity we will use very simple structures. The application will have a Droid class and a Board class. A droid will have the following attributes that define it: public class Droid {final String name; int x; int y; int range; int damage; int health;Board board;public Droid(String name, int x, int y, int health, int damage, int range) { this.name = name; this.x = x; this.y = y; this.health = health; this.damage = damage; this.range = range; }public void update() { // placeholder for each turn or tick }/* ... */ /* getters and setters and toString() */ /* ... */ } The Droid is just a simple pojo with a few attributes. The attributes are self explanatory but here’s a short summary of them:name – the unique name of the droid, can be used for ID as well. x and y – the coordinates on the grid. health, damage and range – what it says. board – is the reference to the Board the droid is on along with other droids. We need this because the droid will make decisions by knowing its environment, which is the board<./li>There is also an empty update() method which is called each time the droid finishes its turn. If it’s a realtime game, the update method is called from the game loop, ideally from the game engine. There are also the obvious getters and setters and the toString() method which are omitted from the listing. The Board class is vey simple. public class Board {final int width; final int height;private List<Droid> droids = new ArrayList<Droid>();public Board(int width, int height) { this.width = width; this.height = height; }public int getWidth() { return width; }public int getHeight() { return height; }public void addDroid(Droid droid) { if (isTileWalkable(droid.getX(), droid.getY())) { droids.add(droid); droid.setBoard(this); } }public boolean isTileWalkable(int x, int y) { for (Droid droid : droids) { if (droid.getX() == x && droid.getY() == y) { return false; } } return true; }public List<Droid> getDroids() { return droids; } } It has a width and a height and it contains a list of droids. It also contains a few convenience methods to check if a droid is already present at a given coordinate and a method to easily add droids one by one. So far this is pretty standard. We can scatter a few droids on the board but they will not do anything. We can create the board, add some droids to it and start calling update(). They are only some dumb droids. Not so Dumb Droids To make a droid do something, we could implement the logic in its update() method. This is the method called every tick or in our case every turn. For example we want our droids to wander around the arena (board) and if they see an other droid in range, engage them and start firing at them until they die. This would be a very rudimentary AI but is still a AI. The pseudo code would look like this: if enemy in range then fire missile at it otherwise pick a random adjacent tile and move there This means any interaction between the droids will result in a stand-off and the weaker droid gets destroyed. We might want to avoid this. So we can add that if a droid is likely to lose, then try to flee. Stand and fight only if there is nowhere to escape.if enemy in range then if enemy is weaker then fight otherwise if escape route exists then escape otherwise fight otherwise wanderThis is all good. The droids will start acting “intelligently” but they are still very limited unless we add more code to do more clever things. And also, they will act the same. Imagine if you drop them in a more complicated arena. An arena where there are items like power-ups to pick up to enhance powers, obstacles to avoid. For example decide between picking up a health/repair kit and picking up a weapon power-up when droids are swarming around. It can get out of hands quite quickly. Also what if we want a differently behaving droid. One is an assault droid and the other one is a repair droid. We could achieve this of course with object composition, but the brains of the droids will be extremely complicated and any change in game design will require tremendous effort to accommodate. Let’s see if we can come up with a system that can solve these problems. Here Comes the Brain We can think of the AI module of the droid as some kind of a brain. The brain is composed of several routines that act on the droid following a set of rules. These rules govern the execution of the routines so it maximises the chances of survival and winning the game as an ultimate goal. If we think of our human brain consisting of routines and having Maslow’s hierarchy of needs as a reference , we can identify a few routines instantly.Physiological routine – a routine that needs to be executed every time otherwise there won’t be any living Subsistence routine – this routine needs to be executed once the living conditions have been met so the long term existence is secured Aspirational routine – this will be executed if there is time left after the subsistence has been secured and before subsistence needs to be executed againLet’s break the human intelligence down a bit. A human needs to breathe to live. Each breath consumes energy. One can breathe so much until it runs out of energy. To replenish the energy one needs to eat. One can only eat if he/she has food at his/her disposal. If there is no available food, it needs to be acquired which consumes some more energy. If the procurement of food takes a long time (needs to be hunted for example) and the amount of food obtained is small, after eating it, the human is in need of more food and the routine restarts without delay. If the food was bought in bulks from a supermarket, after eating it, there is plenty left so the human can move on to do more interesting things which are in his/her aspirational section. Things like making friends or wage war or watch television for example. Just think of how many things are in a human brain to make us function and try to simulate it. This all by disregarding most of the stimuli we are getting and responding to them. To do this, we would need to parametrise the human body and each sensor triggered by a stimulus will update the correct parameters and the executed routine will examine the new values and act accordingly. I won’t describe it now but you get the idea I hope. Let’s switch back to our much simpler droids. If we try to adapt the human routines to the droids we’ll get something like this:Physiological / Existential – this part we can ignore for this example because we design robots and they are mechanical beings. Of course for them to exist, they still need energy (eg. action points) which they can take from a battery or from some other energy source which can be depleted. For the sake of simplicity we will ignore this and consider the energy source to be infinite. Subsistence / Safety – this routine will make sure that the droid will survive the current turn and live by avoiding an immediate threat. Aspirational – this kicks in once the safety routine checked out OK and didn’t have to activate the droid’s fleeing routine. The current simple aspiration for the droid is to kill the other droids.Although the described routines are very simple and can be hard-coded, the approach we will take to implement is a bit more elaborate. We will use an approach based on behaviour trees. First and foremost we need to delegate every activity of the droid to its brain. I will call it Routine instead of brain. It can be called Brain or AI or anything, but I have chosen Routine because it will serve as a base class for all the routines that will consist of. Also it will be in charge of governing the flow of information in the brain. The Routine itself is a finite state machine with 3 states. public abstract class Routine {public enum RoutineState { Success, Failure, Running }protected RoutineState state;protected Routine() { }public void start() { this.state = RoutineState.Running; }public abstract void reset();public abstract void act(Droid droid, Board board);protected void succeed() { this.state = RoutineState.Success; }protected void fail() { this.state = RoutineState.Failure; }public boolean isSuccess() { return state.equals(RoutineState.Success); }public boolean isFailure() { return state.equals(RoutineState.Failure); }public boolean isRunning() { return state.equals(RoutineState.Running); }public RoutineState getState() { return state; } } The 3 states are:Running – the routine is currently running and will act on the droid in the next turn. Eg. the routine is responsible to move the droid to a certain position and the droid is in transit and still moving uninterrupted. Success – the routine has finished and it succeeded doing what it was meant to be doing. For example if the routine is still the “move to position”, it succeeded when the droid reached the destination. Failure – using the previous example (move to), the moving of the droid was interrupted (either the droid got destroyed or some unexpected obstacle appeared or some other routine interfered) and it didn’t reach the destination.The Routine class has the act(Droid droid, Board board) abstract method. We need to pass in the Droid and the Board because when the routine acts, it does so on the droid and in the knowledge of the droid’s environment which is the board. For example the moveTo routine will change the droid’s position each turn. Usually when the routine acts on the droid, it uses the knowledge gathered from its environment. This knowledge is modelled on the realities of the situation. Imagine that the droid (like us humans) can’t see the whole world but only as far as its sight range. Us humans have a field of view of about 135 degrees so if we would be simulating a human, we’d pass in a slice of the world containing the section we see and all the visible components in it and let the routine process just that to the best of its capabilities and come to a conclusion. We could do that for the droids too, and just pass in the section of the board that is covered by the range, but we will keep it simple for now and use the whole board. The start(), succeed() and fail() methods are simple public overridable methods that set the state accordingly. The reset() method on the other hand is abstract and it has to be implemented by each concrete routine to reset any internal state proprietary to that routine. The rest are convenience methods to query the state of the routine. Learning to Walk Let’s implement the first concrete routine which will be the MoveTo discussed above. public class MoveTo extends Routine {final protected int destX; final protected int destY;public MoveTo(int destX, int destY) { super(); this.destX = destX; this.destY = destY; }public void reset() { start(); }@Override public void act(Droid droid, Board board) { if (isRunning()) { if (!droid.isAlive()) { fail(); return; } if (!isDroidAtDestination(droid)) { moveDroid(droid); } } }private void moveDroid(Droid droid) { if (destY != droid.getY()) { if (destY > droid.getY()) { droid.setY(droid.getY() + 1); } else { droid.setY(droid.getY() - 1); } } if (destX != droid.getX()) { if (destX > droid.getX()) { droid.setX(droid.getX() + 1); } else { droid.setX(droid.getX() - 1); } } if (isDroidAtDestination(droid)) { succeed(); } }private boolean isDroidAtDestination(Droid droid) { return destX == droid.getX() && destY == droid.getY(); } } It’s a very basic class that will move the droid one tile towards the destination until it reaches it. It does not check for any other constraint than if the droid is alive. That’s the condition for failure. The routine has 2 parameters destX and destY. These are final attributes which the MoveTo routine will use to achieve its target. The routine’s single responsibility is to move the droid. If it can’t do that it will fail. That’s it. Single responsibility is very important here. We will see how we’ll combine these to achieve more complex behaviours. The reset() method simply sets the status to Running. It has no other internal state or values to deal with, but it needs to be overridden. The heart of the routine is the act(Droid droid, Board board) method which performs the action and contains the logic. First it checks for the failure condition, which is if the droid is dead. If it’s dead and the routine is active (its status is Running) then the routine failed to do what it was supposed to. It calls the super class’s default fail() method to set the status to Failure and exits the method. The second part of the method checks for the success condition. If the droid is not yet at the destination, then move the droid one tile towards the destination. If its’ reached the destination, set the state to Success. The check for isRunning() is made to make sure that the routine only acts if the routine is active and hasn’t finished. We also need to fill in the Droid‘s update method to make it use the routine. It’s just a simple delegation. This is how it looks like: public void update() { if (routine.getState() == null) { // hasn't started yet so we start it routine.start(); } routine.act(this, board); } It should consist only of line #6 but I also put in a check to see if the state is null and if so, then start the routine. This is a hack to start the routine the first time update is called. It’s a quasi command pattern, as in the act method gets the receiver of the action command as a parameter, which is the droid itself. I also modified the Routine class to log the different events in it, so we can see what’s happening. // --- omitted --- */ public void start() { System.out.println(">>> Starting routine: " + this.getClass().getSimpleName()); this.state = RoutineState.Running; }protected void succeed() { System.out.println(">>> Routine: " + this.getClass().getSimpleName() + " SUCCEEDED"); this.state = RoutineState.Success; }protected void fail() { System.out.println(">>> Routine: " + this.getClass().getSimpleName() + " FAILED"); this.state = RoutineState.Failure; } // --- omitted --- */ Let’s put it to test with a simple Test class. public class Test {public static void main(String[] args) { // Setup Board board = new Board(10, 10);Droid droid = new Droid("MyDroid", 5, 5, 10, 1, 2); board.addDroid(droid);Routine moveTo = new MoveTo(7, 9); droid.setRoutine(moveTo); System.out.println(droid);// Execute 5 turns and print the droid out for (int i = 0; i < 5; i++) { droid.update(); System.out.println(droid); } } } It’s a standard class with a main method which firsts sets up a square 10 x 10 Board and adds a Droid with the provided attributes at the coordinates 5,5. On line #10 we create the MoveTo routine which sets the destination to (7,9). We set this routine to be the only routine of the droid (line #11) and print the droid’s state (line #12). Then we execute 5 turns and display the droid’s state after each turn. Running the Test we see the following printed to the sysout: Droid{name=MyDroid, x=5, y=5, health=10, range=2, damage=1}>>> Starting routine: MoveToDroid{name=MyDroid, x=6, y=6, health=10, range=2, damage=1}Droid{name=MyDroid, x=7, y=7, health=10, range=2, damage=1}Droid{name=MyDroid, x=7, y=8, health=10, range=2, damage=1}>>> Routine: MoveTo SUCCEEDEDDroid{name=MyDroid, x=7, y=9, health=10, range=2, damage=1}Droid{name=MyDroid, x=7, y=9, health=10, range=2, damage=1} As we can see the droid starts at position (5,5) as expected. Calling the update method for the first time, starts the MoveTo routine. The subsequent 3 calls to the update will move the droid to the destination by changing its coordinate each turn by one. After the routine succeeded, all the calls passed to the routine are ignored, because it’s complete. This is the first step, but it’s not very helpful. Let’s say we want to have our droid wander around the board. To achieve this, we will need to execute the MoveTo routine repeatedly, but every time it restarts, the destination needs to be randomly picked. Wandering About But let’s start with the Wander routine. It’s nothing more than a MoveTo but we generate a random destination given that we know the board. public class Wander extends Routine {private static Random random = new Random(); private final Board board; private MoveTo moveTo;@Override public void start() { super.start(); this.moveTo.start(); }public void reset() { this.moveTo = new MoveTo(random.nextInt(board.getWidth()), random.nextInt(board.getHeight())); }public Wander(Board board) { super(); this.board = board; this.moveTo = new MoveTo(random.nextInt(board.getWidth()), random.nextInt(board.getHeight())); }@Override public void act(Droid droid, Board board) { if (!moveTo.isRunning()) { return; } this.moveTo.act(droid, board); if (this.moveTo.isSuccess()) { succeed(); } else if (this.moveTo.isFailure()) { fail(); } } } Following the single responsibility principle, the Wander class’s sole purpose is to pick the random destination on the board. Then it uses the MoveTo routine to get the droid to the new destination. The reset method will restart it and pick a new random destination. The destination is set in the constructor. If we’d like our droid to wander, we would change the Test class to the following: public class Test { public static void main(String[] args) { // Setup Board board = new Board(10, 10);Droid droid = new Droid("MyDroid", 5, 5, 10, 1, 2); board.addDroid(droid);Routine routine = new Wander(board); droid.setRoutine(routine); System.out.println(droid);for (int i = 0; i < 5; i++) { droid.update(); System.out.println(droid); } } } The output would be something similar to this: Droid{name=MyDroid, x=5, y=5, health=10, range=2, damage=1}>>> Starting routine: Wander>>> Starting routine: MoveToDroid{name=MyDroid, x=6, y=6, health=10, range=2, damage=1}Droid{name=MyDroid, x=7, y=7, health=10, range=2, damage=1}Droid{name=MyDroid, x=7, y=8, health=10, range=2, damage=1}>>> Routine: MoveTo SUCCEEDED>>> Routine: Wander SUCCEEDEDDroid{name=MyDroid, x=7, y=9, health=10, range=2, damage=1}Droid{name=MyDroid, x=7, y=9, health=10, range=2, damage=1} Notice how the Wander contains and delegates to the MoveTo routine. Repeat, Repeat, Repeat … This is all good but what if we want the droid to be wandering repeatedly? We will make a Repeat routine which will contain a routine to be repeated. Also we will make this routine so that it can take in a parameter to specify how many times we want to repeat a routine. If it won’t take in a parameter, then it will repeat the containing routine forever or until the droid’s dead. public class Repeat extends Routine {private final Routine routine; private int times; private int originalTimes;public Repeat(Routine routine) { super(); this.routine = routine; this.times = -1; // infinite this.originalTimes = times; }public Repeat(Routine routine, int times) { super(); if (times < 1) { throw new RuntimeException("Can't repeat negative times."); } this.routine = routine; this.times = times; this.originalTimes = times; }@Override public void start() { super.start(); this.routine.start(); }public void reset() { // reset counters this.times = originalTimes; }@Override public void act(Droid droid, Board board) { if (routine.isFailure()) { fail(); } else if (routine.isSuccess()) { if (times == 0) { succeed(); return; } if (times > 0 || times <= -1) { times--; routine.reset(); routine.start(); } } if (routine.isRunning()) { routine.act(droid, board); } } } The code is easy to follow but I’ll explain a few things that were added. The attribute routine is passed in the constructor and that will be the routine that gets repeated. The originalTimes is a storage variable that holds the initial number of times value, so we can restart the routine with the reset() call. This is just a back-up of the initial state. The times attribute is how many times the provided routine will be repeated. If it’s -1 then it’s infinite. This is all coded in the logic inside the act method. To test this out, we need to create a Repeat routine and provide what to repeat. For example, to have the droid wander endlessly, we’d have this: Routine routine = new Repeat((new Wander(board))); droid.setRoutine(routine); If we’d call the update repeatedly, we’ll see that the droid will be moving constantly. Check this sample output: Droid{name=MyDroid, x=5, y=5, health=10, range=2, damage=1}>> Starting routine: Repeat>>> Starting routine: Wander>>> Starting routine: MoveToDroid{name=MyDroid, x=4, y=6, health=10, range=2, damage=1}>>> Routine: MoveTo SUCCEEDED>>> Routine: Wander SUCCEEDEDDroid{name=MyDroid, x=4, y=7, health=10, range=2, damage=1}>>> Starting routine: Wander>>> Starting routine: MoveToDroid{name=MyDroid, x=5, y=6, health=10, range=2, damage=1}Droid{name=MyDroid, x=6, y=5, health=10, range=2, damage=1}Droid{name=MyDroid, x=7, y=4, health=10, range=2, damage=1}Droid{name=MyDroid, x=8, y=3, health=10, range=2, damage=1}Droid{name=MyDroid, x=8, y=2, health=10, range=2, damage=1}>>> Routine: MoveTo SUCCEEDED>>> Routine: Wander SUCCEEDEDDroid{name=MyDroid, x=8, y=1, health=10, range=2, damage=1}>>> Starting routine: Wander>>> Starting routine: MoveToDroid{name=MyDroid, x=7, y=2, health=10, range=2, damage=1}Droid{name=MyDroid, x=6, y=3, health=10, range=2, damage=1} Notice how the Repeat routine does not end. Assembling the Intelligence So far we’re just composing behaviours. But what if we want to add decision making to the droids and build a more complex behaviour? Enter the behaviour trees. This term doesn’t describe what it is and neither do most of the articles that I found. I’ll start with what I want to achieve first and hopefully it will all make sense. I want to implement the behaviour described at the beginning of the article. I want my droid to scan if there is a weaker droid in its range and engage it if it is, or flee otherwise. Take a look at the following diagram. It shows a tree. It’s nothing more than a routine composed of multiple different routines. Each node is a routine and we will have to implement some special routines.Let’s break the routines down.Repeat – is the routine implemented earlier. It will repeat the given routine forever or until the embedded routine fails. Sequence – the sequence routine will succeed only when all the routines that it contains have succeeded. For example to attack a droid, the enemy droid needs to be in range, the gun needs to be loaded and the droid needs to pull the trigger. Everything in this order. So the sequence contains a list of routines and acts on them until all succeed. If the gun is not loaded then there is no point in pulling the trigger so the whole attack is a failure. Selector – this routine contains a list of one or more routines. When it acts, it will succeed when one of the routines in the list succeeds. The order in which the routines are executed is set by the order in which the routines are passed in. If we’d like to randomise the execution of routines, it’s easy to create a Random routine whose sole purpose is to randomise the list of routines passed in. All the grey routines are leaves in the tree, meaning that they can’t have any subsequent routines and these are the ones that act on the droid which is the receiver.The above tree represents the very basic AI we wanted to implement. Let’s follow it through starting from the root. Repeat – will repeat the selector indefinitely until neither of the branches can be executed successfully. The routines in the selector are: Attack a droid and Wander. If both fail that means that the droid is dead. The Attack a droid routine is a sequence of routines meaning that all of them have to succeed in order for the whole branch to succeed. If it fails, then the fall back is to pick a random destination through Wander and to move there. Then repeat. All we need to do is to implement the routines. For example the IsDroidInRange could look something like this: public class IsDroidInRange extends Routine {public IsDroidInRange() {}@Override public void reset() { start(); }@Override public void act(Droid droid, Board board) { // find droid in range for (Droid enemy : board.getDroids()) { if (!droid.getName().equals(enemy)) { if (isInRange(droid, enemy)) { succeed(); break; } } } fail(); }private boolean isInRange(Droid droid, Droid enemy) { return (Math.abs(droid.getX() - enemy.getX()) <= droid.getRange() || Math.abs(droid.getY() - enemy.getY()) < droid.getRange()); } } It’s a very basic implementation. The way it determines if a droid is in range, is by iterating through all the droids on the board and if the enemy droid (assuming that the names are unique) is within range, then it succeeded. Otherwise it failed. Of course we need to feed in this droid to the next routine somehow, which is IsEnemyStronger. This can be achieved by giving the droid a context. One simple way could be that the Droid class could have an attribute nearestEnemy and on success the routine will populate that field and on failure it will clear it. This way the following routine can access the droid’s internals and use that information to work out its success or failure scenarios. Of course this can be and should be extended so the droid will contain a list of droids in its range and have a routine to work out if the droid should fly or fight. But it’s not the scope of this introduction. I won’t be implementing all the routines in the article, but you will be able to check out the code on github: https://github.com/obviam/behavior-trees and I will be adding more and more routines. Where to go from here? There are quite a few improvements that can be made just by looking at it. As a first step to test the system out, I’d move the creation of the routines to a factory for convenience. /** * Static convenience methods to create routines */ public class Routines {public static Routine sequence(Routine... routines) { Sequence sequence = new Sequence(); for (Routine routine : routines) { sequence.addRoutine(routine); } return sequence; }public static Routine selector(Routine... routines) { Selector selector = new Selector(); for (Routine routine : routines) { selector.addRoutine(routine); } return selector; }public static Routine moveTo(int x, int y) { return new MoveTo(x, y); }public static Routine repeatInfinite(Routine routine) { return new Repeat(routine); }public static Routine repeat(Routine routine, int times) { return new Repeat(routine, times); }public static Routine wander(Board board) { return new Wander(board); }public static Routine IsDroidInRange() { return new IsDroidInRange(); }} This will allow to test some scenarios out in a more elegant way. For example to place 2 droids with different behaviours you could do the following: public static void main(String[] args) { Board board = new Board(25, 25); Droid droid1 = new Droid("Droid_1", 2, 2, 10, 1, 3); Droid droid2 = new Droid("Droid_2", 10, 10, 10, 2, 2);Routine brain1 = Routines.sequence( Routines.moveTo(5, 10), Routines.moveTo(15, 12), Routines.moveTo(2, 4) ); droid1.setRoutine(brain1);Routine brain2 = Routines.sequence( Routines.repeat(Routines.wander(board), 4) ); droid2.setRoutine(brain2);for (int i = 0; i < 30; i++) { System.out.println(droid1.toString()); System.out.println(droid2.toString()); droid1.update(); droid2.update(); } } Of course this is not the best solution by far but it’s still better than the constant instantiation of routines. Ideally the AI should be scripted and loaded from an external source, either via scripting, or at least provided as a JSON for example and have a AI assembler create it. This way the game does not need to be recompiled every time the AI is tweaked. But again, it is not the scope of this article. Also, how shall we decide which action will take up a turn/tick or is evaluated instantly? One possible solution could be to allocate action points to the droid that it can spend one turn (tick if realtime) and for each action to assign a cost. Whenever the droid runs out of points, then we can move on. We’d also need to track which routine is the current one so we can optimise the traversal of the tree. This is helpful if the AIs are very complex especially in realtime games. If you think the article was useful and want to get the code, please check the github repo. You can also check back because I intend to extend it and to update it so it evolves into a more complete AI example. As it is my first encounter with AI, there will be lots of things to improve and I am always open to criticism and ideas on how to improve.https://github.com/obviam/behavior-treesReference: Game AI – An Introduction to Behaviour Trees from our JCG partner Impaler at the Against the Grain blog....
software-development-2-logo

Books That Have Most Influenced My Software Development Career

I have read numerous books on software development and have learned valuable things from most of them, but a small subset of these books has significantly influenced me and how I develop software. Effective C++ and More Effective C++ Although I had written a lot of lines of code in BASIC, Pascal, C, and C++ before starting my career, it was C++ that was my first professional programming language. As such, it was the first programming language in which I started to get past the basic syntax and learn about more advanced issues and nuances of the programming languages. For the first time, I started considering performance issues, maintainability, readability, and issues other than just whether the code worked or not. Effective C++ and More Effective C++ helped me to see that there was more to programming than basic syntax and getting functionality to work. These books helped me to realize that there are general programming concepts that are wise to follow but that there are also language-specific concepts and tips one should learn and apply in the programming language of choice. General software development principles apply across many languages, but sometimes it is necessary to know language-specific features as well.Effective Java, Editions 1 and 2 After such good experiences with Effective C++ and More Effective C++, I was excited to learn about the book called Effective Java as I was transitioning from C++ to Java, a transition several years in the making. Effective Java did not disappoint. I started reading Effective Java sooner in my Java experience than I had started reading the Scott Meyer‘s C++ books in my C++ experience and it helped me tremendously. It helped me to see from the beginning that there were more considerations when developing with Java than just writing syntax and making things work.Java Cookbook Although I have purchased and read seemingly countless Java-themed books over the years, I’ve never had a book focused on the Java language basics. Instead, I’ve always had specialized books focusing on aspects of Java or Java EE. The way that I learned the basics of the Java programming language was via the Java Cookbook. It helped me realize that I like this recipe-based approach to reading about, learning, and applying a new programming language. I’ve liked recipe-oriented books ever since, especially for quickly learning and apply a new programming language or framework.Groovy Recipes: Greasing the Wheels of Java Groovy Recipes: Greasing the Wheels of Java was my introduction to Groovy. This excellent book provides a nice introduction to Groovy that not only quickly introduces its syntax and features but also introduces practical ways that Groovy can be applied in regular everyday situations. I was able to quickly see the value of learning Groovy and to realize that Groovy was more than just a trendy language fad. This book reaffirmed my realization that I learn programming languages best from recipe-oriented books that demonstrate the language used in practical situations. Groovy Recipes: Greasing the Wheels of Java and the Groovy language itself have dramatically influenced my overall approach to software development by giving me the tools and confidence to do significantly more scripting than I used to do. Being able to script and develop software in similar languages (Groovy and Java) and use the same Java libraries and frameworks has made scripting easier. Easier scripting has meant that I’ve done more of it and spent less time doing it.Holub on Patterns: Learning Design Patterns by Looking at Code I purchased Holub on Patterns after seeing Allen Holub speak at SD West 2005 (I wasn’t the only one). Holub, the author of Why Extends is Evil and Why Getters and Setters Are Evil, challenged my way of thinking (traditional and commonly accepted way of thinking at the time) about object-oriented programming. I definitely look at objects now more from a behavioral perspective than data perspective. Also, although willing to write get/set methods when necessary, my reluctance to write them until needed has been of great benefit as the era of multicores has helped us realize the dangers of mutable state. Although Holub on Patterns does provide in-depth coverage of some common design patterns implemented in Java, the far bigger influence it had on me was in how I think about object-oriented design.Expert One-on-One J2EE Design and Development At a time when developers of enterprise Java applications were being told to use heavyweight EJBs and like it, many of us were wondering what we were missing when it seemed overly complex to us. Rod Johnson‘s J2EE Design and Development stuck a chord with me; it was relieving to see that I wasn’t the only one who thought EJB 1.x was too difficult and cumbersome. More importantly, Johnson’s book provided examples and discussion text that helped to see what parts of J2EE were worth using and which parts needed improvement. The Spring Framework was born out of the examples covered in this book and Spring’s success inspired changes in Java EE that make it much more productive and useful. J2EE Design and Development influenced me personally and influenced an entire community. It also helped me to realize that one can be correct in thinking something isn’t all it’s said to be even if the so-called experts insist it is. This has helped me weather numerous fads (and their blindly adherent evangelists) in software development since then. The book also articulated better than I could my own thoughts and feelings on enterprise Java development.Agile Web Development with Rails During my brief infatuation with Ruby on Rails, I found Agile Web Development with Rails to be a great introduction to Ruby on Rails. Although I enjoyed my foray into Rails, I have never worked with it to the same degree as I have with Java. Agile Web Development with Rails introduced me to Ruby on Rails, but more importantly it influenced my career, which has mostly not been in Rails, by demonstrating in a practical way how agile development can be done if a client is readily available to provide feedback. Agile Web Development with Rails and the Ruby on Rails framework itself helped change my way of thinking to see the value of convention over configuration. Shortly thereafter, the Java-sphere began to see changes inspired by Ruby on Rails’s success. These included Java Persistence API (JPA) adopting “configuration by exception” approach and the Grails framework. Ruby on Rails influenced much of the web development community and Agile Web Development with Rails was the tool that allowed me to most easily experience this influence personally.The Practice of Programming The Practice of Programming does not waste time with extraneous pages. The 250 page book covers the most fundamental issues in programming such as debugging, testing, performance, and portability. I read this early in my software development career and find myself reading portions of it again from time to time. Many great books have come along since that deal with these subjects, but The Practice of Programming was the first to cover most of these for me.Software Craftsmanship: The New Imperative Software Craftsmanship: The New Imperative was published at almost the perfect time for me in my career. The book helped me articulate my own observations about what made a “software engineer” more complete. In addition, this relatively short and to-the-point book helped me discover other approaches that I would later use in efforts to make my code more than just functional.201 Principles of Software Development 201 Principles of Software Development features 201 short (typically one or two paragraphs) descriptions of 201 software development principles with a reference to a generally well-recognized expert source with further details on that principle. The text is comprehensive enough to understand the principle and the references to proven sources give the reader the ability to learn in more detail how to apply the covered principle. This book not only helped me to solidify these principles in my own mind, but helped me to understand the breadth of materials available to the software developer. During my software development career, I’ve repeatedly seen trends come and go. Sometimes I’ll hear a relatively new developer talking about some “new” thing that is really just a reincarnation of the same idea in different form that its previous incarnations. 201 Principles of Software Development helped me realize at a relatively early stage in my career that many concepts and principles that were “new” to me, were really not new to the greater software development industry. Most “innovative” concepts in our industry typically share common themes or are even grounded in one or more of the principles covered in this book.Conclusion The books covered in this post have had significant influence on my software development career and how I think about software development today. Numerous other books have had lesser degree of influence. In some cases, these other books might have had more influence had I encountered them at a different (often earlier) point in my career. In fact, that might be the point of this post: different books will have different impact on different developers depending on where those developers are in their careers. The books in this post have had particularly great influence on me, but I know that other developers have been significantly influenced by books such as Code Complete, Clean Code, and numerous other books. I was surprised at how many language-specific books were on this list as I compiled it, but each was really more about that language. These books are about how to apply the language to achieve more general software development ideals and that’s where they have been most influential to me.Reference: Books That Have Most Influenced My Software Development Career from our JCG partner Dustin Marx at the Inspired by Actual Events blog....
enterprise-java-logo

Java EE: Asynchronous constructs and capabilities

Introduction Java EE has a number of APIs and constructs to support Asynchronous execution. This is vital from a scalability and performance stand point. Let us assume 2 modules which are interacting with each other. When moduleA (the sender) sends a message to moduleB (the receiver) in a Synchronous fashion, the communication takes place in the context of a Single thread i.e. the thread which initiated the communication from moduleA is blocked until moduleB responds back. This was a generic statement but can be extended to the context of a simple Java methods interacting with each other – in this case, a synchronous call from methodA to methodB would execute in the same thread which would be blocked until methodB returns or throws an exception. Why do we need Asynchronous behavior in Java EE based applications? We can further extrapolate this point to the Java EE world – be it inter server communication e.g. between web tier and EJB tier (servlets and EJBs) or a typical client server interaction – a browser interacting with a RESTful end point, Servlets etc – the server thread which responds to a client request always blocks until the server component responds back. Here is where Asynchronous execution comes into play – if the server thread processing the client request can be released/suspended and the actual business logic is executed in a separate thread (different than that of the original one), performance and scalability can be improved immensely ! E.g. if a HTTP listener thread allocated to listen to client requests is released immediately, then it is free to attend to requests from other clients and the business logic can be executed in a separate container thread which can then return the response via appropriate methods such as java.util.concurrent.Future object or via call back handlers registered by the client. Think from an end user perspective – responsiveness matters a lot! Dive In: Async constructs and APIs in Java EE Let’s take a look at few of the Async related features (APIs) in Java EE. This is not an exhaustive list – but should be a good starting point. Different Java EE specs have their typical ways and APIs to facilitate Async capabilities. Let’s explore the below Java EE specificationsJAX-RS 2.0 (Java EE 7) Websocket 1.0 (Java EE 7) Concurrency Utilities 1.0 (Java EE 7) EJB 3.1 (Java EE 6) Servlet 3.0 (Java EE 6)Note: The code presented below is in a snippet form (for obvious reasons). The complete samples can be accessed here.  JAX-RS 2.0 Async processing of requests is a new feature in 2.0 edition of JAX-RS (new in Java EE 7). In order to execute an aysnc request using JAX-RS APIs, one needs to inject a reference to a javax.ws.rs.container.AsyncResponse interface in the JAX-RS resource method itself. This parameter puts the request execution in async mode and the method proceeds with its execution. The resume method on the AsynResponse object needs to be called from within a separate thread after the business logic execution is complete. One can leverage the Java EE concurrency utility features (discussed later) such as the javax.enterprise.concurrent.ManagedExecutorService in order to encapsulate the business logic as a Runnable object and submitting it to the container’s executor service which takes care of the rest. No need to spawn un-managed, isolated threads on your own. @Path("/{id}") @GET @Produces("application/xml") public void asyncMethod(@Suspended AsyncResponse resp, @PathParam("id") String input) {System.out.println("Entered MyAsyncRESTResource/asyncMethod() executing in thread: "+ Thread.currentThread().getName()); mes.execute( () -> { System.out.println("Entered Async zone executing in thread: "+ Thread.currentThread().getName()); System.out.println("Simulating long running op via Thread sleep() started on "+ new Date().toString()); try { Thread.sleep(5000); } catch (InterruptedException ex) { Logger.getLogger(MyAsyncRESTResource.class.getName()).log(Level.SEVERE, null, ex); } System.out.println("Completed Long running op on "+new Date().toString()); System.out.println("Exiting Async zone executing in thread: "+ Thread.currentThread().getName());//creating a dummy instance of our model class (Student)Student stud = new Student(input, "Abhishek", "Apr-08-1987"); resp.resume(Response.ok(stud).build()); } );System.out.println("Exit MyAsyncRESTResource/asyncMethod() and returned thread "+Thread.currentThread().getName()+" back to thread pool"); } The JAX-RS Client API also has asynchronous capabilities but they have not been discussed in the post. They are definitely worth a look! Websocket 1.0 The Websocket API is a brand new addition to the Java EE arsenal (introduced in Java EE 7). It facilitates bi-directional (both server and client initiated) communication which is also full duplex in nature (either the client or server can send messages to each other at any time). In order to send async messages using the Websocket API, one needs to use the getAsyncRemote method available on the javax.websocket.Session interface. Internally, this is nothing but an instance of the nested interface of the javax.websocket.RemoteEnpoint – javax.websocket.RemoteEnpoint.Async. Calling the regular sendXXX methods on this would result in the sending process being executed in a separate thread. This is particularly useful when you consider exchange of large messages or handling large numbers of websocket clients to whom the messages need to be sent. The method wither returns a java.util.concurrent.Future object or one can register a callback in the form of a javax.websocket.SendHandler interface implementation. public void sendMsg(@Observes Stock stock) { System.out.println("Message receieved by MessageObserver --> "+ stock); System.out.println("peers.size() --> "+ peers.size()); peers.stream().forEach((aPeer) -> { //stock.setPrice();aPeer.getAsyncRemote().sendText(stock.toString(), (result) -> { System.out.println("Message Sent? " + result.isOK()); System.out.println("Thread : " + Thread.currentThread().getName()); });}); } Concurrency Utilities 1.0 The Java EE Concurrency Utilities is another great addition to Java EE 7. It provides a standard way of spawning threads – the good part is that these are container managed and not just isolated/orphan threads about which the container has no contextual information. In general, the Concurrency Utilities 1.0 provide a few standard constructs for execution of asynchronous tasks in separate threads. These are as follows – javax.enterprise.concurrent.ManagedExecutorService  and javax.enterprise.concurrent.ManagedScheduledExecutorService. In order to start a new task in a separate thread, one can use the ManagedExecutorService interface to submit a Runnable. In addition to implementing the Runnable interface, a class can also implement the javax.enterprise.concurrent.ManagedTask interface and provide a  javax.enterprise.concurrent.ManagedTaskListener implementation in order to listen to life  cycle changes to the task submitted via the ManagedExecutorService. @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("Enter AConcurrencyUtilsExample/doGet executing in thread "+ Thread.currentThread().getName()); System.out.println("initiating task . . . "); mes.execute(new AManagedTask()); System.out.println("Exit AConcurrencyUtilsExample/doGet and returning thread "+ Thread.currentThread().getName() +" back to pool"); } Servlet 3.0 Asynchronous HTTP was introduced in Servlet 3.0 (part of Java EE 6) which basically provided the capability to execute the request in separate thread and suspend the original thread which handled the client invocation. The key player here is the javax.servlet.AsyncContext interface. In order to initiate asynchronous processing, the startAsync method of the java.servlet.ServletRequest interface is called. In order to execute the core logic, a java.lang.Runnable object needs to be submitted to the start method of the AsyncContext interface. One can choose to attach a listener by implementing the javax.servlet.AsyncListener in order to receive callback notifications during specific times of the Async task execution. @Overridepublic void doGet(HttpServletRequest req, HttpServletResponse resp) {PrintWriter writer = null; try { writer = resp.getWriter(); } catch (IOException ex) { Logger.getLogger(MyAsyncServlet.class.getName()).log(Level.SEVERE, null, ex); } //System.out.println("entered doGet()"); writer.println("ENTERING ... " + MyAsyncServlet.class.getSimpleName() + "/doGet()"); writer.println("Executing in Thread: " + Thread.currentThread().getName()); //step 1 final AsyncContext asyncContext = req.startAsync();//step 2 asyncContext.addListener(new CustomAsyncHandler(asyncContext));//step 3 asyncContext.start( () -> { PrintWriter logger = null; try { logger = asyncContext.getResponse().getWriter(); } catch (IOException ex) { Logger.getLogger(MyAsyncServlet.class.getName()).log(Level.SEVERE, null, ex); }logger.println("Long running Aync task execution started : " + new Date().toString());logger.println("Executing in Thread: " + Thread.currentThread().getName()); try { Thread.sleep(5000); } catch (InterruptedException e) { Logger.getLogger(MyAsyncServlet.class.getName()).log(Level.SEVERE, null, e); }logger.println("Long task execution complete : " + new Date().toString());logger.println("Calling complete() on AsyncContext");//step 4 asyncContext.complete(); } );writer.println("EXITING ... " + MyAsyncServlet.class.getSimpleName() + "/doGet() and returning initial thread back to the thread pool");} EJB 3.1 Typically, (prior to EJB 3.1) EJB Message Driven Beans were used to fulfill async related requirements. A MDB bean listens to messages sent to a javax.jms.Destination (a Queue or Topic) and executes the required business logic – this might be anything from sending an email to initiating an order processing task. The important thing to understand is that the client which sends the message to the Queue in the first place is unaware of the MDB (decoupled) and does not have to wait/remain blocked until the end of the job (email receipt or order processing confirmation). EJB 3.1 (part of Java EE 6) introduced the javax.ejb.Asynchronous annotation. This can be placed on a EJB Session bean (Stateless, Stateful or Singleton) class (makes all the methods Asynchronous) or at the method level itself – in case fine grained control is needed. A method with the @Asynchronous annotation can either return void (fire and forget) or an instance of java.util.concurrent.Future if the async method result needs to be tracked – this can be done by calling the Future.get() – the thing to note is that the get method itself is blocking in nature. @Asynchronous public Future<String> asyncEJB2(){System.out.println("Entered MyAsyncEJB/asyncEJB2()"); System.out.println("MyAsyncEJB/asyncEJB2() Executing in thread: "+ Thread.currentThread().getName()); System.out.println("Pretending as if MyAsyncEJB/asyncEJB2() is doing something !"); try { Thread.sleep(5000); } catch (InterruptedException ex) { java.util.logging.Logger.getLogger(MyAsyncEJB.class.getName()).log(Level.SEVERE, null, ex); }System.out.println("Exiting MyAsyncEJB/asyncEJB2()"); return new AsyncResult("Finished Executing on "+ new Date().toString());} This was a rather brief preview of Java EE capabilities. These APIs and specifications are functionally rich and it is hard cover all of them via a blog post! I hope this piques your interest and gives you a starting point to explore further. Cheers!Reference: Java EE: Asynchronous constructs and capabilities from our JCG partner Abhishek Gupta at the Object Oriented.. blog....
hawtio-logo

HawtIO on JBoss EAP (Part II)

I just posted an entry on running HawtIO on JBoss Wildfly 8.1 recently. From that post you know how awesome HawtIO is, and all of the cool plugins it has to make managing your JVM based technologies from a single dashboard… well… hawt….However, I wanted to dedicate a post to running HawtIO on JBoss EAP for the same reasons outlined in the previous post: As we at Red Hat roll out JBoss Fuse and JBoss Fuse Serviceworks, we’re getting better at integrating the individual components. For example, a Fuse Service Works subscription gives you full access to A-MQ, Fuse, and all of its components, including HawtIO. Unfortunately, HawtIO isn’t “officially” supported in EAP as of today, but that will be fixed in next releases. It’s not a limitation of the technology, it’s just there’s so much there and Red Hat has stringent testing/compatibility requirements so we need to have all of the testing/certification done before we “support it” fully. BUT… there’s really no reason to not use it anyway (at least Development and QA), while we wait for support. And there are lots of people already doing that. Just remember, it’s not officially supported yet! So the rest of this blog is a step-by-step guide with best practices for getting HawtIO deployed and secured on your JBoss EAP 6.x application server. I will use HawtIO 1.4.11 (latest release from the community) for this guide.HawtIO on JBoss EAP 6.1 This first section will discuss EAP 6.1 because it seems to work great following the similar directions as those for deploying HawtIO on Wildfly 8.1. Basically, if you follow the instructions from the blog post on running on Wildfly, you’ll get it working just fine. To be very specific do these pieces:Remove the log4j.properties file to use EAP logging subsystem Rename distro to hawtio.war Create users in ApplicationRealm with roles including “admin” Edit the standalone.xml file to account for the following settings:I’ve also added [these instructions to the HawtIO documentation][http://hawt.io/getstarted/index.html] (the website should update with those changes soon). After successfully deploying HawtIO to JBoss EAP 6.1, you should be greeted with a login page at this URL: http://localhost:8080/hawtioHawtIO on JBoss EAP 6.2 So unfortunately, getting HawtIO to run on JBoss EAP 6.2 has some issues with JAAS that I haven’t been able to figure out. If you’re a Wildfly 7/EAP 6.x wizard and wish to take a look have a peek at the github issue I have open. Thankfully, however, HawtIO is quite versatile and doesn’t have to be run as a web-app collocated on the container you want to manage. You can run it standalone as a Chrome extension or in a separate container that’s not JBoss EAP. Effectively, you can use HawtIO’s Connect page to remotely connect to the container you wish to manage. For example, download the standalone distribution of HawtIO which ends up just being an executable jar. Run it like this (make sure to add the params for the port change, because we don’t want to conflict with the EAP ports if running on the same machine): ceposta@postamachat(standalone) $ java -jar hawtio-app-1.4.11.jar --port 9091 This will bring up HawtIO running standalone (with an internal Jetty server! Woohoo!). Then click the “Connect” tab and you should see a page like this:Wait, what? Just connect? “How would this even work”” you ask? “How can we connect to EAP and have HawtIO just manage it?” Well, the magic is this totally awesome little library named Jolokia.Jolokia provides REST access to your JMX tree. So the way to get HawtIO to manage your JBoss EAP 6.2 container is to enable Jolokia on it and then use HawtIO’s Connect tab to log in. If you haven’t taken a look at Jolokia, you’re missing out!! No more complicated JMX API/clients and query/filter API. Just use REST endpoints and curl. Simple. Jolokia has a few options for deploying/enabling. The most straight forward is a web app, but you could also attach as a JVM agent at startup time. We’ll take the easy approach and deploy Jolokia as a webapp: Rename distro For this blog post, I’m using Jolokia 1.2.2. So when you download it, it has a name like this jolokia-1.2.2.war. Let’s rename the distro so we don’t take into account the version numbers to make it easier to get to the URL: ceposta@postamachat(rename) $ mv jolokia-war-1.2.2.war jolokia.war Enable security for Jolokia Next, we want to enable security for the jolokia web app. We’ll do that as described in the Jolokia documentation. We’ll need to edit the web.xml file that comes in the Jolokia jar and uncomment the section that’s blocked out for security: ceposta@postamachat(rename) $ vi jolokia.war Your config in WEB-INF/web.xml should have a security section like this: 163 <!-- 164 Example Configuration for switching on BASIC security. The role 'Jolokia' 165 must be mapped to real users with passwords on the Appserver side: 166 --> 167 <login-config> 168 <auth-method>BASIC</auth-method> 169 <realm-name>Jolokia</realm-name> 170 </login-config> 171 172 <security-constraint> 173 <web-resource-collection> 174 <web-resource-name>Jolokia-Agent Access</web-resource-name> 175 <url-pattern>/*</url-pattern> 176 </web-resource-collection> 177 <auth-constraint> 178 <role-name>Jolokia</role-name> 179 </auth-constraint> 180 </security-constraint> 181 182 <security-role> 183 <role-name>Jolokia</role-name> 184 </security-role> 185 186 </web-app> Now add a user like we did in the previous blog that has a role of “Jolokia”. Note, make sure this user is added to the ApplicationRealm. Connect to EAP 6.2 Now go back to your standalone HawtIO (we deployed it in the previous step at http://localhost:9091/hawtio) and enter the connect params (path as follows):Click “Connect to remote server” and viola! You’re conencted. Where to go from here You can also try to enable SSL over the http connection as well as maybe use DIGEST auth instead of the default BASIC auth. I’ll leave that as an exercise for the reader!Reference: HawtIO on JBoss EAP (Part II) from our JCG partner Christian Posta at the Christian Posta – Software Blog blog....
java-logo

Decorator Design Pattern Applied

Hi there! Today i’m gonna show the decorator design pattern in action. The decorator design pattern is a largelly used design pattern while dealing with grafics, trees and dynamic changes during runtime. It is also a greate choice if you are looking or trying to do recursion with. I love it. In this post we will implement a students decoration. We will decorate it with degrees and doctor titles. A nice example to see how it works in the real world. First of all, let’s take a look at the UML diagram of it in its simpliest variety. After that we will take the analogy for our example. The simpliest UML Pay close attention, because once you understand that, everything will become clear and simple to understand. That’s the reason I’m putting the simplest model here first.Understanding the Details The decorable will be every concrete implementation of the common interace Decorable. The decorators will be every implementation of the abstract class Decorator. Which defines the decorator’s contract holding an instance to decorables. Let’s dive into some code to fix it: // 1. COMMON INTERFACE FOR DECORABLES public interface Decorable { public String getDescription(); } // 2. THE ABSTRACT DECORADOR WHICH HOLDS A REFERENCE TO DECORABLES public abstract class Decorator implements Decorable { protected Decorable component; public Decorator(Decorable component){ super(); this.component=component; } } The Analogy to our Students example Let’s start again with the UML diagram first:The common decorable Girl Here we start with the analogies. The interface Girl is the decorable. GirlDecorator defines the abstract decorator’s contract with the concrete decorators bellow. // 1. COMMON INTERFACE FOR DECORABLES public interface Girl { public String getDescription(); } // 2. THE ABSTRACT DECORADOR WHICH HOLDS A REFERENCE TO DECORABLES public abstract class GirlDecorator implements Girl { protected Girl girl; public GirlDecorator(Girl girl){ super(); this.girl=girl; } } // 3. DEFINING CONCRETE DECORATORS public class Science extends GirlDecorator { public Science(Girl girl) {super(girl);} @Override public String getDescription() { // DECORATES WITH A SCIENCE'S DEGREE return girl.getDescription() + "+Like Science"; } public void caltulateStuff() { // ADDS NEW FEATURES (METHOD) TO IT System.out.println("scientific calculation!"); } } public class Art extends GirlDecorator { public Art(Girl girl) {super(girl);} @Override public String getDescription() {return girl.getDescription() + "+Like Art";} public void draw() {System.out.println("draw pictures!");} } public class Doctor extends GirlDecorator { public Doctor(Girl girl) {super(girl);} @Override public String getDescription() {return girl.getDescription() + "+Like Doctor";} public void calculateStuff() {System.out.println("doctor calculation!");} public void doctorTitle() {System.out.println("doctor title");} } The Decorables AmericanGirl and EuropeanGirl are the decorable that will be decorated with degrees and doctor tittles at runtime enhancing its curriculum and abilities. // 4. AN AMERICAN GIRL WILL BE DEFINED AS A DECORABLE public class AmericanGirl implements Girl { private String description=""; // NORMAL AMERICAN GIRL public AmericanGirl(){ super(); description = "+American"; } @Override public String getDescription() {return description;} } public class EuropeanGirl implements Girl { private String description=""; public EuropeanGirl() { super(); description = "+European"; } @Override public String getDescription() {return description;} } Testing it Now let’s see in practise how it looks like. How we can decorate and enhance its abilities at runtime: public class Client { public static void main(String[] args) { // COMMOM GIRL Girl girl; // CREATING NORMAL AMERICAN GIRL girl = new AmericanGirl(); System.out.println(girl.getDescription()); // DECORANTING AMERICANA GIRL WITH SCIENCE'S DEGREE girl = new Science(girl); System.out.println(girl.getDescription()); // DECORANTING AMERICANA GIRL WITH ART'S DEGREE girl = new Art(girl); System.out.println(girl.getDescription()); // EUROPEAN GIRL HAS ALREADY ALL DEGREES Girl europeia = new Science(new Art(new EuropeanGirl())); System.out.println(europeia.getDescription()); // DOCTOR HAS NEW FUNCTIONS girl = new Doctor(girl); System.out.println(girl.getDescription()); // BECAUSE DOCTOR EXTENDS FROM COMMON GIRL, IT CAN DO A DOWNCAST ((Doctor)girl).doctorTitle(); ((Doctor)girl).calculateStuff(); // PAY ATTENTION THAT WE USE THE SAME INSTANCE, BUT THEY BEHAVIOR DIFFERENT // AT DIFFERENT TIME SLOTS. THE CLIENT HAS THE IMPRESSION THAT WE HAVE // CHANGED THE IMPLEMENTATION, BUT IN FACT NOT. } } That’s all! Hope you like it!Reference: Decorator Design Pattern Applied from our JCG partner Ricardo Ferreira at the Clean Code Development – Quality Seal blog....
enterprise-java-logo

Writing Clean Tests – To Verify Or Not To Verify

When we write unit tests that use mock objects, we follow these steps:                    Configure the behavior of our mock objects. Invoke the tested method. Verify that the correct methods of our mock objects were invoked.The description of the third step is actually a bit misleading, because often we end up verifying that the correct methods were invoked AND that the other methods of our mock objects were not invoked. And everyone knows that if we want to write bug free software, we have to verify both of these things or bad things happen. Right? Let’s Verify Everything Let’s start by taking a look at the implementation of a service method that is used to add new user accounts to the database. The requirements of this service method are:If the email address of the registered user account is not unique, our service method must throw an exception. If the registered user account has a unique email address, our service method must add a new user account to the database. If the registered user account has a unique email address and it is created by using normal sign in, our service method must encode the user’s password before it is saved to the database. If the registered user account has a unique email address and it is created by using social sign in, our service method must save the used social sign in provider. A user account that was created by using social sign in must not have a password. Our service method must return the information of the created user account.If you want learn how you can specify the requirements of a service method, you should read the following blog posts:From Top to Bottom: TDD for Web Applications From Idea to Code: The Lifecycle of Agile SpecificationsThis service method is implemented by following these steps:The service method checks that the email address given by user is not found from the database. It does this by invoking the findByEmail() method of the UserRepository interface. If the User object is found, the service method method throws a DuplicateEmailException. It creates a new User object. If the registration is made by using a normal sign in (the signInProvider property of the RegistrationForm class is not set), the service method encodes the password provided by user, and sets the encoded password to the created User object. The service methods saves the information of the created User object to the database and returns the saved User object.The source code of the RepositoryUserService class looks as follows: import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;@Service public class RepositoryUserService implements UserService {private PasswordEncoder passwordEncoder;private UserRepository repository;@Autowired public RepositoryUserService(PasswordEncoder passwordEncoder, UserRepository repository) { this.passwordEncoder = passwordEncoder; this.repository = repository; }@Transactional @Override public User registerNewUserAccount(RegistrationForm userAccountData) throws DuplicateEmailException { if (emailExist(userAccountData.getEmail())) { throw new DuplicateEmailException("The email address: " + userAccountData.getEmail() + " is already in use."); }String encodedPassword = encodePassword(userAccountData);User registered = User.getBuilder() .email(userAccountData.getEmail()) .firstName(userAccountData.getFirstName()) .lastName(userAccountData.getLastName()) .password(encodedPassword) .signInProvider(userAccountData.getSignInProvider()) .build();return repository.save(registered); }private boolean emailExist(String email) { User user = repository.findByEmail(email);if (user != null) { return true; }return false; }private String encodePassword(RegistrationForm dto) { String encodedPassword = null;if (dto.isNormalRegistration()) { encodedPassword = passwordEncoder.encode(dto.getPassword()); }return encodedPassword; } } If we want write unit tests which ensure that our service method is working correctly when the user is registering a new user account by using social sign in AND we want to verify every interaction between our service method and our mock objects, we have to write eight unit tests for it. We have to ensure that:The service methods checks that email address is unique when a duplicate email address is given. The DuplicateEmailException is thrown when a duplicate email address is given. The service method doesn’t save a new account to the database when a duplicate email address is given. Our service method doesn’t encode the user’s password if a duplicate email address is given. Our service method checks that the email address is unique when a unique email address is given. When a unique email address is given, our service method creates a new User object that contains the correct information and saves the information of the created User object to the database. When a unique email address is given, our service method returns the information of the created user account. When a unique email address is given and a social sign in is used, our service method must not set the password of the created user account (or encode it).The source code of our test class looks as follows: import net.petrikainulainen.spring.social.signinmvc.user.dto.RegistrationForm; import net.petrikainulainen.spring.social.signinmvc.user.dto.RegistrationFormBuilder; import net.petrikainulainen.spring.social.signinmvc.user.model.SocialMediaService; import net.petrikainulainen.spring.social.signinmvc.user.model.User; import net.petrikainulainen.spring.social.signinmvc.user.repository.UserRepository; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; import org.springframework.security.crypto.password.PasswordEncoder;import static com.googlecode.catchexception.CatchException.catchException; import static com.googlecode.catchexception.CatchException.caughtException; import static net.petrikainulainen.spring.social.signinmvc.user.model.UserAssert.assertThatUser; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when;@RunWith(MockitoJUnitRunner.class) public class RepositoryUserServiceTest {private static final String REGISTRATION_EMAIL_ADDRESS = "john.smith@gmail.com"; private static final String REGISTRATION_FIRST_NAME = "John"; private static final String REGISTRATION_LAST_NAME = "Smith"; private static final SocialMediaService SOCIAL_SIGN_IN_PROVIDER = SocialMediaService.TWITTER;private RepositoryUserService registrationService;@Mock private PasswordEncoder passwordEncoder;@Mock private UserRepository repository;@Before public void setUp() { registrationService = new RepositoryUserService(passwordEncoder, repository); }@Test public void registerNewUserAccount_SocialSignInAndDuplicateEmail_ShouldCheckThatEmailIsUnique() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(new User());catchException(registrationService).registerNewUserAccount(registration);verify(repository, times(1)).findByEmail(REGISTRATION_EMAIL_ADDRESS); }@Test public void registerNewUserAccount_SocialSignInAndDuplicateEmail_ShouldThrowException() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(new User());catchException(registrationService).registerNewUserAccount(registration);assertThat(caughtException()).isExactlyInstanceOf(DuplicateEmailException.class); }@Test public void registerNewUserAccount_SocialSignInAndDuplicateEmail_ShouldNotSaveNewUserAccount() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(new User());catchException(registrationService).registerNewUserAccount(registration);verify(repository, never()).save(isA(User.class)); }@Test public void registerNewUserAccount_SocialSignInAndDuplicateEmail_ShouldNotCreateEncodedPasswordForUser() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(new User());catchException(registrationService).registerNewUserAccount(registration);verifyZeroInteractions(passwordEncoder); }@Test public void registerNewUserAccount_SocialSignInAndUniqueEmail_ShouldCheckThatEmailIsUnique() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);registrationService.registerNewUserAccount(registration);verify(repository, times(1)).findByEmail(REGISTRATION_EMAIL_ADDRESS); }@Test public void registerNewUserAccount_SocialSignInAndUniqueEmail_ShouldSaveNewUserAccountAndSetSignInProvider() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);registrationService.registerNewUserAccount(registration);ArgumentCaptor<User> userAccountArgument = ArgumentCaptor.forClass(User.class); verify(repository, times(1)).save(userAccountArgument.capture());User createdUserAccount = userAccountArgument.getValue();assertThatUser(createdUserAccount) .hasEmail(REGISTRATION_EMAIL_ADDRESS) .hasFirstName(REGISTRATION_FIRST_NAME) .hasLastName(REGISTRATION_LAST_NAME) .isRegisteredUser() .isRegisteredByUsingSignInProvider(SOCIAL_SIGN_IN_PROVIDER); }@Test public void registerNewUserAccount_SocialSignInAndUniqueEmail_ShouldReturnCreatedUserAccount() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);when(repository.save(isA(User.class))).thenAnswer(new Answer<User>() { @Override public User answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); return (User) arguments[0]; } });User createdUserAccount = registrationService.registerNewUserAccount(registration);assertThatUser(createdUserAccount) .hasEmail(REGISTRATION_EMAIL_ADDRESS) .hasFirstName(REGISTRATION_FIRST_NAME) .hasLastName(REGISTRATION_LAST_NAME) .isRegisteredUser() .isRegisteredByUsingSignInProvider(SOCIAL_SIGN_IN_PROVIDER); }@Test public void registerNewUserAccount_SocialSignInAnUniqueEmail_ShouldNotCreateEncodedPasswordForUser() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);registrationService.registerNewUserAccount(registration);verifyZeroInteractions(passwordEncoder); } } These unit tests are written by following the instructions given in the previous parts of this tutorial. That class has a lot of unit tests. Are we sure that every one of them is really necessary? Or Maybe Not The obvious problem is that we wrote two unit tests which both verify that our service method checks that the email address given by the user is unique. We could fix this by combining these tests into a single unit test. After all, one test should convince us that our service method verifies that the email address given by user is unique before it creates a new user account. However, if we do this, we won’t find an answer to a much more interesting question. This question is: Should we really verify every interaction between the tested code and our mock objects? A few months I ago I ran into an article titled: Why Most Unit Testing is Waste by James Coplien. This article makes several good points but one of them was suits very well in this situation. James Coplien argued that we should ask one question about every test in our test suite: If this test fails, what business requirement is compromised? He also explains why this is such an important question: Most of the time, the answer is, “I don’t know.” If you don’t know the value of the test, then the test theoretically could have zero business value. The test does have a cost: maintenance, computing time, administration, and so forth. That means the test could have net negative value. That is the fourth category of tests to remove. Let’s find out what happens when we evaluate our unit tests by using this question. Popping Up the Question When the ask the question: “If this test fails, what business requirement is compromised?” about every unit test of our test class, we get the following answers:The service method checks that email address is unique when a duplicate email address is given.User must have a unique email address.The DuplicateEmailException is thrown when a duplicate email address is given.User must have a unique email address.The service method doesn’t save a new account to the database when a duplicate email address is given.User must have a unique email address.Our service method doesn’t encode the user’s password if a duplicate email address is given.-Our service method checks that the email address is unique when a unique email address is given.User must have a unique email address.When a unique email address is given, our service method creates a new User object that contains the correct information and saves the information of the created User object to the used database.If the registered user account has unique email address, it must be saved to the database. If the registered user account is created by using social sign in, our service method must save the used social sign in provider.When a unique email address is given, our service method returns the information of the created user account.Our service method must return the information of the created user account.When a unique email address is given and a social sign in is used, our service method must not set the password of the created user account (or encode it).User account that is created by using social sign in has no password.At first it looks like our test class has only one unit test that has no business value (or which might have a negative net value). This unit test ensures that there are no interactions between our code and the PasswordEncoder mock when a user tries to create a new user account by using a duplicate email address. It is clear that we must delete this unit test, but this is not the only unit test that must be deleted. The Rabbit Hole Is Deeper than Expected Earlier we noticed that our test class contains two unit tests that both verify that the findByEmail() method of the UserRepository interface is called. When we take a closer look at the implementation of the tested service method, we notice that:Our service method throws a DuplicateEmailException when the findByEmail() method of the UserRepository interface returns a User object. Our service method creates a new user account when the findByEmail() method of the UserRepository interface returns null.The relevant part of the tested service method looks as follows: public User registerNewUserAccount(RegistrationForm userAccountData) throws DuplicateEmailException { if (emailExist(userAccountData.getEmail())) { //If the PersonRepository returns a Person object, an exception is thrown. throw new DuplicateEmailException("The email address: " + userAccountData.getEmail() + " is already in use."); }//If the PersonRepository returns null, the execution of this method continues. }private boolean emailExist(String email) { User user = repository.findByEmail(email);if (user != null) { return true; }return false; } I argue that we should remove both of these unit tests because of two reasons:As long as we have configured the PersonRepository mock correctly, we know that its findByEmail() method was called by using the correct method parameter. Although we can link these test cases to a business requirement (user’s email address must be unique), we don’t need them to verify that this business requirement isn’t compromised. These unit tests don’t document the API of our service method. They document its implementation. Tests like this are harmful because they litter our test suite with irrelevant tests and they make refactoring harder.If we don’t configure our mock objects, they return “nice” values. The Mockito FAQ states that: In order to be transparent and unobtrusive all Mockito mocks by default return ‘nice’ values. For example: zeros, falseys, empty collections or nulls. Refer to javadocs about stubbing to see exactly what values are returned by default. This why we should always configure the relevant mock objects! If we don’t do so, our tests might be useless. Let’s move on and clean up this mess. Cleaning Up the Mess After we have removed these unit tests from our test class, its source code looks as follows: import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; import org.springframework.security.crypto.password.PasswordEncoder;import static com.googlecode.catchexception.CatchException.catchException; import static com.googlecode.catchexception.CatchException.caughtException; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when;@RunWith(MockitoJUnitRunner.class) public class RepositoryUserServiceTest {private static final String REGISTRATION_EMAIL_ADDRESS = "john.smith@gmail.com"; private static final String REGISTRATION_FIRST_NAME = "John"; private static final String REGISTRATION_LAST_NAME = "Smith"; private static final SocialMediaService SOCIAL_SIGN_IN_PROVIDER = SocialMediaService.TWITTER;private RepositoryUserService registrationService;@Mock private PasswordEncoder passwordEncoder;@Mock private UserRepository repository;@Before public void setUp() { registrationService = new RepositoryUserService(passwordEncoder, repository); }@Test public void registerNewUserAccount_SocialSignInAndDuplicateEmail_ShouldThrowException() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(new User());catchException(registrationService).registerNewUserAccount(registration);assertThat(caughtException()).isExactlyInstanceOf(DuplicateEmailException.class); }@Test public void registerNewUserAccount_SocialSignInAndDuplicateEmail_ShouldNotSaveNewUserAccount() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(new User());catchException(registrationService).registerNewUserAccount(registration);verify(repository, never()).save(isA(User.class)); }@Test public void registerNewUserAccount_SocialSignInAndUniqueEmail_ShouldSaveNewUserAccountAndSetSignInProvider() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);registrationService.registerNewUserAccount(registration);ArgumentCaptor<User> userAccountArgument = ArgumentCaptor.forClass(User.class); verify(repository, times(1)).save(userAccountArgument.capture());User createdUserAccount = userAccountArgument.getValue();assertThatUser(createdUserAccount) .hasEmail(REGISTRATION_EMAIL_ADDRESS) .hasFirstName(REGISTRATION_FIRST_NAME) .hasLastName(REGISTRATION_LAST_NAME) .isRegisteredUser() .isRegisteredByUsingSignInProvider(SOCIAL_SIGN_IN_PROVIDER); }@Test public void registerNewUserAccount_SocialSignInAndUniqueEmail_ShouldReturnCreatedUserAccount() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);when(repository.save(isA(User.class))).thenAnswer(new Answer<User>() { @Override public User answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); return (User) arguments[0]; } });User createdUserAccount = registrationService.registerNewUserAccount(registration);assertThatUser(createdUserAccount) .hasEmail(REGISTRATION_EMAIL_ADDRESS) .hasFirstName(REGISTRATION_FIRST_NAME) .hasLastName(REGISTRATION_LAST_NAME) .isRegisteredUser() .isRegisteredByUsingSignInProvider(SOCIAL_SIGN_IN_PROVIDER); }@Test public void registerNewUserAccount_SocialSignInAnUniqueEmail_ShouldNotCreateEncodedPasswordForUser() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);registrationService.registerNewUserAccount(registration);verifyZeroInteractions(passwordEncoder); } } We removed three unit tests from our test class, and as a result, we can enjoy the following benefits:Our test class has less unit unit tests. This might seem like a strange benefit because often we are advised to write as many unit tests as possible. However, if we think about this, having less unit tests makes sense because we have less tests to maintain. This and the fact that each unit tests only one thing makes our code easier to maintain and refactor. We have improved the quality of our documentation. The removed unit tests didn’t document the public API of the tested service method. They documented its implementation. Because these tests were removed, it is easier to figure out the requirements of the tested service method.Summary This blog post has taught us three things:If we cannot identify the business requirement that is compromised if a unit test fails, we shouldn’t write that test. We should not write unit tests that don’t document the public API of the tested method because these tests make our code (and tests) harder to maintain and refactor. If we find existing unit tests that break these two rules, we should delete them.We have achieved a lot during this tutorial. Do you think that it is possible to make these unit tests even better? If you want to learn more about writing clean tests, read all parts of my Writing Clean Tests tutorial.Reference: Writing Clean Tests – To Verify Or Not To Verify from our JCG partner Petri Kainulainen at the Petri Kainulainen blog....
apache-maven-logo

Maven Git Release

I need to start this post by stating that I’ve only started to work seriously with Git within the last year. Unfortunately, a lot of the projects that I work on are still using SVN or CVS, but I’m now finally starting in a few that use Git. During the last few years, I’ve done a lot of software releases using Maven Release Plugin. I still remember that I’ve took a full week just to setup the plugin in one of my projects. It worked well most of the times, but if something went wrong you could spend the next few hours fixing the problem. Oh boy, what a nightmare! Recently, I wanted to do the same operation with a Git project and I came across with the Maven JGit-Flow Plugin and I have to tell you that this is fantastic! Very easy to setup and worked flawlessly on the first try! This plugin is based on the development model described in the post A successful Git branching model by Vincent Driessen. Take your time to read it, since it’s very interesting. I’m going to show you how to perform a release using this plugin. I’ll use the project from my latest post about Spring Batch as Wildfly Module. Setup Setup is very easy, just add the following to your pom.xml: om-jgitflow-maven-plugin.xml <plugin> <groupId>external.atlassian.jgitflow</groupId> <artifactId>jgitflow-maven-plugin</artifactId> <version>1.0-m3</version> <configuration> <noDeploy>true</noDeploy> </configuration> </plugin> I’ve just added the noDeploy configuration, because I’m not releasing to a Maven repository. That’s it! Release Let’s look at my project branches and version: branches radcortez:wildfly-spring-batch radcortez$ git branch -avv * master 0b2364b [origin/master] Added documentation. remotes/origin/master 0b2364b Added documentation. radcortez:wildfly-spring-batch radcortez$ mvn help:evaluate -Dexpression=project.version [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building wildfly-spring-batch 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-help-plugin:2.2:evaluate (default-cli) @ wildfly-spring-batch --- [INFO] No artifact parameter specified, using 'com.cortez.wildfly.batch:wildfly-spring-batch:war:1.0-SNAPSHOT' as project. [INFO] 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ Now, just run mvn jgitflow:release-start: release-prepare radcortez:wildfly-spring-batch radcortez$ mvn jgitflow:release-start [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building wildfly-spring-batch 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- jgitflow-maven-plugin:1.0-m3:release-start (default-cli) @ wildfly-spring-batch --- [INFO] ensuring origin exists... [INFO] (develop) Checking for SNAPSHOT version in projects... [INFO] (develop) Checking dependencies and plugins for snapshots ... What is the release version for "wildfly-spring-batch"? (com.cortez.wildfly.batch:wildfly-spring-batch) [1.0]: [INFO] ensuring origin exists... [INFO] (release/1.0) adding snapshot to pom versions... [INFO] (release/1.0) updating poms for all projects... [INFO] turn on debug logging with -X to see exact changes [INFO] (release/1.0) updating pom for wildfly-spring-batch... What is the development version for "wildfly-spring-batch"? (com.cortez.wildfly.batch:wildfly-spring-batch) [1.1-SNAPSHOT]: [INFO] (develop) updating poms with next development version... [INFO] (develop) updating poms for all projects... [INFO] turn on debug logging with -X to see exact changes [INFO] (develop) updating pom for wildfly-spring-batch... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ You get an interactive menu to pick the version numbers you want to release, the same way as Maven Release Plugin. I’m developing on the master branch, but during this process a release branch is created with the release versions and development branch with the new development versions. release-prepare-branches radcortez:wildfly-spring-batch radcortez$ git branch -avv develop 728856a [origin/develop] updating poms for 1.1-SNAPSHOT development master 0b2364b [origin/master] Added documentation. * release/1.0 9f88a42 updating poms for branch '1.0' with snapshot versions remotes/origin/master 0b2364b Added documentation. Now the cool thing about this, is that everything is still in your local environment! If you are not happy with the changes, you can get rid of the branches and start over. No build was performed at this point. If we want to release, just run mvn jgitflow:release-finish: release-finish radcortez:wildfly-spring-batch radcortez$ mvn jgitflow:release-finish [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building wildfly-spring-batch 1.0 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- jgitflow-maven-plugin:1.0-m3:release-finish (default-cli) @ wildfly-spring-batch --- [INFO] ensuring origin exists... [INFO] running jgitflow release finish... [INFO] ensuring origin exists... [INFO] (release/1.0) Updating poms for RELEASE [INFO] (release/1.0) removing snapshot from pom versions... [INFO] (release/1.0) updating poms for all projects... [INFO] turn on debug logging with -X to see exact changes [INFO] (release/1.0) updating pom for wildfly-spring-batch... [INFO] (release/1.0) Checking for RELEASE version in projects... [INFO] (release/1.0) Checking dependencies and plugins for snapshots ... [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building wildfly-spring-batch 1.0 In this step, the release branch is going to get merged as described in A successful Git branching model and create the tag. Remember, nothing has been pushed yet, so you can always revert the process. Let’s have a look into the branches and tags now: branch-tag radcortez:wildfly-spring-batch radcortez$ git branch -avv * develop a8e762b [origin/develop] Updating develop poms back to pre merge state master b6fbda0 [origin/master: ahead 3] Merge branch 'release/1.0' remotes/origin/master 0b2364b Added documentation. radcortez:wildfly-spring-batch radcortez$ git tag 1.0 Now you’re a push away to complete your release and ready to keep developing in your new updated development branch. How easy was that? Conclusion Looking into some differences between the original release plugin and jgitflow:You don’t have to worry about stage commits. Everything is local until you push. No more problems with other people changing pom.xml during the process. Your project is only built once, saving release time. Very easy to setup. Everything is picked from your Git configuration.When I was investigating / writing, I’ve found this very interesting post, about an alternative way to perform the release. It’s worth reading: http://axelfontaine.com/blog/final-nail.html by Axel Fontaine.Reference: Maven Git Release from our JCG partner Roberto Cortez at the Roberto Cortez Java Blog blog....
Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close