<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-34123842</id><updated>2012-02-16T09:00:23.840-02:00</updated><category term='EJB'/><category term='JavaEE'/><category term='JBoss'/><category term='Profiler'/><category term='Liferay'/><category term='eXo'/><category term='NetBeans'/><category term='Portal'/><category term='Transaction'/><category term='Gridsphere'/><category term='Web'/><title type='text'>Extreme Java</title><subtitle type='html'>I'm not a guru, but sometimes I need to do some "unusual" things in Java. These things are so extreme that are not well documented. To help other Java users, I post my discoveries here.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-34123842.post-3438903478776919270</id><published>2008-02-08T09:51:00.000-02:00</published><updated>2008-02-08T09:52:55.784-02:00</updated><title type='text'>New host</title><content type='html'>This blog is now hosted on my own server:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://extremejava.tpk.com.br"&gt;http://extremejava.tpk.com.br&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-3438903478776919270?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/3438903478776919270/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=3438903478776919270' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/3438903478776919270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/3438903478776919270'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2008/02/new-host.html' title='New host'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-937638937922093136</id><published>2008-01-08T09:33:00.001-02:00</published><updated>2008-01-08T16:26:01.435-02:00</updated><title type='text'>Blackmagic with NetBeans and OpenOffice</title><content type='html'>This one is one of the weirdest (and useful) things I ever seen in 16 years of my life as a developer (I'm 26, BTW)... OpenOffice is a very powerful Office Automation solution... NetBeans Plaform is a very powerful application platform... Can you imagine what you get when you mix both together? Yup, this is possible. With NB and OOo installed, you just need to create a NB Module with following JARs from OOo: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;juh.jar&lt;/li&gt;&lt;li&gt;jurt.jar&lt;/li&gt;&lt;li&gt;officebean.jar&lt;/li&gt;&lt;li&gt;ridl.jar&lt;/li&gt;&lt;li&gt;unoil.jar&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I created another module with a single TopComponent, and add this snippet:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;private OOoBean oo;&lt;br /&gt;@Override&lt;br /&gt;public void componentOpened() {&lt;br /&gt;  try {&lt;br /&gt;    add(oo = new OOoBean());&lt;br /&gt;    oo.loadFromURL("private:factory/swriter", null);&lt;br /&gt;    oo.aquireSystemWindow();&lt;br /&gt;  } catch (Exception ex) {&lt;br /&gt;    Exceptions.printStackTrace(ex);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;But, this will NOT work... If you try to run it, an exception will be thrown, because OOo libs (.DLL/.SO) will not be found. They only exists in OOo install folder, and are automagically found by OOo classes - only if they aren't moved from the "classes" folder in OOo installation.&lt;br /&gt;&lt;br /&gt;The workaround is a couple of classes in OOo SDK and The Ultimate Blackmagic(TM) - patent pending:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Grab odk / source / com / sun / star / lib / loader from OOo's CVS and add it to integration module.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Add unowinreg.dll to Windows Path (if you are on Linux, skip this step).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Alter Loader.java and add this after line 205 (after "UnoInfo" call):&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;vec.add(new File(fClassesDir, "officebean.jar").toURL());&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;This part of the magick adds "officebean" to classpath. Here lies OOoBean, and is optional if you are only using UNO interfaces. Other JARs are correctly listed by UnoInfo.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Now, the ugliest part of the evil potion: create a Facade. Using OOoBean directly will lead to some ugly ClassLoader conflicts. I've no time to fix this, but the following works:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;public static Container buildOOoBean() {&lt;br /&gt;  return (Container) Loader.getCustomLoader().&lt;br /&gt;    loadClass("com.sun.star.comp.beans.OOoBean").&lt;br /&gt;    newInstance();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static void showOOoBean(Container oo) {&lt;br /&gt;  Class c = oo.getClass().&lt;br /&gt;    getClassLoader().&lt;br /&gt;    loadClass("com.sun.star.beans.PropertyValue");&lt;br /&gt;  Class ca = Array.newInstance(c, 0).getClass();&lt;br /&gt;  Method m = oo.getClass().&lt;br /&gt;    getMethod("loadFromURL", String.class, ca);&lt;br /&gt;  m.invoke(oo, "private:factory/swriter", null);&lt;br /&gt;&lt;br /&gt;  oo.getClass().&lt;br /&gt;    getMethod("aquireSystemWindow").invoke(oo);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Back to the TC, I use "buildOOoBean" in ComponentOpened and "showOOoBean" AFTER the component is shown (does not work otherwise).&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Yes, it is the purest evilness, but works (with some bugs):&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_fw4nVyjLLhg/R4O-L74AgfI/AAAAAAAAAAo/gaL9-OeyJ5w/s1600-h/ooo-nb.png"&gt;&lt;img style="margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_fw4nVyjLLhg/R4O-L74AgfI/AAAAAAAAAAo/gaL9-OeyJ5w/s320/ooo-nb.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5153171510902424050" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This level of indirection is mandatory, because client module's ClassLoader is different than integration module's. If I do "OOoBean oo = new OOoBean()", the declaration and instantiation will try to use the JARs bundled. Since they don't lie on OOo install folder, the libraries will not be found. If I use "oo = (OOoBean) Loader.getCustomLoader().getClass("...").newInstance()", the "OOoBean" class from declaration will NOT be the same as the class instantiated. If you ever worked with JavaEE 4 and JSF/Struts/etc, you know that same classes from different ClassLoaders throws ClassCastException.&lt;br /&gt;&lt;br /&gt;OOo works really well with Java, but NetBeans ClassLoader is "self-contained" (i.e. your bundled application must include EVERYTHING you use). This is a very nice architecture, but does not help if you if you need to interface with external applications.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-937638937922093136?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/937638937922093136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=937638937922093136' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/937638937922093136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/937638937922093136'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2008/01/blackmagic-with-netbeans-and-openoffice.html' title='Blackmagic with NetBeans and OpenOffice'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_fw4nVyjLLhg/R4O-L74AgfI/AAAAAAAAAAo/gaL9-OeyJ5w/s72-c/ooo-nb.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-4226605306213050167</id><published>2008-01-04T14:42:00.000-02:00</published><updated>2008-01-04T15:16:42.260-02:00</updated><title type='text'>Asynchronous Node children in NetBeans Platform</title><content type='html'>5 minutes playing with the new NetBeans 6 platform and I found a very useful feature. In previous post, I download URL. Using that code, I want to create a list of POJOs (that will be represented by a list of Nodes). In old NB5 days, I had to create a Thread and a lot of syncronization code to make the download run in background. In NetBeans 6 is easy as 1, 2, 3:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Subclass ChildFactory (from Nodes API), implementing createKeys and createNodeFromKey&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Create an AbstractNode passing Children.create(MyChildFactory)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Compile, run and enjoy!&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-4226605306213050167?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/4226605306213050167/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=4226605306213050167' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/4226605306213050167'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/4226605306213050167'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2008/01/asynchronous-node-children-in-netbeans.html' title='Asynchronous Node children in NetBeans Platform'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-4419261867901222126</id><published>2008-01-04T12:31:00.000-02:00</published><updated>2008-01-04T14:41:16.006-02:00</updated><title type='text'>HTTP POST download with Java's URL class</title><content type='html'>This is easy, but I always forget the recipe. I need to download and process a file using a POST request. The code is:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;URL url = new URL(FORM_URL);&lt;br /&gt;URLConnection conn = url.openConnection();&lt;br /&gt;conn.setDoOutput(true);&lt;br /&gt;&lt;br /&gt;OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());&lt;br /&gt;out.write("field=value&amp;field=value&amp;...");&lt;br /&gt;out.flush();&lt;br /&gt;&lt;br /&gt;BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));&lt;br /&gt;String line;&lt;br /&gt;&lt;br /&gt;while ((line = in.readLine()) != null) {&lt;br /&gt;    // do something&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;out.close();&lt;br /&gt;in.close();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The only catch is to use URLEncoder.encode to translate keys and values to the x-form-url-encoded style.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-4419261867901222126?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/4419261867901222126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=4419261867901222126' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/4419261867901222126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/4419261867901222126'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2008/01/http-post-download-with-javas-url-class.html' title='HTTP POST download with Java&apos;s URL class'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-5777960190149307979</id><published>2007-03-26T11:17:00.000-03:00</published><updated>2007-03-26T11:59:14.242-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='EJB'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaEE'/><category scheme='http://www.blogger.com/atom/ns#' term='Transaction'/><title type='text'>Transactions in EJB3</title><content type='html'>A little pause in the Quest for the Java Portal. I'm creating a JavaEE application, and I got a simple problem, but not well explained on the Internet. The scenario:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;EJB module has:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Some CMP beans (with @ManyToOne and @OneToMany relationships);&lt;/li&gt;&lt;li&gt;A Session Facade (stateless local bean).&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;WEB module has:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;A jMaki-powered menu tree;&lt;/li&gt;&lt;li&gt;A JSF-managed bean (that populates the jMaki tree with a call to Session Facade).&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;It is very simple, but I got a ServletException (caused by a LazyInitializationException) when I try to navigate the relationships on web container.&lt;br /&gt;&lt;br /&gt;Googleing this problem, I found that the transaction of a stateless bean (using a "requires" or "requires new" attribute) is closed after the method returns, if the container opened it. Specifically, it happens when the EntityManager is destroyed. This is obvious, but not very intuitive. Solutions:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Use a stateful bean. The Entity Manager will "survive" along with the session, but I think this will make the transaction survive that long, too. Not the best solution;&lt;/li&gt;&lt;li&gt;Open the transaction in web container. This is strange, but logical: if I want to access the database (with lazy fetching), I must have an active transaction. EJB container is prepared to reuse the transaction by using the @TransactionAttribute annotation (defaults to "REQUIRED"). Using the brand-new resource injection, it is a matter of creating a "@Resource UserTransaction tx" attribute on my JSF managed bean. It is not nice to inject a transaction on every bean of web container, so, you only need to create a web filter that opens before chaining the operation.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;As a conclusion, my contribution to JavaEE community. If you want to use Lazy Loading on web containers, you just need to create a Filter like this one:&lt;br /&gt;&lt;pre&gt;public class TransactionFilter implements Filter {&lt;br /&gt; @Resource&lt;br /&gt; private UserTransaction tx;&lt;br /&gt;&lt;br /&gt; public void doFilter(ServletRequest request,&lt;br /&gt;         ServletResponse response,&lt;br /&gt;         FilterChain chain)&lt;br /&gt;         throws IOException, ServletException {&lt;br /&gt;     try {&lt;br /&gt;         if (tx.getStatus() == STATUS_NO_TRANSACTION) {&lt;br /&gt;             tx.begin();&lt;br /&gt;         }&lt;br /&gt;     } catch (NotSupportedException ex) {&lt;br /&gt;         throw new ServletException(ex);&lt;br /&gt;     } catch (SystemException ex) {&lt;br /&gt;         throw new ServletException(ex);&lt;br /&gt;     }&lt;br /&gt; &lt;br /&gt;     chain.doFilter(request, response);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void destroy() {&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void init(FilterConfig filterConfig) {&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-5777960190149307979?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/5777960190149307979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=5777960190149307979' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/5777960190149307979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/5777960190149307979'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2007/03/transactions-in-ejb3.html' title='Transactions in EJB3'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-5427997601020763575</id><published>2007-03-18T16:41:00.000-03:00</published><updated>2007-03-18T16:41:15.575-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Portal'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><category scheme='http://www.blogger.com/atom/ns#' term='Profiler'/><category scheme='http://www.blogger.com/atom/ns#' term='Liferay'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>The quest for the Java Portal - Profiling Liferay</title><content type='html'>It's time to run the Profiler. I start JBoss with "run-nbprofiler.bat" (created by NetBeans) and ask NB to attach profiler. I'm using "analyze performance", filtering Java core classes. JBoss runs very slow, but this is normal, since profiler is collecting execution of every method.&lt;br /&gt;&lt;br /&gt;My first try showed that Lucene is called a lot of times, even when server is on "idle" state. Maybe it is a background job that should have a smaller frequency.&lt;br /&gt;&lt;br /&gt;The second try filters out Lucene classes (using NB Profiler options). I found two bootlenecks: com.liferay.portal.lucene.IndexWriterFactory.decrement (takes 58% of startup time) and JBoss classloaders. And I found that Liferay auto deploy is running too often (~5 seconds of delay). Nice for develoment, awful for production use.&lt;br /&gt;&lt;br /&gt;I had to remove JBoss classes from profiling, and I got amazed on things I discovered. I got a OutOfMemoryError (perm gen space) - solved by adding "-XX:MaxPermSize=256m" to run script - but I could find a lot of interesting things:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;getResourceAsStream was called 12068 times;&lt;/li&gt;&lt;li&gt;Xerces' ChildNode was instantiated 853808 times (does anybody imagine why Java is "slow"?);&lt;/li&gt;&lt;li&gt;Stacktrace got really deep. About 50 levels or more, not including JBoss, Lucene and JDK classes;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A chain of 7 filters was called before hitting Liferay's MainServlet. If you consider a little forward made after MainServlet, we reach 14 filters before hitting a JSP file;&lt;/li&gt;&lt;li&gt;JSP compilation took 19s on this environment - total execution was 180s;&lt;/li&gt;&lt;li&gt;LR's VelocityTaglib has 8 iconXXX() methods that took 8 seconds each - detail: each one forwards another request;&lt;/li&gt;&lt;li&gt;Everytime a "include" is made, the chain of 7 filter is called. And there's a LOT of includes.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Remember that this was only ONE hit and the request wasn't complete, because of the OOM error. After that, I'm going to have some fun in the "real world". I'll try to go deeper tomorrow. Maybe I can send a RFE to Liferay team after I organize the arguments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-5427997601020763575?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/5427997601020763575/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=5427997601020763575' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/5427997601020763575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/5427997601020763575'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2007/03/quest-for-java-portal-profiling-liferay.html' title='The quest for the Java Portal - Profiling Liferay'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-7637405091214335245</id><published>2007-03-18T14:34:00.000-03:00</published><updated>2007-03-18T14:44:19.505-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Portal'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><category scheme='http://www.blogger.com/atom/ns#' term='Profiler'/><category scheme='http://www.blogger.com/atom/ns#' term='Liferay'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>The quest for the Java Portal - Running Liferay</title><content type='html'>Now, I have a profiled environment. But, when I tried to run JBoss (without profiling), I got an error in counter-ejb module. Its classpath is not correctand, so, I added this line to my build.[user|computer].properties:&lt;br /&gt;&lt;pre&gt;classpath.manifest=[original line in build.properties] lib/doubleclick-filter.jar&lt;/pre&gt;I reported this bug on Liferay JIRA [#LEP-2406]. After another 16 minutes of compilation, I forgot to initialize the database. I had two options: use a diferent connection pool or initialize it before deploying Liferay. I prefer the second, so, the easiest way was to create a MBean that depends on LiferayPool. Hypersonic is smart enough to allow multiple SQL commands in one Statement. I will upload the code later, but it is a matter of create a MBean that reads the script provided by Liferay and runs it on the poll.&lt;br /&gt;&lt;br /&gt;This leads to an strange error about Spring transactions with EJB, Hibernate, JBoss and all. I don't remember the details, but the solution is to change the debug attribute of CachedConnectionManager. This is something I can't do in my shared JBoss server, so, I used an dirty trick:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Start JBoss with no Liferay, but with the original data source (liferay-db.xml configured);&lt;/li&gt;&lt;li&gt;JBoss translates your -ds file into and -service file and logs it with debug level;&lt;/li&gt;&lt;li&gt;Grab the translated file in log, create the -service, delete the -ds and indent the file - this will help you understand its structure;&lt;/li&gt;&lt;li&gt;Now, the funny part: copy CacheConnectionManager definition from jboss-jca.xml, paste into liferay-service.xml (inside the "CachedConnectionManager" optional attribute), and rename the MBean to an unique name - I put a ",name=xxx" suffix.&lt;/li&gt;&lt;/ol&gt;This will create a custom CCM to Liferay, without violating the original instance. That's what I love in Java (specially in JBoss): you can create a Lego-like software that is just a matter of do the bindings.&lt;br /&gt;&lt;br /&gt;Liferay runs fine, but I found two bugs: a ClassNotFoundException about ical4j, and the contents of Guest community are blank. The first, I solve by adding lib/ical4j.jar to manifest classpath (as above). The second I don't care, since I will clean everything when I deploy the real application.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-7637405091214335245?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/7637405091214335245/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=7637405091214335245' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/7637405091214335245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/7637405091214335245'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2007/03/quest-for-java-portal-running-liferay.html' title='The quest for the Java Portal - Running Liferay'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-5503232102303980308</id><published>2007-03-16T15:09:00.000-03:00</published><updated>2007-03-16T16:03:02.361-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Portal'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><category scheme='http://www.blogger.com/atom/ns#' term='Profiler'/><category scheme='http://www.blogger.com/atom/ns#' term='Liferay'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>The quest for the Java Portal - Compiling Liferay</title><content type='html'>I got some weird exceptions with JBoss Portal, so, I decided to play around with Liferay. I have it running on my shared JBoss, and I have some ideas to their structured articles feature, so I will try harder on Liferay.&lt;br /&gt;&lt;br /&gt;I've decided to check the bootlenecks on Liferay, because it is too slow. I'll use NetBeans Profiler. Using NB's ability to create projects using existing Ant scripts, I've done some setup:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Create an Java Application project using an already existing Ant script;&lt;/li&gt;&lt;li&gt;Add all "src" folder to the source folders list - about 20 of them (I guess this isn't necessary unless we want to change anything);&lt;/li&gt;&lt;li&gt;Adjust compilation build to the "start" target and run to "deploy" (Liferay does not set "start" as dependency to "deploy");&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Create a "build.[user|computer].properties" and "app.server.[user|computer].properties" to customize some build parameters. I dislike Jikes, so, I'm using "javac.compiler=modern". The rest of properties are straighforward to customize, but folders on app.server must be correctly configured - JBoss predefined values does not work on an out-of-box installation;&lt;/li&gt;&lt;li&gt;After building a lot of modules (about 10 minutes on an almost empty Windows box powered by an Athlon XP 3200+), more than 2000 classes - yes, two thousands - are compiled without errors. Running the "deploy" target will install Liferay on JBoss. It installs some JARs on server's lib folder - I will change this later, before uploading to the real server.&lt;/li&gt;&lt;/ol&gt;Now, you can run JBoss. But first, some one-time configuration:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Add a datasource. To use profiling, I created a memory-only HSQLDB:&lt;pre&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;datasources&amp;gt;&lt;br /&gt;&amp;lt;local-tx-datasource&amp;gt;&lt;br /&gt;  &amp;lt;jndi-name&amp;gt;jdbc/LiferayPool&amp;lt;/jndi-name&amp;gt;&lt;br /&gt;  &amp;lt;connection-url&amp;gt;jdbc:hsqldb:.&amp;lt;/connection-url&amp;gt;&lt;br /&gt;  &amp;lt;driver-class&amp;gt;org.hsqldb.jdbcDriver&amp;lt;/driver-class&amp;gt;&lt;br /&gt;  &amp;lt;user-name&amp;gt;sa&amp;lt;/user-name&amp;gt;&lt;br /&gt;  &amp;lt;password&amp;gt;&amp;lt;/password&amp;gt;&lt;br /&gt;&amp;lt;/local-tx-datasource&amp;gt;&lt;br /&gt;&amp;lt;/datasources&amp;gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Use NetBeans Profiler (Profile | Attach Profiler) to prepare a special run script to active profiling on JBoss - this file will be called "run-nbprofiler".&lt;/li&gt;&lt;/ol&gt;Now, we have an working environment. Next step is test and profile.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-5503232102303980308?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/5503232102303980308/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=5503232102303980308' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/5503232102303980308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/5503232102303980308'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2007/03/quest-for-java-portal-compiling-liferay.html' title='The quest for the Java Portal - Compiling Liferay'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-2546459887912011647</id><published>2007-03-13T11:47:00.000-03:00</published><updated>2007-03-13T11:46:00.744-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Portal'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><title type='text'>The quest for the Java Portal - Testimonial</title><content type='html'>I was supposed to be an &lt;span style="font-weight: bold;"&gt;user &lt;/span&gt;of Java Portals, not a developer. Things like JBoss management portlet are annoying, but it is just a matter of user experience. At least JBoss Portal deploys with minimal changes. Actually, I only need to change &lt;span style="font-weight: bold;"&gt;deployment&lt;/span&gt; descriptors.&lt;br /&gt;&lt;br /&gt;Portals like Gridsphere, Jetspeed and others are unusable to normal users, since they need to know Java very well. How can I replace Zope/Plone in my job if every environment admin will need to know how to use Maven/Ant/etc?&lt;br /&gt;&lt;br /&gt;Is that hard to develop an JavaEE application that makes users' life &lt;span style="font-weight: bold;"&gt;easier&lt;/span&gt;?&lt;br /&gt;&lt;br /&gt;If I need to do any developer task, I prefer to develop my own portal that conforms to JSR-168 without violating JavaEE specifications.&lt;br /&gt;&lt;br /&gt;BTW, I'm talking as a Java Portal user (i.e. portal deployer/admin). I'm not talking as the user of the portal I will create with a Java Portal (i.e. my "costumers").&lt;br /&gt;&lt;br /&gt;End note: I'll try JBoss Portal beta-1, since it was released this week, but I won't use it if I still needs that buggy management layout.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-2546459887912011647?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/2546459887912011647/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=2546459887912011647' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/2546459887912011647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/2546459887912011647'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2007/03/quest-for-java-portal-testimonial.html' title='The quest for the Java Portal - Testimonial'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-8846540452078229102</id><published>2007-03-13T10:30:00.000-03:00</published><updated>2007-03-13T10:38:51.360-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gridsphere'/><category scheme='http://www.blogger.com/atom/ns#' term='Portal'/><title type='text'>The quest for the Java Portal - Gridsphere Tests</title><content type='html'>GridSphere compiled in an zero-error-in-deploy WAR file. But, with my well-known luck and my incredible skill of catch the weirdest bugs on Earth, I got the classic "error-page-that-throws-error" bug. A page throwed an error. This triggers the error page. But, the same error was throwed. This triggers the error page. I love when this happens. My luck was the StackOverflowError. In some EPTTE bugs the error page leads to HTTP infinite redirection.&lt;br /&gt;&lt;br /&gt;The origin of the error? This little piece of code:&lt;br /&gt;&lt;pre&gt;public synchronized Object deepCopy(Object oldObj) throws Exception {&lt;br /&gt;   ObjectOutputStream oos = null;&lt;br /&gt;   ObjectInputStream ois = null;&lt;br /&gt;   try {&lt;br /&gt;       ByteArrayOutputStream bos =&lt;br /&gt;           new ByteArrayOutputStream(); // A&lt;br /&gt;       oos = new ObjectOutputStream(bos); // B&lt;br /&gt;       // serialize and pass the object&lt;br /&gt;       oos.writeObject(oldObj);   // C&lt;br /&gt;       oos.flush();               // D&lt;br /&gt;       ByteArrayInputStream bin =&lt;br /&gt;           new ByteArrayInputStream(bos.toByteArray()); // E&lt;br /&gt;       ois = new ObjectInputStream(bin);                  // F&lt;br /&gt;       // return the new object&lt;br /&gt;       return ois.readObject(); // G&lt;br /&gt;   } catch (Exception e) {&lt;br /&gt;       throw e;&lt;br /&gt;   } finally {&lt;br /&gt;       if (oos != null) oos.close();&lt;br /&gt;       if (ois != null) ois.close();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;I will not comment the weird "catch e throw e" fragment, but this was the most expensive way to follow the Prototype pattern (deep copy variant) I ever seen. You don't need to be an extreme Java programmer to notice this code will fail on the first non-serializable class found by oos.writeObject. Now, guess what was the exception I got?&lt;br /&gt;&lt;pre&gt;java.io.NotSerializableException: org.apache.log4j.Level&lt;/pre&gt;After digging into the code, I discovered that GS team knows the use of transient keyword, but didn't used it on BasePortletComponent.java, line 42:&lt;br /&gt;&lt;pre&gt;protected Log log = LogFactory.getLog(PortletPageFactory.class);&lt;/pre&gt;How this works on Tomcat is a mistery to me. Changing it to a final static attribute and adding some dependencies of dependencies (Jackrabbit needs Lucene and yet another logging implementation - SLF4J), made it work, but not as expected.&lt;br /&gt;&lt;br /&gt;Result: an installation page with some really ugly URL rewrite techniques.&lt;br /&gt;&lt;pre&gt;&amp;lt;link ... href="/tmp54563GridSphere-exp.war/...css" ...&amp;gt;&lt;br /&gt;&amp;lt;img src="/@GRIDSPHERE_DEPLOY@/...png" ...&amp;gt;&lt;/pre&gt;The second one is a side-effect of using my own build script. The first one (along with cool design patterns) gives GridSphere an one-way ticket to my attic.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-8846540452078229102?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/8846540452078229102/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=8846540452078229102' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/8846540452078229102'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/8846540452078229102'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2007/03/quest-for-java-portal-gridsphere-tests.html' title='The quest for the Java Portal - Gridsphere Tests'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-6838704776493979856</id><published>2007-03-13T09:41:00.000-03:00</published><updated>2007-03-13T09:38:40.978-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gridsphere'/><category scheme='http://www.blogger.com/atom/ns#' term='Portal'/><title type='text'>The quest for the Java Portal - Gridsphere Compilation</title><content type='html'>Current version of Gridsphere, 3.0.3, supports Tomcat and Jetty only. Since I'm extreme (-lly nuthead), I've tryed to run it on JBoss. I haven't found any live demo on its site - too bad.&lt;br /&gt;&lt;br /&gt;Like Jetspeed and eXo, there's no WAR/EAR/SAR/CAR/etcAR file to download - I must download the source and compile (there's a corrupted, hidden WAR file on server, if you edit by hand the URL of download). Good news is: it uses Ant (not Maven) - that means I does not need to dig into obscure and unstructured XML. IMHO, Maven is good for the main developer, but not for the bug hunters, like me.&lt;br /&gt;&lt;br /&gt;As expected, it wasn't straightforward. The steps:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Set CATALINA_HOME to JBoss' server folder - "$JBOSSHOME/server/$instance". Compilation script needs a "lib" folder with JavaEE API. Tomcat 5 stores on "$C_H/common/lib", Tomcat 6 stores on "$C_H/lib". Gridsphere "detects" tomcat version by verifying if "$C_H/common/lib" exists.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;This leads to a "$C_H/bin" not found. After some digging in build scripts (I love Ant), I found an strange task that adds Tomcat's bin dir to classpath:&lt;blockquote&gt;&lt;pre&gt;110 &amp;lt;fileset dir="${appserver.home}/bin/"&amp;gt;&lt;br /&gt;111     &amp;lt;include name="*.jar"&amp;gt;&lt;br /&gt;112 &amp;lt;/fileset&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;Removing it and running the undocumented "ant war" task, creates the web archive.&lt;/li&gt;&lt;li&gt;The archive will not deploy: a ClassNotFoundException nested in a WSException. The class that was not found was the CaptchaServlet. The CNFE is strange, since the class is on "WEB-INF/lib" folder. Since I will not allow new users, I removed the reference from web.xml, but the same exception was thrown, with class GridSphereServlet.&lt;/li&gt;&lt;/ol&gt;At this point, I got tired of editing files by hand, and I created a NetBeans project to handle everything to me. This is the approach I'm doing with Liferay, and, likewise, I found a lot of dependencies, like Castor (yet another binding framework), JFreeChart, and others.&lt;br /&gt;&lt;br /&gt;BTW, JFreeChart deserves some lines. First, I thought one of JFree JAR files were corrupt in GS distribution. I've decided to download it from JFree site and I can't see the documentation because IT IS NOT FREE. Yup. I can download the sources, but not the developer documentation.&lt;br /&gt;&lt;br /&gt;And, like every giant project, I found useless things, like Perl5Util. I don't want to discuss if P5U is useful, but use it to replace regex like "\.xml$" with "" is a waste of resources, since String.replaceFirst can do the job.&lt;br /&gt;&lt;br /&gt;Finally, I could compile with zero errors (and a lot of unchecked warnings). But it didn't run. I got an weird exception in Castor. After some reverse engineering, since there isn't architetural documentation, I found I need to add six XML files to their correct folders. In original GS structure, these XML lies on a "config" dir, but are copied to different folders by one of the 10 Ant scripts. Copying them made a deployable WAR file.&lt;br /&gt;&lt;br /&gt;This is a thumbs up no NetBeans: users will always have an well organized project structure. There are no lost files on lost folders needing a lost task on a lost script to copy them to the correct place.&lt;br /&gt;&lt;br /&gt;BTW, the problem was a static Class.getResource returning null. I had to change the code (adding some assertions) to figure it out.&lt;br /&gt;&lt;br /&gt;Tip to Gridsphere team: use NetBeans to manage the project...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-6838704776493979856?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/6838704776493979856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=6838704776493979856' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/6838704776493979856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/6838704776493979856'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2007/03/quest-for-java-portal-gridsphere.html' title='The quest for the Java Portal - Gridsphere Compilation'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-2391064302974924615</id><published>2007-03-11T02:16:00.000-03:00</published><updated>2007-03-11T03:06:55.523-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Portal'/><category scheme='http://www.blogger.com/atom/ns#' term='Profiler'/><category scheme='http://www.blogger.com/atom/ns#' term='Liferay'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>The quest for the Java Portal - inside Liferay, ep. 1</title><content type='html'>Liferay is running slowly on my JBoss server, crashes lots of times, but works. I have decided to play with its source code, maybe optimizing here and there. &lt;a href="http://www.netbeans.org/products/profiler/"&gt;NetBeans Profiler&lt;/a&gt; is perfect for this job, but Liferay was written with Eclipse. NetBeans project importer worked, but it didn't help, because the Liferay source structure is monolithic. Since I had some free time this weekend, I'm manually converting the project. I converted about 15%, but look what I found so far:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Tab size = 8. This is a HUGE tab size. Usually Java projects use 4. But this is a matter of taste.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Actually, this is what I didn't found: documentation. No JavaDocs on classes I opened. I don't know how they can work on classes without any documentation. I always forget the use of any class I don't open often... :)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Lots of third part libraries. And I'm not talking about the classic ones (like commons-logging). I found things like EasyConf (looks like Java Preferences API), OSCache (object cache that works on cluster environments) and Trone (yet another Collections framework). This explains the need for a bigger PermSize.&lt;/li&gt;&lt;/ul&gt;Liferay is a great product, but it really needs a good cleanup. Some of their optimization tricks creates overheads, like using Colt (yet another Collections framework - yes, they have TWO different YACF). Colt have some "sync collections" that works using the same synchronization principle as Hashtable and Vector. The question is: why they leave synchronization to the collection? What about using the "synchronized(xxx)" structure?&lt;br /&gt;&lt;br /&gt;I will follow GrOG's tip (in last blog's comments): report my discoveries to the community. I preferred to report only after deciding which Portal I will use, but the decision is taking me too deep on each implementation I'm testing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-2391064302974924615?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/2391064302974924615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=2391064302974924615' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/2391064302974924615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/2391064302974924615'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2007/03/quest-for-java-portal-inside-liferay-ep.html' title='The quest for the Java Portal - inside Liferay, ep. 1'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-5764982448296687140</id><published>2007-03-08T15:07:00.000-03:00</published><updated>2007-03-08T15:18:00.136-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Portal'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><title type='text'>The quest for the Java Portal - JBoss Portal 2.6 live</title><content type='html'>No changes in JBoss Portal 20070307 nightly build. I saw JBoss &lt;a href="http://labs.jboss.com/portal/jbossajax4jsf"&gt;ajax4jsf&lt;/a&gt; and JBoss &lt;a href="http://labs.jboss.com/portal/jbossrichfaces"&gt;Rich Faces&lt;/a&gt; and could not imagine why these incredibly cool components aren't used by JBoss Portal.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-5764982448296687140?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/5764982448296687140/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=5764982448296687140' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/5764982448296687140'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/5764982448296687140'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2007/03/quest-for-java-portal-jboss-portal-26_08.html' title='The quest for the Java Portal - JBoss Portal 2.6 live'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-7592555081610774833</id><published>2007-03-08T11:19:00.000-03:00</published><updated>2007-03-08T13:53:18.677-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Portal'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><title type='text'>The quest for the Java Portal - JBoss Portal 2.6</title><content type='html'>JBoss Portal version 2.6 is still alpha, but I tryed it (since it claims to have a better user experience). I've downloaded its binary version - a JBoss' SAR archive. Out-of-box installation was a matter of copy datasource definition and the SAR file to my deploy folder.&lt;br /&gt;&lt;br /&gt;It has the same limitations as 2.4:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Delete the management portlet and your layout is locked;&lt;/li&gt;&lt;li&gt;You can delete ALL users and have a nice NPE;&lt;/li&gt;&lt;li&gt;The layout arrangement is not inline (needs the management portlet).&lt;/li&gt;&lt;/ul&gt;But, as I expected, it is pretty light. Unlink Liferay, the startup was really quick. If it was more AJAX-aware, JBoss Portal could be my portal of choice. Well, according to Grog, beta 1 will be released soon. I'm downloading a nightly build and I'll try it again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-7592555081610774833?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/7592555081610774833/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=7592555081610774833' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/7592555081610774833'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/7592555081610774833'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2007/03/quest-for-java-portal-jboss-portal-26.html' title='The quest for the Java Portal - JBoss Portal 2.6'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-2275570250786890911</id><published>2007-03-08T09:22:00.000-03:00</published><updated>2007-03-08T11:03:39.135-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Portal'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><title type='text'>The quest for the Java Portal - JBoss Portal</title><content type='html'>Today mission: JBoss Portal. My first impression: negative. I've tryed its live demo and, after two minutes, I render it useless. How? Follow the steps:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Login as admin/admin&lt;/li&gt;&lt;li&gt;Go to the admin page&lt;/li&gt;&lt;li&gt;Remove the administration portlet&lt;/li&gt;&lt;/ol&gt;What you got? A portal with a layout that can't be changed... That's typical from JBoss community: they create a simple kernel and everything is extension. JBoss Application Server is a microkernel that manages JMX beans. Everything else is JMX. Likewise, JBoss Portal is just a portlet container. You need that ugly and unintuitive manager (as ugly and unintuitive as AS managers) to manage everything.&lt;br /&gt;&lt;br /&gt;BTW, that management portlet does a lot of roundtrips to the server (yep, no AJAX). If you plan to use it on your server, create a page that contains only the manager portlet.&lt;br /&gt;&lt;br /&gt;JBoss Portal 2.4 is off my list. I will try 2.6alpha2.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-2275570250786890911?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/2275570250786890911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=2275570250786890911' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/2275570250786890911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/2275570250786890911'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2007/03/quest-for-java-portal-jboss-portal.html' title='The quest for the Java Portal - JBoss Portal'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-214484174349718484</id><published>2007-03-06T20:56:00.000-03:00</published><updated>2007-03-08T08:49:57.201-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gridsphere'/><category scheme='http://www.blogger.com/atom/ns#' term='Portal'/><category scheme='http://www.blogger.com/atom/ns#' term='eXo'/><category scheme='http://www.blogger.com/atom/ns#' term='Liferay'/><title type='text'>Thumbs down to Java Portals</title><content type='html'>One of the most frustrating things I have tryed to do was to use a Java Portal. I haven't found a JSR-168 compliant portal that could work at all. I have simple needs:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The portal must run on JBoss: I'm renting a shared JBoss server;&lt;/li&gt;&lt;li&gt;I need to put a "virtual-host" tag in every jboss-web.xml: this is how JBoss will map my domain to my applications;&lt;/li&gt;&lt;li&gt;I must have total control over JNDI/JMX naming conventions: "default" names are unacceptable, since other "clients" may want to use the same implementation;&lt;/li&gt;&lt;li&gt;The portal must NOT create any files on the filesystem: JBoss runs with an specific user that does not have write access to my private folders; and&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Memory and CPU consumption must be light: obviously.&lt;/li&gt;&lt;/ol&gt;What I found:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;JBoss Portal:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Prós: Runs on JBoss (of course) and seems to be light&lt;/li&gt;&lt;li&gt;Cons: UGLY. Portal layout is defined with some weird arrows on an weird admin page&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Liferay&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Pros: beautiful, lots of AJAX, lots of out-of-box portlets&lt;/li&gt;&lt;li&gt;Cons: invasive (needs to create a lot of files), eats CPU and memory like I eat chocolate and creates JMX in runtime (but does not release them on undeploy). "Professional" version (WAR) takes 30 minutes to deploy, "Enterprise" version (EAR) crashed the server (yikes) and requires a lot of customization to run on a shared server&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;eXo&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Pros: like Liferay, it's beautiful, lots of AJAX, lots of portlets, and have an awesome "desktop" version&lt;/li&gt;&lt;li&gt;Cons: I have to compile EVERYTHING and do a lot of digging on its source to customize it to my needs. I simply can't understand its compilation steps. Poor documentation. I could only test tomcat version, since I could not compile an working version...&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Gridsphere&lt;br /&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Pros: dunno&lt;/li&gt;&lt;li&gt;Cons: runs only on Tomcat&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;This is amazing... With JavaEE version 5, I thought I could find a portal that could be deployed as easy as 1-2-3:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Download a WAR/EAR file;&lt;/li&gt;&lt;li&gt;Add some jboss-web.xml (to map JNDI and virtual host) - this is my "deployer" role on an JavaEE application lifecycle (as defined by JavaEE specs);&lt;/li&gt;&lt;li&gt;Deploy the file on server.&lt;/li&gt;&lt;/ol&gt;But step 1 is non-existent on portals like GridSphere. Step 2 becames steps 2.a to 2.zzzz on eXo and Liferay... Every portal wants the user to download a package bundled with tomcat/jboss or to follow this recipe:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Download source (WORA, anyone?)&lt;/li&gt;&lt;li&gt;Compile using Maven (yet-another-build-automation-tool)&lt;/li&gt;&lt;li&gt;Package using Maven (its "custom" tasks does not allow me to add a jboss-web.xml, since even web.xml is generated by it)&lt;/li&gt;&lt;li&gt;Deploy on tomcat (JBoss sometimes)&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Why?? Is that hard to create a REAL JavaEE-compliant application that implements JSR-168??? That's a thumb down to Java Portals (and JSR-168)...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-214484174349718484?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/214484174349718484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=214484174349718484' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/214484174349718484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/214484174349718484'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2007/03/thumbs-down-to-java-portals.html' title='Thumbs down to Java Portals'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-115801450146082629</id><published>2006-09-11T19:27:00.000-03:00</published><updated>2006-09-12T08:55:54.556-03:00</updated><title type='text'>NetBeans Code Folding</title><content type='html'>Tired of lose the fight against NetBeans MDR stuff, I decided to check out Code Folding. Pretty easy, indeed. I haven't done a full code fold example, but I was able to use NB 'editor-fold' pseudo-tag. Considering that you have the syntax support (see &lt;a href="http://platform.netbeans.org/tutorials/index.html"&gt;NBP Tutorials&lt;/a&gt;), the steps are:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;On your SettingsInitializer, you need to add this line:&lt;br /&gt;    &lt;pre&gt;settingsMap.put(SettingsNames.CODE_FOLDING_ENABLE, Boolean.TRUE);&lt;/pre&gt;This is not obvious, but it is the most important step. Without it, you will never activate folding (this was hard to find out - like any other "non-layer.xml" stuff).&lt;br /&gt; &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;On your EditorKit, you need to implement the SyntaxUpdateTokens class and put it as a document property. Like this:&lt;br /&gt;      &lt;pre&gt;public class MyEditorKit extends NbEditorKit {&lt;br /&gt;    [ ... ]        &lt;br /&gt;&lt;br /&gt;    protected void initDocument(BaseDocument doc) {&lt;br /&gt;        doc.putProperty(SyntaxUpdateTokens.class, new SUT());&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public class SUT extends SyntaxUpdateTokens {&lt;br /&gt;&lt;br /&gt;        private List list;&lt;br /&gt;        &lt;br /&gt;        public void syntaxUpdateStart() {&lt;br /&gt;            list = new ArrayList();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public List syntaxUpdateEnd() {&lt;br /&gt;            return list;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void syntaxUpdateToken(TokenID tid, TokenContextPath tcp,&lt;br /&gt;                int offset, int len) {&lt;br /&gt;            if (tokenID == MyTokenContext.LINE_COMMENT) {&lt;br /&gt;                list.add(new TokenInfo(tid, tcp, offset, len));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;This will tell CustomFold which tokens it must use to find the pseudo-tag.&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;You need to create a three-line class to add the sidebar to the editor:&lt;br /&gt;    &lt;pre&gt;public class MyFoldingSideBarFactory implements SideBarFactory {&lt;br /&gt;    public JComponent createSideBar(JTextComponent jTextComponent) {&lt;br /&gt;        return new CodeFoldingSideBar(jTextComponent);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;This is a weird step. I don't know why there's no ready-to-go class to do this job.&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Now, glue everything in your layer.xml, under "Editor/MIME" folder:&lt;br /&gt;    &lt;pre&gt;&amp;lt;folder name="SideBar"&amp;gt;&lt;br /&gt;    &amp;lt;file name="mypkg-MyFoldingSideBarFactory.instance"/&amp;gt;&lt;br /&gt;    &amp;lt;attr name="org-netbeans-editor-GlyphGutter.instance&lt;br /&gt;        /mypkg-MyFoldingSideBarFactory.instance"&lt;br /&gt;        boolvalue="true"/&amp;gt;&lt;br /&gt;&amp;lt;/folder&amp;gt;&lt;br /&gt;&amp;lt;folder name="FoldManager"&amp;gt;&lt;br /&gt;    &amp;lt;file name="org-netbeans-editor-CustomFoldManager$Factory.instance"/&amp;gt;&lt;br /&gt;&amp;lt;/folder&amp;gt;&lt;/pre&gt;FoldManager can be chained, just like the SideBar. Making it easy to add a "real" code fold based on tokens.&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-115801450146082629?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/115801450146082629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=115801450146082629' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/115801450146082629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/115801450146082629'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2006/09/netbeans-code-folding.html' title='NetBeans Code Folding'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34123842.post-115784488215159438</id><published>2006-09-09T20:16:00.000-03:00</published><updated>2006-09-11T09:22:16.123-03:00</updated><title type='text'>First post - current misson brief</title><content type='html'>This is the first post. I don't have any ready tip yet, but I'll post my "current mission":&lt;br /&gt;&lt;br /&gt;I'm trying to understand how to add a new language to &lt;a href="http://www.netbeans.org"&gt;NetBeans&lt;/a&gt;. I want everything Java Editor has: Code Completion, Code Folding, etc. In theory, it's simple: I just need to add editor support and create a metamodel to feed other subsystems.&lt;br /&gt;&lt;br /&gt;The first part is well explained on &lt;a href="http://platform.netbeans.org"&gt;NetBeans Platform web site&lt;/a&gt; (actually, it's incredibly simple to add syntax highlight), but there aren't good docs about how the "Java Language Model" works on NB.&lt;br /&gt;&lt;br /&gt;And now my problem: I've created a metadata repository using NetBeans' MDR stuff, but I simply do not know how to populate the repository using source files (and how to create source files from the repository).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34123842-115784488215159438?l=extremejava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://extremejava.blogspot.com/feeds/115784488215159438/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34123842&amp;postID=115784488215159438' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/115784488215159438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34123842/posts/default/115784488215159438'/><link rel='alternate' type='text/html' href='http://extremejava.blogspot.com/2006/09/first-post-current-misson-brief.html' title='First post - current misson brief'/><author><name>Eduardo</name><uri>http://www.blogger.com/profile/04225169220107206884</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
