Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Monday, November 7, 2011

Does Maven honor principles it is based on in its own architecture ?

  I like Maven a lot, makes Java programming more fun and spares a lot of time. I also understand principles of preserving backward compatibility, but it is supposed to be a comprehension tool and despite of that it still uses Plexus or Javadoc tags that are quite hard to comprehend and imho should be deprecated in version 2 and disappear in version 3. Unfortunately I don't see almost any sings of that.

People know and like Guice, not Plexus that is deprecated anyway... What about promised Plexus substitution with Google Guice in Maven?
   First off, I got quite angry because I couldn't find any leads that would reveal this mysterious Dependency Injection Framework swap. After the hype almost a year ago that maven is going to migrate to Google Guice from Plexus I grep through the maven trunk source base and it is full of org.codehaus.plexus references and the only place where Guice is used is maven/app-engine

Then I hit MNG-4749 and I realized that the compatibility shim is a work of sonatype dev and I found these two posts : From Plexus to Guice (#2) and From Plexus to Guice (#3) that were quite hidden to me and that revealed Sisu project. Basically, they created a bean injection layer on top of the raw custom injection API provided by Guice. These images tell a little more. The left one expresses how the consequences of preserving backward compatibility or avoiding radical refactoring might look like :-)


You can find the source code in sonatype sisu repository. Btw seeing software moving to git is always nice. Do you remember all those sayings how Maven is lightweight a couple years back :-) ? Although I appreciate the effort of sonatype dev. It must have been a tough work and I certainly try it out and change this article accordingly.

Another point of interest is migration to Java Annotations. As Maven comes from JDK1.4 era, it uses Javadoc tags. They are not represented at the byte code level. It seems to be quite a drawback for Plugin and Mojo API. And tough to understand - missing Annotation's convention. Developers know Annotations, but most of them have never worked with Javadoc tags extensively. In case you need to inherit a Mojo class of different artifact and the maven property doesn't get initialized, what then ? F*** around on Jira and study how QDox and all that work :-) ? Or duplicating all code you would inherited otherwise ? Extending Mojos is so hard now.
    There are some rumors it is going to be changed to Annotations, and one can see some activity around it : Java 5 Annotations for plugins and MPLUGIN-189, but I'm afraid that it might end up with some sort of compatibility layer as in case of the sisu project.
It is so hard
It is a comprehension tool for a user, but these things make it tough to work with for plugin developers. It is sad, but it is true.

I believe that much more developers would create Maven Mojo or plugin instead of a Shell script even for simple things, if these 2 critical issues were solved.

Sunday, November 6, 2011

Booting up Ant project when testing with Maven and surefire plugin


Have you ever had a huge non-maven project that you needed to boot up in order to use it when testing your maven project ? The first time I had to deal with that, I wrote an Ant script that has installed all those hundreds of jars as dummy dependencies with no metadata to maven repository. It was called every time the software finished building.
   The second time I needed to do something similar, I was already aware of the fact that installing dummy artifacts with no metadata has no sense. Just because you need them on classpath, it doesn't mean you have to do it the maven way at all costs.

So I decided to use Maven Surefire Plugin for that. It is a really complex and configurable plugin. But it can drive people crazy because MS Windows has become so popular in past 2 decades. The fact that it has problems with long classpaths made surefire plugin use Manifest-Only JAR :
A jar that declares"Class-Path" attribute  in its manifest where the true classpath is specified 
or an Isolated classloader :
Launching an app by booter that uses new classloader that is passed the classpath
This is cool I get it, plain simple, but take a look at the maven surefire plugin documentation :
Surefire provides a mechanism for using multiple strategies. The main parameter that determines this is called useSystemClassLoader. If useSystemClassLoader is true, then we use a manifest-only JAR; otherwise, we use an isolated classloader. If you want to use a basic plain old Java classpath, you can set useManifestOnlyJar=false which only has an effect when useSystemClassLoader=true.
olol !!! What the heck is that ? Moreover they suddenly mention that it somehow changed and in the end it is the other way around or what. I have to debug that plugin to actually see what is this about. I mean, how many time one sets up surefire plugin a year ? Many times... And every time a programmer hits this crap, unless he spends hours by investigating deeper, he has to spend time thinking about it and dealing with classpath and threading issues.

To make the story short, if you need to do something like this :

   
  <additionalClasspathElements>
     <additionalClasspathElement>
        /path/to/libs/*.jar
     </additionalClasspathElement>
     <additionalClasspathElement>
        /path/to/libs2/*.jar
     </additionalClasspathElement>
     <additionalClasspathElement>
        /path/to/libs3/*.jar
     </additionalClasspathElement>
  </additionalClasspathElements>

and you use a sane operating system and surefire version 2.10, then you need to set these properties to false :

  <useManifestOnlyJar>false</useManifestOnlyJar>
  <useSystemClassLoader>false</useSystemClassLoader>

The explanation is hidden in ForkConfiguration.java :

 if ( useManifestOnlyJar )
  {
      File jarFile;
      try
      {
          jarFile = createJar( classPath );
      }
      catch ( IOException e )
      {
       throw new SurefireBooterForkException( "Error creating archive file", e );
      }
       cli.createArg().setValue( "-jar" );
       cli.createArg().setValue( jarFile.getAbsolutePath() );
  }
  else
  {
      cli.addEnvironment( "CLASSPATH", StringUtils.join( classPath.iterator(), File.pathSeparator ) );
      final String forkedBooter = ForkedBooter.class.getName();
      cli.createArg().setValue( shadefire ? new Relocator().relocate( forkedBooter ) : forkedBooter );
  }
  cli.setWorkingDirectory( workingDirectory.getAbsolutePath() );
  return cli;
 }

 public File createJar( List classPath ) throws IOException
  {
     ..................
     String cp = "";
     for ( Iterator it = classPath.iterator(); it.hasNext(); )
     {
         String el = (String) it.next();
         // NOTE: if File points to a directory, this entry MUST end in '/'.
         cp += UrlUtils.getURL( new File( el ) ).toExternalForm() + " ";
     }
     man.getMainAttributes().putValue( "Manifest-Version", "1.0" );
     man.getMainAttributes().putValue( "Class-Path", cp.trim() );
     man.getMainAttributes().putValue( "Main-Class", ForkedBooter.class.getName() );
     man.write( jos );
     jos.close();

     return file;
 }

This explains that you cannot useManifestOnlyJar if you need to append stuff with wildcards to your overall classpath, see how Class-Path attribute is made in createJar method.

However, if useSystemClassLoader is false, then the context classloader that you get from currentThread is the Isolated classloader that contains only surefire and plexus booting related classes.

   
    Thread currentThread = Thread.currentThread();
    ClassLoader contextClassLoader = currentThread.getContextClassLoader();

On the other hand, if useSystemClassLoader is true, then test(s) is not run at all :

   
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running cz.instance.liferay.test.SampleTest
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.218 sec

Results :

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0


   Which is in fact some sort of hard to kill TestNG issue. If you use Junit instead, guess what classloader you get from currentThread.getContextClassLoader(); Yeah, you get the isolated classloader that contains just the booting classes...

    I came to conclusion, that thanks to Surefire-plugin's toleration to shitty OS like MS Windows, they practically discouraged most people from using this extensively, because you hardly can boot up an app like Liferay via its Isolated classloader. Liferay extensive classloading will simply doesn't work with it. In fact it is even using  ClassLoader.getSystemClassLoader();  Plus consider classloading issues with loggers...

   Unless you're the kinda guy that wants to spend hours playing with it, you better go with a shell script that installs the dummy artifacts and produces a pom artifact that serves only as dependencies aggregator, that you just include as dependency to your project.

Monday, October 24, 2011

Died learning Scala

Update - One year and a half later : I love Scala, therefore I declare this blog post deprecated. I just gave it a week more and I totally fell in love with it. And no, java 8 cannot weaken scala :-)

     I spent an entire weekend trying to break through Scala. The amplitude of interest was increasing at first but suddenly rapidly decreased until I lost patience for good. I barely finished 10 projectEuler's problems except for reading up documentation. The more experience I had the more unhappy I was about the complexity of the language and mainly the abstraction layer. Considering the fact that Java 8 is "almost" here and it comes with closures, I said to myself that it was going to make Scala's existence and popularity much weaker. And this reason was strong enough for me to give up on Scala. It was like redemption for me. Scala is so different from imperative languages like Java that for a Java developer it is more effort to learn it on the production level than there is to gain and a non-Java developer would have to learn Java no matter what if he is going to become a professional Scala programmer. At least I think he would probably have to because of the nature of the environment.

    Now, I'm aware of the fact that learning a new language (at least to be able of doing the basic things and truly understand its paradigms) is huge benefit for improving logic and getting oneself out of the box a little, but learning Scala to become proficient would make such a madness in my head and it would take so long to get used to it, that I find my life too short for that. It seems to me that Java and imperative algorithms consequently are readable and edible by other language programmers, but Scala algorithms give everybody feeling that they might know what it is about, but only Scala developer knows what it is doing (because he knows the abstraction layer underneath).
    Sometimes I was under the impression that Scala is so popular because programmers needed to prove themselves as smart asses. Except for those that were really learning Scala for some heavy multi concurrency data or message processing. Things like :  weird compiler and classloading quirks (that some Scala *.class is broken for instance), still quite inadequate eclipse ide to the language and constant impression that Scala is not an improvement on complexity would discourage me sooner or later anyway. So far I think of Scala that it is improvement on scalability only. After all it is Scalable language, huh ?

   Java developers tend to have problems to master even all types of java.util data structures and java.lang primitive wrappers properly and Scala puts heavy abstraction on top of it. Cool, why not ? 
      To make it easier, right? To get rid of primitives in fully OO style, also autoboxing disappears from your sight, no BigInteger.ZERO anymore. To accommodate the functional style, because it kinda implicitly requires a lot of methods and overloaded operators.
     Consider Stream interface for instance. Stream helps to realize laziness, one of the fundamental concepts of Functional Programming. Stream is "infinite", it's like a collection that goes on and on and it is evaluated on an as-needed basis and only up to the point that you need it. There are more than 200 methods together and you often cannot even find a method because it actually sits somewhere in a companion object ( compiler resolves the lack of method by implicit conversion to that companion object because it actually has it) and after you find it you realize that it returns something you wouldn't expect. Which is correct at the end,  because it is passed the "by-name" parameter that is actually not invoked until it is used and it doesn't directly return that type.
     For every Object declaration in the code an anonymous class is created which inherits from whatever classes it extends. If a class shares the same name with the Object, the Object become a companion object of that class. The object cannot have more than one instance ( which is what Classes are for ), in fact it is practically a substitution for static fields and methods in Java. That is to say, if you define an Object in Scala, it would be like defining a Java Class with static methods and fields only. However Object can extend another Class, implement interfaces, and be passed around as an instance of a class. If you gave this to Macgyver he would end up dead, reading up on inverse associative order :-)

     I don't want to discourage anybody from giving it a shot. I gave it just 2 days and I'm sure now that this is not my cup of coffee. Not the functional style, I like that one in Scala and I also like closures in Groovy and ease of Javascript callbacks in NodeJS. Of course in Scala it is much more fancy, that one cannot even compare that to closures in Groovy.
     In fact, there are many sweet things, who wouldn't like Scala's comprehensions, Generators, Guards, all those filters, placeholder syntax or a little controversial inverse associative order (if you type '1 :: 2 :: 3', you get a List(1, 2, 3) back - if the method name ends with colon, the method is invoked on the right operand.
     But for what price? I rather won't be able to use it than getting familiarized with what I wrote in the previous paragraph. And I certainly won't learn Scala because of it's Actor concurrency  framework which others sometimes do.

   Maybe I gave up too early, maybe I didn't have the correct motivation for learning Scala. I might not be smart enough. Who knows, I will stick with Java only. I started to have doubts, but now I'm sure of that.

Monday, October 17, 2011

Google Translator Toolkit Client

    Half a year ago I implemented this Java Client that covers most of what Google Translator Toolkit  API has to offer. One implementation that depends on the old gdata-java-client is already available by Google. This one is using the new java client library (com.google.api-client 1.5-beta) after I switched from 1.3 or 1.4 version.
    Translator Toolkit API is restricted but you may ask for the access. I really don't know if it is going to be shut down or monetized, I hope not, because I decided to use that and I implemented this client library before it became restricted.
    Now I can finally use it in production because until now there were really annoying server side bugs that made API return different results than those you could see right in GTT. Also I wasn't aware of the category with label "completed" that signalizes that the document was marked as "completed". Somebody told me that "gtt:percentComplete" element is good for that, but it is really not ! You cannot determine if it is complete or not based on this information at all.

    Beware that this client is a prototype, so you shouldn't really rely on it right now. I'm going to test it more in a few weeks. I've already wrote a few tests but I don't run them because they directly call GTT API and I don't really want to make Google API busy with testing data.
    If you are going to clone that repository, please run it "mvn install -DskipTests"  to avoid running the tests. You would need to install this document-provider anyway.

Need documents of various media types and language ?

    I wrote this java document provider library for Google Translator Toolkit Client. It is quite handy when developing an application that works with documents, that either vary in media type or language. TDD is the best approach for writing these kinds of apps and this library allows you to set up your test suits with documents very easily.
   It downloads text data and makes combination of following document types and languages :

html - "html"
pdf - "pdf"
odt - "vnd.oasis.opendocument.text"
docx - "vnd.openxmlformats-officedocument.wordprocessingml.document"
doc - "msword"
xlsx - "vnd.openxmlformats-officedocument.spreadsheetml.sheet"
xls - "vnd.ms-excel"
ppt - "vnd.ms-powerpoint"

(bg, es, cs, da, de, et, el, en, fr, it, lv, lt, hu, mt, nl, pl, pt, ro, sk, sl, fi, sv)

You just need to call one of DocumentProvider's API methods :

DocumentProvider.getDocByTypeAndLang(type, lang);

to get object(s) representing a document :

long id;
long size;
long checksum;
String type;
String sample;
File sampleFile;
String url;
String state;
File file;
MediaType mediaType;
int wordCount;
String content;
List<String> words;
List<String> sampleWords;
int sampleWordCount;

Tuesday, October 11, 2011

Is Java concurrency for human beings ?

  Do you also have the bad feeling or uncertainty whenever you use volatile field modifier? The fact that compiler or processor can reorder statements or keep values in registers and that Java Memory Model and compiler is designed to allow aggressive optimizations is bad for our intuition about sufficiency of code synchronization.
  For instance, if you are iterating something on a boolean field ( while(! stop) ) until another thread changes it, the compiler doesn't know or see that and unless the boolean field is volatile, it might make an optimization on the assumption that the value of boolean is never going to change, so it eventually transforms it into an infinite loop. If it is a volatile field the compiler knows that it is not allowed to do such an operation.

What is important to be aware of !!!

  Knowing that processes use separate address spaces and all threads share one is irrelevant here. In Java Memory Model, memory that can be shared between threads is called shared memory or heap memory. All instance fields, static fields and array elements are stored in heap memory. Local variables are never shared between threads and are unaffected by the memory model.
  The most important thing is visibility of JVM inter-thread actions. Inter-thread action is an action performed by one thread that can be detected or influenced by another one (read & write volatile/non-volatile; locking & unlocking a monitor, actions when thread starts/terminates and some external actions).

  Visibility and so called happens before relationship differ for synchronization / locking and using volatile field modifier.

Blocking synchronization using Locks or synchronized methods / statements :
  1. thread A acquires a lock on an object and do some writes
  2. the Lock release pushes out the updates that thread 1 made to shared memory 
  3. thread B performs subsequent Lock acquire that grabs the updates that were performed by thread A by updating the cached values of fields from shared memory. 
  4. thread B performs read or write on updated values
   A synchronized method by default synchronizes on the instance it is being called on or the class object in case of a static method. The key synchronization concept for JVM concurrency is the monitor. Every object in a JVM has a monitor associated with it.
When you are using non blocking synchronization - using volatile field modifier, you practically perform so called happens-before relationship manually. 
  1. threads A, B, C change some field(s) (write) in the flow of their execution and perform a write to a volatile field
  2. each other thread that performs a read on that volatile field will see values of those changed fields updated in shared memory up until any of threads A, B, C wrote to it  
  Two accesses (reads of or writes to) the same variable are conflicting if at least one of them is a write. That is to say, if there are two accesses to a memory location and at least one of those is a write and the memory location isn't volatile, then the accesses must be ordered by happens-before relationship by some other means.    One of the means is using quite nifty java.util.concurrent.atomic package which provides a set of useful APIs that helps to make your software thread safe.    All memory accesses in Java are atomic by default, with the exception of long and double. All other data types are 32 bit. So we don’t have any issue as it will be single write. But for long & double it would be two writes. This can result in a situation where a thread sees the first 32 bits of a 64 bit value from one write and the second 32 bits from another write. Writes and reads of volatile long and double values are always atomic. So, if a thread A begins to set the field and a thread B attempts to get its value, then there is no guarantee it finishes before the read occurs. No atomicity guaranteed.

JSR-133 is the overall thread and Java Memory Model specification. JSR-166 relates to the utilities in java.util.concurrent package.

  I think that Java concurrency is for human beings. And after all I like it. There is other stuff that is quite inedible in comparison with Java concurrency, like practically useless java.lang.reflect.Type that looks it might come handy but finally you have to code all by yourself to get what you need from it :-)

Sunday, October 9, 2011

Not Invented Here Syndrome, why reinvent the wheel?


From my point of view Not Invented Here Syndrome is both a great anti-pattern and a way to be very productive in short term.

When developing application without using third party software (libraries, platforms or APIs) there is nothing to stop you from delivering the SW. Except for your own inability to design and implement it. I'm not talking about the fact that developers don't have significant experience with the 3rd party SW and they spent time, money and effort learning and getting used to it. At least learning and investigating new SW is not a waste of time but it's always a new experience. Also there are pieces of software like Spring (Spring helps with everything and is very mature and stable) or some MVC and UI technologies (you will hardly work with servlet api directly when building web application) that might be considered an exception.

I'm talking about software, that you could either substitute (implement from scratch) easily or software that contains a few features and abilities that you need and the rest of it you'll probably never use. If you find yourself standing before this question and you decide to use this software, there are two resolutions depending on the quality of its opensource community, because you would most probably need to make modifications to it, deliver a good patch and make others to apply it.

  1.    Either you hit road block. You come across serious bugs, idiosyncrasies and bending SW is not possible because nobody listens or it is a remote API that you don't have sources available to. Or suddenly after further experience it is not what you expected. What now? Weeks of work have been done, you can't make such a huge step back, refactoring would be awful. You get stuck.
  2.    The opensource community is good, software is perspective with good architecture and devoted developers and project leads, that responds to what you have to say. To define a good community is hard, because in huge, active community with thousands of users and developers nobody will listen to you soon unless you make a significant effort. In small but active community of mostly developers you get immediate response and you deal with everything very quickly. 

Not using open source SW and reinventing the wheel is the anti-pattern. Because instead of improving and testing an existing universal and generic software, you make a new custom piece of software that suits your needs.
   On the other hand you can't hit the road blocks, you don't need anything from anybody and you won't have to wait entire days or weeks for response.
   Big companies like Google, IBM, Red Hat etc. usually have Not Invented Here Syndrome. I guess they have to from various reasons.The wheel is being reinvented on daily basis. I'm very grateful that there are hundreds of specifications and standards for Java development that reduce the consequences of this.

To exemplify these facts on two pieces of software :

Google APIs are great, you can think of hundreds of use cases of their utilization. Fancy AtomPub based GData protocol, tons of client libraries, what not. But after all they are very buggy, at least from my perspective. Right now I'm using Google Translator Toolkit API that has such a tremendous bug that you can hardly believe. The funny thing is that GTT is in "Labs" stage and the API is restricted and might be shut down in December 2011. Anyway the bug consists in that fact that API results do not correspond to what you see in Google Translator Toolkit. There are 2 documents listed, API resolves one or none. You delete a document, GTT still lists it whereas API does not. It's like nobody is testing or using it what so ever, because they would have seen that. Now what? I merely get any response from Google and their engineers as to concrete API issue reports. Road block.

Liferay might be another example. Liferay is a sophisticated and mature piece of software. But think good what you expect and need from it ! Do you want to use it because some of its plugins? You need groups, roles and you'd have to implement permissioning system on resources, but Liferay already has that implemented, so why would you? You go for Liferay and you get incredible platform but tons of road blocks as well. So you better be sure that you really need a full-fledged Portal or professional Web Content Management system.

Wednesday, June 1, 2011

Liferay - Train of thoughts

It is ca 2 years ago when I was playing with sample portlets wondering what is the difference between Ext and Hook. I wanted to make a summary of the most important facts that it is good to be aware of.

Newcomers usually expect that they will be able to deliver an Intranet solution or at least a nice website with a few handy plugins very shortly. But suddenly they realize that even though Liferay has so much to offer, they really need at least a few weeks of LR experience to be able to customize or even use them. Just setting everything up and configure plugins and portal requires decent knowledge of Liferay.

You can easily add Wiki, Message Board or Blog into your site and set up roles and permissions for its users. Add some web content, social portlet, calendar or even Document Library (there are more of them). What I just named is great, I appreciate it a lot, but the problem is, that these portlets itself don't constitute a production ready solution most of the time. Make a list of those plugins and imagine what market product you would be able to put together using them.

  • Full-fledged website for 
    •  a common interest that connects some social group together
    •  a product that needs a proper representation and that has its user / social group  
    •  a corporate extranet and basic intranet with Document Library that is capable of document workflow and connection to other repositories or accessible from your desktop
    •  etc.
Beware, that there is not much you can do if you just going to create some web content and install Liferay's plugins. And even if you become a good administrator and you make a good looking social website via Control Panel and other configurations, you will most probably see many requirements that need to be done and many unused plugins, because there wasn't reasonable usage for them or it would be redundant. At that time you need a Liferay developer and UI designer.

As Liferay has many features and plugins, rather than framework it is a collection of applications, running on a robust software infrastructure (permissioning, roles, grouping, portlets lifecycle management, unified UI framework, event system, scheduling, very solid abstraction over data persistence, etc.). The features are there, they work, but they are made for universal use and as a developer you can either use them, improve them or use them as a model to create your own, which is mostly not an option. The architecture is very maintainable and you are mostly able to use services that the plugins are built on, to do what you need. There is a difference between portlets, for instance Message Board is most probably not going to be modified whereas Document Library is something that might be accessed more programmatically than via GUI, because if you are building an intranet for instance, custom document workflow and processing could be necessary and you're gonna have to make a good plan how to integrate with Document Library and benefit from the advantages that results from using. And this is something why you need to know Liferay a little longer. An important skill of a developer is the ability to learn from past mistakes and the ability to perceive what makes sense or not.

In Liferay you just has to accept the fact, that they try to satisfy existing customers, have as many features, that they can present to business world, as possible and that Liferay supports wide technology stack and vendors. This is kinda good for business and community growth, but it is not so beneficial for the software itself. It leads to defensive programming and not so much of refactoring or radical changes. There are quite a lot of programmers working on new features, producing bugs and skilled developers that are able to do radical infrastructure changes often end up fixing them and wasting a lot of precious time.
      Document library is a good example of this (notice that I don't criticize that, I mentioned before that it has valid reasons). DL came through a lot of changes recently, a lot of new features actually (CMIS, Document types and their processing, metadata, workflows, etc.). It's design is quite alright, but it doesn't adhere to any specification because LR needs it to be scalable (filesystem sore, JCR store, Amazon S3) and it utilizes the same permissioning system for it that is used for every other resource in the portal. Documents are also part of Asset management and it has it's own way of indexing and versioning. That's why it is built on repository data model (repository, file, folder, metadata, type, version, etc.). All this is quite complex and it is very hard to use a variety of interfaces where you all the time have to think of "and what if this..., wtf if that..." and you have to dive down into the implementation to answer many questions and you are infinitely not sure of consequences of what you're doing, then you finally become Document Library proficient to be able to work with it. This doesn't happen so much with software based on specification, like JCR spec. Wouldn't it be better if instead of all those new features a major refactoring was performed and all those necessary attributes of common document store were handled by JCR repository like Modeshape ? (ACLs - authentication/authorization, scalability (Modeshape datasources/connectors), versioning, indexing, CMIS ... I know that it is almost impossible at this stage, because files in Document Library are common resources and assets as well as blog post, wiki entry etc. It's part of the asset management that other portlets work with. Similarly the indexing and searching through the entire portal. On the other hand, standardization and specification is here because it doesn't change and once a developer learns it, nobody can take it from him and when a newcomer comes to a software based on specification, he knows how it works instantly.

Developing Liferay portlets is very straightforward, but only after you learn from all what you have done wrong in past. Quick example : I was so out of luck that I built one of my most important portlets on Liferay Service Builder (code and spring infrastructure generator - service/dao/domain layer). Everything looks fantastic except for one thing. Unit testing. You can easily load up portal spring context to use its services when testing, but you cannot load up your portlet Service Builder context (which depends on the portal one), because the bean IDs are the same in portlet context as of those in portal context. You just have to do heavy infrastructure coding to put such a basic thing like unit testing of a portlet together ... Actually I had 3 different variations of loading up SB portlet context together with Portal context ...

Anyway, I got really tired, gotta pack for a Nederland boat trip :-) I don't have enough energy to read it after myself so please excuse mistakes, my English or the exaggerated idea about Document Library refactoring :-)


Monday, May 30, 2011

Broadleaf Commerce Vs. Apache Ofbiz


At first, around 2-3 years ago, I gave up on using Apache Ofbiz, because it seemed that I wouldn't be able to be "productive" with it for weeks, because of its complexity. But I noticed of Broadleaf Commerce a few months ago and I find it very interesting. The technology stack suits me a lot ( spring, spring-mvc frontend, GWT backend, hibernate on jpa spec, maven, etc.), if it utilized git and github.com for SCM, I wouldn't have anything to criticize. On the other hand they got rid of flex from backend which makes me happy :-) The principle of building customized shopping cart on this platform is very straightforward, but it expects a developer with some experience too.

First off, I'd like to mention that e-commerce out-of-the-box solutions (this applies especially for non-US businesses) are simply not able to fulfill specific needs. If you look around, you see tons of PHP shopping carts (install & go) that allows you to run a cart, but you have to live with all the disadvantages that result from the "universality" of the solution. Payment, taxes, accountancy and shipment is locale specific. They have mostly terrible architecture, missing modularity, horrible UX and tons of other idiosyncrasies...  Prestashop is not that bad from what I've seen and been told.

Then there are Java e-commerce solutions like partially opensource Konakart or opensource shopizer and jadasite. Jadasite looks quite alright, but it is out-of-the-box, it doesn't even have a shell or ant script, no maven...imagine you would need to change payment or shipment module... no way. I just refuse to work with applications that depend on eclipse WTP anyway...

And finally, there are solutions like Apache Ofbiz and Broadleaf Commerce. They are not out-of-the-box solutions (well broadleaf coffee shop demo is almost production ready for US), but rather platforms. A  developer utilizes them to put a custom solution together, not develop/program/code but rather "put it together", which means : infrastructure setup, beans/services/entities adding, overriding, merging, extending or changing an existing module to adjust it to a concrete region, etc. Complexity of Apache Ofbiz makes you waste a lot of time, in my opinion. Unless you are being paid for that familiarization, it's a big problem. As to Broadleaf commerce, I find it much easier. The documentation could be more actual / current though. But I think that for a developer who is new to these two platforms, choosing Apache Ofbiz means much more investigating and learning the internal working than the actual results and it is very demotivating. But in regards to Broadleaf Commerce, I kinda see everything after 2 hours of reading through the codebase.

I tried to investigate Ofbiz and I came to conclusion, that for my needs (shopping cart) it is not worth it. Its entity and service engines, workflows etc. and the way you're setting up the platform seemed very J2EE non-standard and I felt lost! Then I realized that it is probably inevitable, because how else should e-commerce platform of this caliber look like? It just can't be done as it is in Broadleaf commerce. You simply have to spend  weeks learning how to become productive with it... Whole weeks ? Yeah I'd have to deliver the entire e-commerce cart myself. It's advantage is that it is 10 years old, it is roofed by Apache foundation and it has relatively big community around. The disadvantage is, imho, that its main contributors are employees of companies that doesn't allow radical changes to it which causes defensive programming and not much of a radical refactoring that would be beneficial for the platform (at least I got the impression). This is not a problem for experienced Ofbiz developers, but it's quite a roadblock for newcomers.

I spent a couple hours looking at source base of Broadleaf Commerce and I see very clearly what would need to be done to setup a maven project (webapp) that represents e-commerce cart and that just deploys to a container with broadleaf platform libraries as dependencies and works ! You can see that a few minutes after svn checkout ! There is a demo project that you are supposed to copy/use as your new site/eshop. You  just override/add/merge what you need to (controllers, services, entities, jsp, css, entire modules) simply via spring configuration or filesystem changes and this way you build up your custom e-commerce cart. There is one thing that I would appreciate though : in addition to the demo site there should also be a maven archetype with default/classic template, infrastructure setup and default workflows and modules, that a developer just deploys and starts to modify. Or a theme or two would be nice. Another important point to mention is, that a good knowledge of Google Web Toolkit is great advantage, because you need it for developing backend / administration. Also Broadleaf Commerce seems to be easily deployable to Cloud Foundry for eventual scaling or other cloud-like needs. And finally, I think that this is the only and ideal e-commerce solution that would be relatively easy to integrate with Portals like Liferay or WebSphere and I'm not talking about just embedding it, but about building an e-commerce cart portlet with Broadleaf framwork. It would be tough integration job, but there is definitely no better or suitable candidate for that.

I would like to see and I wish Broadleaf Commerce a growing community because this software deserves attention.