Showing posts with label Design Discussions. Show all posts
Showing posts with label Design Discussions. Show all posts

Sunday, March 25, 2012

Java architecture with DTOs

The DTO Discussion

The DTO (Data transfer objects) pattern is really useful if you intend to achieve a clean separation between the service layer and the presentation layer of the application. DTOs are part of the service layer API and therefore something that is best to have than not to.

DTOs also serve another purpose: Adapt model values, which in most cases are normalized, to view-friendly values, which most of the time presents particular values from an object graph and also calculated values.

Very often, applying the DTO pattern in a given architecture is not an easy task, you earn an application easy to maintain  by spending a lot of time (shallow) copying data from one object to another.

One solution for the data copy problem can be found by using a framework, in this case jDTO Binder. jDTO Binder makes easy for the programmer to achieve some tasks:


  • Receive form values and copy them to target business objects.
  • Create lists with data from particular properties of an object graph.
  • Add to those lists calculated values.
  • Change the format of the data to be more appropriate for display or network transmission.
I've taken the time to create a sample maven project with a very popular setup: Spring Web MVC, Spring Framework and Hibernate. Although you can use this project as a starting point to build a web application with this technologies, this project incorporates jDTO Binder into its ecosystem and demonstrates how it makes your life a lot easier.

To run the project, just unzip the file, open the terminal and type the following commands:

$ cd <path to the unzipped folder>
$ mvn clean install tomcat:run

Project Description and Walkthrough.


Required Skills: To go through this project, basic Spring Web MVC knowledge is required. Even though the important part is written on the service layer, Spring MVC and Spring Context knowledge helps a lot to put all the pieces together.

The DTOs

The following snippets shows the DTOs this project uses and its purpose:

public class PizzaDTO implements Serializable {
    
    @Source("id")
    private Long pizzaId;
    
    
    @Sources(value={@Source("pizzaName"), 
        @Source("price")}, merger=StringFormatMerger.class, mergerParam="%s ($ %.2f)")
    private String description;
    
    private double price;
    private int rating;
    ...
}


The first DTO to analyze is the PizzaDTO, this one is intended to serve in a listing of available pizzas. It has a description attribute which is intended for display and is created from the pizza name and the pizza price in a formatted string.

public class PizzaOrderForm implements Serializable {
    
    @NotEmpty //validation annotation
    @Source("whoOrderedName")
    private String customerName;
    
    @NotEmpty //validation
    @Source("contactNumber")
    private String customerPhone;
    
    @NotEmpty //validation
    private String customerAddress;
    
    @Size(min=1) //validation
    @DTOTransient
    private List<PizzaDTO> pizzas;
    ...
}

The second DTO is really the model of a form to take a pizza order, it does not only have DTO binding annotations but also standard JSR 303 bean validation annotations so the data can be validated automatically.

public class OrderDTO implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private Long id;
    
    @Source("whoOrderedName")
    private String customerName;
    
    private String customerAddress;
    
    @Source("contactNumber")
    private String customerPhone;
    
    @Source(value="orderDate", merger=DateFormatMerger.class, mergerParam="MM/dd/yyyy hh:mm")
    private String orderDate;
    
    @Source(value="pizzas", merger=SumMerger.class, mergerParam="price")
    private Double orderPrice;
    ...
}

Next on the line is a DTO intended for a list of pizza orders, it contains most of the data the pizza order has but also it calculates the price of each order so you don't have to do it manually or save the amount in an extra field on your database table.

The Service Class

Now we've got to the interesting part, how the service layer takes advantage of these DTOs to make your life easier. The following is the declaration of the PizzaOrderService, I'll show separately the implementation methods so I can give a little more explanation of each without having you to scroll up and down repeatedly :).

@Service
@Transactional
class PizzaOrderServiceImpl implements PizzaOrderService, Serializable {

    private static final long serialVersionUID = 1L;
    @Autowired
    private HibernateTemplate hibernate;
    @Autowired
    private DTOBinder binder;
    @Autowired
    private Validator validator;
    
    ... //implementation goes here
}


This is a normal service class, it is transactional because it interacts with hibernate, it has injected an instance of the very helpful class HibernateTemplate, also has injected an instance of the DTOBinder (which is configured as a spring bean in applicationContext.xml), finally the JSR 303 standard bean validator to perform validations on objects (also declared as a spring bean).

This class is serializable because it may be serialized for example in a web session.

    @Override
    public List<PizzaDTO> listAvailablePizzas() {

        DetachedCriteria criteria = DetachedCriteria.forClass(Pizza.class);
        criteria.addOrder(Order.asc("pizzaName"));

        return binder.bindFromBusinessObjectList(PizzaDTO.class, hibernate.findByCriteria(criteria));
    }

This method queries the database for pizzas, and returns the list as a list of PizzaDTO by taking advantage of the DTO Binder. Please note that if we hadn't used the DTO framework, we would have had to iterate over the list returned by hibernate template and build the DTO instances ourselves by setting and formatting the values; all is taken care by the framework.

    @Override
    public boolean placeOrder(PizzaOrderForm form) {

        //may validate with hibernate validator
        if (!validator.validate(form).isEmpty()) {
            return false;
        }

        PizzaOrder order = binder.extractFromDto(PizzaOrder.class, form);


        order.setOrderDate(new Date());
        order.setPizzas(new ArrayList<Pizza>());

        for (PizzaDTO pizzaDTO : form.getPizzas()) {
            Pizza pizza = hibernate.get(Pizza.class, pizzaDTO.getPizzaId());
            order.getPizzas().add(pizza);
        }

        hibernate.save(order);

        return true;
    }

This method may look familiar to you if you had to build functionality for adding data to a database in the past :). In this case we get a PizzaOrderForm as a parameter, use the validation framework to check the data, extract the form values into a proper business object using de DTO framework, set data that was not inputted, relate the order with the actual pizzas and finally persist the order!

That's a lot for the few lines of code we've written! If we hadn't had use the DTO framework, then we would have had to manually copy each property of the form into the appropriate property of the business object, which can take several more lines.

    @Override
    public List<OrderDTO> listOrders() {
        DetachedCriteria criteria = DetachedCriteria.forClass(PizzaOrder.class);
        criteria.addOrder(Order.desc("orderDate"));

        return binder.bindFromBusinessObjectList(OrderDTO.class, hibernate.findByCriteria(criteria));
    }

The last method is much the same as the first one so no further discussion is needed.

A couple of final words.

As we may have noticed, this architecture is rather simple but full featured. It uses data validation, transactional behavior and the code is kept really small and clean thanks to the DTO Binding framework.

When used the right way, DTOs are a very powerful tool and makes our application even more bullet-proof by isolating completely the database code (persistent objects included) from the presentation tier.

Another thing to note is that, if you need to change from where data is acquired, add or remove fields is just a matter of configuring the DTO object and nothing else! Compare this to the traditional approach in which you would have added the extra field and then going through each loop when you populated the DTO and add the extra data copy operation.

Saturday, March 10, 2012

Web Based VS Native - Mobile Application Development

I think one of the biggest challenges of mobile application development is supporting an acceptable number of devices, which have different screen sizes (and generally speaking hardware abilities), which can be a real problem because developers need to build multiple versions of the application, say one per device they want to support. The question is: is there any way around this?

Well, some would say, "just build the thing web-based", of course, this has some advantages (at first sight at least) you code it in javascript with HTML 5 and it theoretically will run on most of the devices since most of them have webkit-based web engines!  This approach has proven on the past to work really well for desktop environments, so let's listen to the story of an embedded-web app development.

The story of a mobile web development.
Say we start building the app with this approach. For now everything is working fine, we spent 3 or 4 days just coding plain html and javascript with one framework like Sencha touch or jQuery Mobile and it runs fine on the device (say iphone) emulator, then we spent 4 to 6 days coding a data layer using local storage or web SQL and finally a couple more of days testing on a real device. 

Well, let's try it on the Android emulator.... "DANG! those animations were supposed to work!, and also why the layout is so off? And this looks like an iOS app, my android users won't dig that!

After going through the first experience you realize, you need a theme engine!! and switch the theme for each device... also it would be nice to add some code to adapt the components layout for each screen size and done! after 4 more days of writing javascript your app works fine on the iphone and android, now what? My friend has a blackberry!! Well, a couple more days to build the blackberry theme...

And the story could go on and on while testing on tablets of different brands and screen sizes, but finally... why the app is so slow?? it leaves me without enough battery to make phone calls!

Well finally we wrote just one application that works (awful) on every device, and also we as developers had to deal with thinks like there's no javascript debugger on the device emulators.

The story of a native mobile app development.
After going through the mobile experience we decided to give native application development a try, so started eclipse with the Android plugin and created the user interface with the visual designer, after a couple of hours we have the same 10 screens our web app used to have, with android user experience, ok, we found we have frameworks for data storage so after two days of work we have the same app running.

Ok, now let's bring the iPhone version! We create an Xcode project, after a couple of hours we have the iPhone and iPad user interface, then by taking advantage of the data APIs build the business logic and done!, the app is ready to test on the new platform.

Same story goes for blackberry, and other mobile platforms, now we take a look at the apps, they're working fine but oh no!! we have the same codebase all over the place, in different programming languages and development environments! That's not good for sure.

Time for comparison.
After telling the two stories we had a not-so-happy ending for each. So we need to choose now!! What should we do for our mobile apps.

Well It depends of a few things: manly development costs, delivery time constraints and importance of the user experience, so let's take a look of each point for both platforms.

Development Costs.

On the one hand for a web development you need a web developer with basic knowledge of each platform on the native side, this is because even though embedded web applications are mostly wrote on javascript, you need to build and embedded app environment (or use something like PhoneGap which entails the same basic knowledge), also you need the native development environment to build and package the embedded app environment for each platform. 

On the other hand you need an application developer who has medium to advanced skills on building native mobile applications and also the same native development environments. 

Adding features to the application is relatively simple for embedded web applications while adding features to native applications would take to over and over add the same thing for each platform codebase. We can think here that since the user experiences and the capabilities of mobile devices are different, adding a feature would also be an easy thing for native but complex for web.

Another important thing is tooling, web applications have somehow basic tooling while native applications have very powerful tooling and also the ability to debug and profile the code.

So in my opinion, at the end od the day, the cost is greater for embedded web apps than native web apps even considering that the codebase is repeated.

Delivery Timing.

As the year 2012, people has a lot of experience writing web applications, we have a lot of frameworks and tools to write these things, but most of this is by taking advantage of powerful servers and helping the developers on not writing HTML and CSS, because writing HTML and CSS is a slow process! They're not meant for creating user interfaces but for creating documents, so we made a lot of things to manage achieving the look and feel of user interfaces. Even though frameworks like Sencha Touch or jQuery mobile makes creating the user interfaces rather simple, you still have the three to four days time to create a 10 screens app, and then lots of time and hacks to make it look native for each platform.

With the availability of developer tooling, native applications can be built very quickly, the pitfall is having to deal with lots of programming languages, a not-so-skilled developer could find writing code on different programming languages a hard task, but let's face it, data-driven mobile apps actually entails caching data locally and sending it to (or reading from) a server, with some documentation and examples the logic should be done in a couple of days.

So speaking of time, for web apps, you could have say three developers working on the same codebase, but truth is, the more developers are working on the same codebase the more they get into each others way.

If you have three targeted platforms and three developers you can start the development for each platform at the same time and see it code-complete in 4 to 6 days.

So in my opinion, at the end of the day, you can make delivery rather quicker if you pick native development since the tooling is better and you can have people working independently, with proper project management all the platforms will be finished mostly at the same time.

User Experience.

Finally, the user experience, every platform has its own user experience, meaning for touch gestures, ways of navigating through screens and so on, for example android apps have a back button and a home button which removes the need for applications to provide a "software" navigation button, iOS phones doesn't have this button but all the applications have the same set of ways for navigating.

Also widget layout, colors, sizes and icon meanings are different, also you may have to provide localization and so on. This on an embedded web app will take lots of lines of javascript, and the more lines of javascript you write, the more battery you consume which is also a really bad thing for user experience.

Finally, HTML user interfaces need to be parsed, and rendered by a relatively slow processor so the user would notice some degree of unresponsiveness while interacting with the application.

Native apps doesn't have this advantages, they are built for each platform and for that, you just build the user experience the platform has and later you don't need to adapt it for another platform (maybe only phone/tablet adjustments), so they run fast, very responsive and with low battery consumption.

Conclusion

At this point I hope you're more than convinced that creating embedded web apps for different mobile devices has only the advantage of one single codebase, which is also a drawback because on different platforms things are different. Taking the approach of creating unified user experiences will result on confusing the user and making him to learn new things while he only wants to get the task done; this only works for a little set of apps that has really well-known user interface interactions (like facebook).

In my opinion, building native apps is way better than building embedded web apps, specially thinking on the user experience.

It would be really nice to have a serious scientific study for this, but at least for me, I'm a lot more skilled for web development than native development and with all that, it takes me a lot less time to build the same app native than web based.

Tuesday, December 27, 2011

Liferay Portlet Backend: Service Builder Discussion

Is service builder good enough? Are Spring and Hibernate the best option?

When I first started Liferay Portlet development, the first thing I came across with was "Service Builder", my first thought was "this is awful", with the following reasons:

  • It didn't allow me to do TDD but to directly write business code and then generate the interface out of it.
  • It generates a lot of classes, and I'm only allowed to modify a few (just one I think).
  • The resulting code throws a lot of exceptions (the same as the Liferay API) and I'm really not into throwing lots of exceptions.
But as every first step I was able to look at the configuration files it generates and then learn how I could create my own Spring framework context using the same data source as liferay and having a great coding experience with Hibernate and Spring.

Everything seemed fine until I realized that it wasn't the best option, three reasons I can think of right now are:
  • No support for global transactions, this means the transaction my code manages is different than the transaction of the Liferay API calls so no global rollback for me.
  • No support for database sharding, well not precisely but If I wanted it to work transparently, I would have to make my own way through it.
  • No direct relationships of my data model with the Liferay entities, this means no automatic foreign keys for example.
So then I realized that I was trying to kill a fly with a nuclear bomb, this is the fact: You COULD create huge applications with portlets in Liferay but portlets (as any other liferay plugin) are for customizing the web portal and not to build huge applications. 

If we lower down the scale and say a portlet is just a customization:
  • It's so simple we don't need to write many test classes.
  • We may care of having it done quickly and don't care so much if it's THAT pretty.
  • We may want to make things consistent with the existing API.
  • We don't want to miss Liferay features.
Service Builder is great at this, it generates code following many conventions, it generates javadoc and it basically does all the boilerplate for you so you only need to write 10 to 20 lines of business code and that's it.

So as a conclusion I would say that Service Builder is the best option if you're planning to use liferay as a web portal and not as an app container. If you're using it as an app container (which I really don't recommend) and you don't care that much of loosing a couple of liferay features, then you should definitely go with Spring and Hibernate since your life will be a LOT easier and you'll be able to write unit tests and those kinds of thins. 

Sunday, June 26, 2011

Spring AOP Scoped Proxies

In this post I'll be discussing the Spring AOP Scoped Proxies as a way to expand the scope of the beans managed by the spring IoC container. So far we know two types of scopes common to the IoC container: Singleton, just one instance per container, and Prototype, one instance per client (of the bean). The previous two scopes can give us an idea of stateless/stateful beans but in some context there are other contexts that can be useful, for example in a web application we can think on the scope of a request or the scope of a session to make parts of the application that only makes sense on a web context.

It's true that the right thing to do when we're designing our backend is to try and do the whole functionality as independent of the context as possible but sometimes having a bean that depends on the context makes the application logic so simple, elegant and easy to code that we're tempted to make things that way, for example, if we're coding an application logic that depends a lot on the information of the currently logged user it would be really handy to have in our bean something like this:
 @Autowired
private CurrentUser currentUser
And then get the data as we please. But the thing is with the prototype scope or singleton scope it would be very difficult to achieve this, specially when a lot of users ar accessing the app simultaneously. So to this purpose we'll configure the AOP scoped proxies.

First of all, we'll speak about the dependencies we need:
  • Spring AOP, to have the AOP functionality in our application.
  • CGLIB if we're going to have proxies for classes that doesn't implement any interface.
Then, we'll have our standard configuration but apart from that, some special configuration so spring can tell which request matches to which thread and thus access the session and request scopes.

We'll add the following lines in our web.xml file:
   <listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
Finally we configure the bean to be session scoped or request scoped:

 @Service
@Scope(value="session",proxyMode= ScopedProxyMode.TARGET_CLASS)
public class CurrentUser implements Serializable {
//session data here
}

If we're configuring our beans in the XML fashion, then we add the tag:
 <bean ... scope="session"> 
<aop:scoped-proxy/>
</bean>
To our bean definition and that's it. Really easy and really clean because our bean logic doesn't get dirty with Servlet spec classes and if we need to switch this logic to be for instance a desktop application, we can always switch the bean to be singleton and take care of it by ourselves.

Sunday, May 15, 2011

Wicket 1.4 URL Character Encoding Problems

While developing web apps using wicket I've faced a problem with character encoding on URLs, for example, if you are using default settings and deploying your application into Tomcat, you'll be able to reproduce the issue quite simply:
  • Create a page that prints somewhere a parameter read from the url (on standard query string url coding strategy).
  • Call the page directly from the browser using some special char on the parameter value.
  • Check that the special char has been decoded wrongly and you're scratching your head ;) on how to solve this out.
So my first thought was "this for sure is a wicket issue!" but soon learned the problem is much deeper than that. It turns out that most browsers don't tell to the server the encoding in which they're making the request so it's up to the server to guess this.

Modern browsers can send (and they actually do) make the requests in UTF-8 but most of the containers assume (because it's what you can read in the HTTP protocol RFC) that the encoding is by default ISO-8859-1. From the HTTP protocol definition:
The "charset" parameter is used with some media types to define the character set (section 3.4) of the data. When no explicit charset parameter is provided by the sender, media subtypes of the "text" type are defined to have a default charset value of "ISO-8859-1" when received via HTTP.
Ok, now, wicket has a lot of things you can set up on the web application, one of all is the request cycle character encoding, and it defaults to UTF-8, so this leads us to the first solution to our problem.

The first solution: Change the request cycle character encoding.

This can be done in a very simple way, with just a line of code:
 getRequestCycleSettings().setResponseRequestEncoding("ISO-8859-1");
By doing this, you tell wicket to treat requests and responses as they were in ISO-8859-1 and special characters on the URL get url-encoded and everything works just fine. I have though some suspicions that some strings with special characters get broken but I really can't confirm that (because it could be they get broken for some other reason).

Now, I don't know you but I really don't feel comfortable with having my request and response on ISO-8859-1, specially because I like UTF-8. So since the problem is that the container assumes the requests are in ISO-8859-1 why not tell the container to assume the requests will be by default on UTF-8?

The second solution: Let the container assume the requests are in UTF-8.

To make this solution work we'll need to have access to the production server's configuration, and it's quite easy: tomcat's http connector has a property called URIEncoding, we just need to set that up and all set:
 <Connector port="8080" protocol="HTTP/1.1"  
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8" />
This solution is quite pretty and works like a charm as well, and you can stick with your beloved UTF-8 charset.

I have a third solution but isn't pretty.

The third solution: Write your own QueryStringURLCodingStrategy

This solution is what I've fell down when I first met the issue because I thought it was a wicket issue and was exactly that: subclassing QueryStringURLCodingStrategy and write my own implementation of the decode parameters method and decode the parameters yourself!. At the time it worked, but now I can see it just have a lot of side problems so I think you want to stay away from this solution.

Other solutions that didn't work for me.

While trying to solve this problem I also tried other solutions without luck: some tried writing a servlet filter to set the encoding of the request to UTF-8 including the filters provided by the spring framework and apache tomcat. I also wrote my own implementation of a filter to change the encoding with no luck (the problem didn't go away). But also I think it's worth a try.

Friday, April 29, 2011

Drools as a replacement for the 'Composite Strategy' design pattern.

When facing the need to implement complex business rules over the classical object-oriented approach we always fall down to one of the following solutions:

Spaghetti code:
 if (bill.getAmmount() > 100) {
//apply the best calculation for the store
if (customer.getAge() > 65) {
//apply the senior citizen discount
bill.setAmmount(bill.getAmmount() - 10);
if (customer.isPremium()) {
//apply 10% discount
}
} else {
if (customer.isPremium()) {
//apply 10% discount
}
}
}
Can you guess the business rules out of that code? What about adding a new rule?

The Composite Strategy design pattern:
 DiscountStrategy ds = buildStrategy(customer, bill);
ds.applyDiscounts();
In this last case we would need to create five classes and one interface, one per business rule, one for the composite strategy (to decide in which order is best to apply the strategies) and one strategy factory (to decide which strategies apply). Thats a lot of classes!! And also it would be really hard for any person to understand what were the business rules in the first place.

The bottom line is, we have three business rules:
  • Only bills with value higher than $100 can have discounts.
  • Senior citizens have $10 discount on their purchase.
  • Premium customers have 10% discount on their purchase.
For the cases where two discount policies can be applied we have two situations: what is best for the store and what is best for the customer, and all of this highly affects the readability and maintainability of the code, and also the addition of one simple new rule can make things worse!

The drools approach:
Drools helps us defining complex business logic introducing a new way to face problems: Logical programming. We can define all of our business rules in an elegant fashion:
 package com.juancavallotti
global Bill bill;
import function com.juancavallotti.DiscountLogic.applyDiscount;
rule "Discounts are only for bill over 100 dollars"
salience 20
when
$customer : Customer( )
$bill : Bill( ammount <= 100 )
then
System.out.println("Low value bill");
retract($customer);
retract($bill);
end
rule "Senior Citizen Discount"
salience 10
no-loop
when
Customer( age > 65 )
then
System.out.println("Senior Citizen Discount");
bill.setAmmount(bill.getAmmount() - 10);
end
rule "Premium Customer Discount"
salience 0
no-loop
when
Customer( premium == true )
then
System.out.println("Premium Customer Discount");
bill.setAmmount(applyDiscount(bill.getAmmount(), 10));
end
In the file (called discount.drl) we define our business rules in a very simple format. Now if the business requirements change, we only need to add more rules to the file in a declarative way and the rules engine takes care of how those rules will be applied on our objects.

Also we gave priority to our rules with the "salience" rule property, the greater the salience the more priority the rule has.

I've added the "no-loop" rule property so the rules don't get applied more than once.

Finally the discount service would look as simple as this:
 public class DiscountLogic {
private StatefulKnowledgeSession kbSession;
public DiscountLogic(StatefulKnowledgeSession kbSession) {
this.kbSession = kbSession;
}
public Bill applyDiscountPolicy(Customer customer, Bill bill) {
kbSession.insert(customer);
kbSession.setGlobal("bill", bill);
kbSession.insert(bill);
kbSession.fireAllRules();
return bill;
}
public static double applyDiscount(double ammount, double discountPercent) {
return ammount * (1 - discountPercent / 100f);
}
}
In order to inject the StatefulKnowledgeSession instance we need to add some boilerplate code that will bootstrap our knowledge base and compile the rules and so. You may want to download the sample code and play with it.

To learn more about drools, please refer to the drools documentation. (We are currently having fun with the drools-expert module).

Have Fun!