Monday, December 31, 2012

Leaving CEJUG's Leadership Team

Today is my last day in CEJUG's leadership team. A journey that lasted for tireless 8 years or something. I'm not sure about the exact date I became Jug Leader, but I remember very well how it happened. I was attending a CEJUG coordination meeting at Fortes Informática because I was helping them to organize an event. Right after the meeting, Felipe Gaúcho invited me to co-lead the group, which was unexpected but very pleasant. I accepted immediately! Felipe is not among us anymore, but I am eternally grateful to him for this incredible opportunity.

I'm not leaving because I'm tired or bored. I'm leaving because CEJUG needs renovation. It needs to change its philosophy, its soul. I'm the oldest one in the leadership team, thus I'm a dinosaur in terms of community management. My mind still believes in some practices that don't work anymore and the community is not growing as it could grow. Fresh and valuable ideas usually come from new people with a vision to help others to develop their technical capabilities. I'm sure there are a lot of people like that out there and I wish they get my place and move on faster.

There is a CEJUG's rule that promotes ex-leaders to become advisers for the leadership team. It is a sort of recognition for the great services provided to the group. But I'm not accepting even that. To give advices to a future leader is like bringing back the old way of thinking. That's what I'm trying to avoid. Advisers are not so active anyway. I don't remember the last time I received an advice from them. Actually, it ended up becoming a definitive leave for them too. Eventually, my departure will motivate other members of the leadership team to take the same initiative, if they have the same feeling I'm describing in this post, of course.



Sometime ago, a friend of mine was excited about CEJUG's community and he asked me what he has to do to become a JUG Leader. I told him that it's not so difficult, but it requires patience and a lot of work. That's because CEJUG is a meritocracy, where you are recognised according to your contribution to the community. The recognition is basically promoting you to the leadership team, then you have more power and resources to make things happen. It takes some time because we wanna make sure that you won't give up easily and you will just continue working as hard as before.

The problem is that there is no glamour in the role of Jug Leader. New leaders probably realised that it's more a labor of love, donation and dedication than a professional achievement. Some people love that, like I do, but most people don't. Perhaps new leaders won't find motivation for the merit in this meritocracy model. The excitement may last for a few months and then, even the free time will be occupied with other priorities.

I have been proud of my role as a Jug Leader, not because of what I did for the community, now and in the past, but because of what I feel for them and what I was willing to lose for them. I will keep this feeling in my heart. You may ask me why I'm leaving since I'm still in love. This is like a relationship that doesn't work. When your love is not reciprocal the best thing you can do is set your love free.

If you want to be the next CEJUG Leader, be aware of the need for passion, donation and dedication, with or without professional achievement. In addition to that, read a very interesting post on John Yeary's blog about the definition of a Jug Leader.

By the way, I will continue as a humble CEJUG member, trying to help people there with their technical questions. Meanwhile, I'm working on a new open source project! I'm going to launch it here soon and maybe it will end up in a new, large and successful community! ;)

Sunday, December 23, 2012

Easier Multi-Field Validation with JSF 2.0

One of the most frequent needs when developing application forms is multi-field validation (or cross-field, but I'm not using this term because when I put it on Google I actually got some post-war pictures). I'm talking about situations where we need to compare whether an initial date is earlier than an end date or a value is lower than another one. Isn't it an obvious feature in every business-oriented framework? Not really. Unfortunately, the JSF specification doesn't support it by default. Therefore, until its latest production release (JSR 245 - JSF 2.1), JSF did not offer an out-of-the-box multi-field validation feature.

We probably can hope for something coming in JSF 2.2, since the JSR 344 mentions "Multi-field validation". Meanwhile, developers have used their fruitful creativity to implement their solutions. You can find plenty of working alternatives at Stackoverflow.com; people creating their own components; frameworks built on top of Java EE trying to cover this feature; and many other cases.

I didn't like any solution I found. Some are complex, others are not so elegant. So, I decided to be creative as well and try a simpler solution, easy to understand and change when the time for refactoring comes. It doesn't mean that I'm proposing something better than other proposals. I'm just proposing something simpler.

In the following example, I check whether an allocated budget is smaller than a budget limit. If not, then a message is shown to the user. The example considers only two fields, but it can scale to as many fields as you wish.

Step 1: create an attribute in the managed bean for each field to be validated:


The attributes below are exclusively used in the multi-field validation.

private BigDecimal validationAllocatedBudget;
private BigDecimal validationBudgetLimit;


In this example, I'm coding inside a class named MBean, annotated with @ManagedBean and @RequestScoped.

Step 2: create a validation method in the same managed bean for each field


This solution considers validation methods implemented in the managed bean instead of implementations of the interface javax.faces.validator.Validator.  You can give any name to validation methods as long as you define three standard parameters, which are the FacesContext, the UIComponent, and an Object representing the value input in the field. Only the value is useful for our validation. See the validation methods:

public void validateAllocatedBudget(FacesContext context,
                       UIComponent component, Object value) {
   this.validationAllocatedBudget = (BigDecimal) value;
}

public void validateBudgetLimit(FacesContext context,
                        UIComponent component, Object value) {
   this.validationBudgetLimit = (BigDecimal) value;
   if(this.validationBudgetLimit

          .compareTo(this.validationAllocatedBudget) < 0) {
       throw new ValidatorException(

                 new FacesMessage("Invalid allocated budget!");
   }
}


The method validateAllocatedBudget doesn't validate the allocated budget. It simply set the attribute validationAllocatedBudget to allow its value to be used afterwards. It is possible because the validation methods are called in the same sequence they are declared in the JSF code. So, you can create a simple method like that for each field involved in the validation. The effective validation occurs in the method validateBudgetLimit, which is the latest called validation method in the JSF file, thus the last one to execute.

It's a good idea to declare attributes and validation methods in the same order of the fields in the form. The order doesn't interfere the functioning of the algorithm, but it helps to understand the logic. On the other hand, the order of calls in the JSF file is important.

Step 3: use the parameter validator to reference the validation method


The methods described above are called from the fields below. Remember that the attributes and methods were implemented in the class MBean.

<h:outputLabel for="allocBudget" value="Allocated Budget"/>
<h:inputText id="allocBudget" label="
Allocated Budget"
    value="#{mBean.operation.allocatedBudget}"
    validator="#{mBean.validateAllocatedBudget}"/>

<h:outputLabel for="budgetLimit" value="Budget Limit"/>
<h:inputText id="budgetLimit" label="Budget Limit"

    value="#{mBean.operation.budgetLimit}"
    validator="#{mBean.validateBudgetLimit}"/>

That's it! :) Merry Christmas and Happy New Year! \o/

Tuesday, December 18, 2012

Case Study: Migrating a Large Project from Ant to Maven

The truth is we had been under difficult times. We spent almost three months to migrate our build mechanism from Ant to Maven. That's the minimum time you have to put in your schedule if you are planning to do the same in a large project. There are still some collateral effects of this migration that we are struggling to solve, but fortunately they are not so critical.

The Context


Just to contextualize a little, we have a full Java EE 6 system composed of 25 integrated applications and each application has an average of 3 modules (EJB, WEB, etc), reaching ~80 modules. We manage something close to 500K lines of Java code (JSs, CSSs, JSPs and JSFs files not included), according to our Sonar analysis. It takes between 15 to 20 minutes to build everything. It depends on the mood of the server.

The decision to go for Maven came as a precondition to start a large scale refactoring of the application, which, despite using the latest technology available (Java EE 6), has suffered from a mix of frameworks, design flaws and multiple architectures over the years. We are going towards a single architecture grounded on the Java EE specification in order to optimize dependencies, reduce the evolution cost in a middle/long-term perspective and run seamless in our Glassfish Application Server.

The Duty


The project structure is almost the same as it was with Ant, thanks to the flexibility provided by Maven. We have a super pom.xml file in the root folder, which basically declares all modules, plugins, additional repositories, and dependencies. The dependencies are declared in a dependency management (using the tag <dependencyManagement>). This way, all version numbers are declared in a single place. Besides the super pom.xml, we have a folder for each integrated application and inside each folder we have a application pom.xml and three other folders, one for each Java EE module (EAR, EJB, WEB). The application's pom.xml inherits from the super pom and it basically declares the modules composing the application. Inside the module folders we have one more level of pom files. These pom files inherit from their respective application's pom files and describe the particularities of their modules. In summary, we have three levels of pom files, from the system as a whole to the level of Java EE modules.

Example of structure similar to the one we are using.

For development purposes, we avoid deploying the entire application locally. That's why we have an EAR module in each application. This way, we save time deploying only the application we are working on. Those application EAR modules are not taken into consideration when packaging to deploy on the servers. To build the full EAR for the servers we have a special application that contains a EAR module, whose pom file declares all EJB and WEB modules as dependencies. Performing the goal package on this pom.xml will actually create the super EAR file.

EAR module to package the entire system in a single deployment file.

The Good


Evaluating the project after Maven implementation, we could notice the following benefits:

Maven contributed to simplify the logic behind the build: Now, everybody is aware of what is going on because pom.xml files are much easier to understand than build.xml files. Our Ant files were generated by Netbeans, thus very big and unreadable. We were actually lucky to have them working for so long, since it was difficult to maintain them. No question that we would find a point of irremediable chaos very soon.

Maven also contributed to put some order in all project dependencies: We went from a ~100 MB EAR package to a ~50MB one, a very significant reduction of 50%. It contributed to make the deployment time shorter.

We had the opportunity to clean up the project: While gathering the dependencies to write the pom.xml files, we discovered that some modules were not needed any more; libraries spread through the modules were also removed in favour of Maven's dependency management. In summary, we have said "Maven is a nightmare" until the day we finally had everything in order and we became happier and relaxed. That's what most people say as well, since it's not easy to find solutions for a particular scenario, and everybody has a particular scenario to deal with.

Short learning curve: Once Maven was put in place, we visited all developers, reconfigured Netbeans to recognize the Maven projects and explained to them how to proceed from that point on. All of them could immediately continue with their development activities and just a few call for support were triggered. None of these calls were blocking issues. I have to say that Netbeans contributed a lot to reduce the learning curve because all necessary goals are performed directly from the IDE and there is no need to go to the command line, as it usually happens with Eclipse.

The Bad


Unfortunately, we had some setbacks:

The build now takes longer with Maven: We have noticed a decline on developers' productivity due to that, making us a bit frustrated at the end :-( Since we are not going to rollback to Ant, we are considering JRebel for dynamic reloading of changed code to compensate the additional time we are spending.

We are using some libraries that can't be found in Maven's central repositories or elsewhere: Some are commercial libraries and others are too old. We also found libraries available with inconsistencies, throwing many exceptions at runtime (i.e. Apache FOP). For each one of these situations we had to find workaround solutions that were not so elegant, but we cannot stay like that for so long. We have to install a local Nexus repository to address special cases. This is in our check-list.

Occurrence of unexpected behaviours: the best of the efforts is not enough to avoid unexpected behaviours in the application. We have built a spreadsheet listing all applications and their respective modules; documented all dependencies from libraries and between modules; depicted the project structure; went deeper into details. In order to elaborate this spreadsheet we spent several days investigating the guts of the system, absorbing low level mechanisms and design decisions. All the collected information was used on the migration. Nevertheless, the rearrangement of dependencies and the removal of duplicates and unused libraries caused broken navigation flows, alert messages coming from nowhere, changes on URL paths and many other surprises. Unfortunately, we couldn't predict those problems and we spent much more time on fixes than what was initially foreseen.

The Conclusion


I would like to conclude giving some advices for those planning to adopt Maven in a middle/large scale project:

Communicate the migration to end-users: it's very important to communicate to end-users what is going to happen in the coming days. Users should be aware that, as they have the duty to improve their business, we also have the duty to improve ours. It means the delivery of new features will temporarily slow down to pave the way to a better product with faster releases. If they are not aware of what is going on, they will have very low tolerance to problems, undermining the reputation of the project.

Don't be afraid to change even what is working well: We have questioned ourselves why to migrate to Maven if Ant is working so well. Actually, our strategy is to reduce complexity to streamline the resolution of problems. So, we were not afraid to migrate because preventive measures are very important too.

Keep the entire migration under version control to help the investigation of problems: Once all pom files were created and versioned, every little changes in those files should be committed separately in order to revert changes in case of unexpected problems. It helps to isolate the causes. It is also good to know that there is no conflict between Ant and Maven files. So, both can stay in the same branch during the migration without any impact on developers.

Don't start a big refactoring without a build system like Maven: a successful refactoring depends on a detailed understanding of the application and adopting Maven will push you to perform an extensive investigation. In addition to that, the project will be cleaner and better organized.

There are other alternatives to Maven, such as Apache Ivy and Gradle, but, despite all deserved criticism, we still recommend Maven when replacing Ant because of its maturity; vast plug-in portfolio; abundant documentation on the web; and rich IDE support. However, it's a good idea to evaluate other alternatives once Maven is put in place. After the initial tsunami, other waves will come quietly.