NetBeans World Tour 2008 in Krakow

NetBeans World Tour 2008
Last Friday NetBeans Roadshow which is part of NetBeans WorldTour took place in Krakow at AGH University. Guys from Sun department were presenting new capabilities of NetBeans 6.0 trying to convience participants that it is better or at least as good as Eclipse;-)

Interesting stuff I have found out is that actually one of the presenters (Karol Harezlak) fixed the bug in NetBeans mobile component FileBrowser that I have described couple of weeks before and spent couple of extra hours on code because of it. Besides that nice demo of using SVG (JSR 226) in J2ME was presented – it allows to make really cool looking stuff on mobile devices easily, especially while using Mobility Pack.

My general impression of NetBeans 6.0 – it goes in right direction. There are a lot on nice and unique features (e.g. Mobility Pack, JavaFX plugin, quite good Maven integration) but until Java editor in NetBeans isn’t as efficient as Eclipse one I will not switch with development completly to NetBeans.

Keep the fingers crossed for NetBeans 😉

Eclipse – a workspace and its resources. Problem with case-insensitive file systems.

All the resources in Eclipse workspace are case-sensitive. Name of the file inside a project in Eclipse workspace is case-sensitive. On Eclipse API level two resources called somefile.TXT and somefile.txt are different resources. The problem starts while such resources are stored in the file system. Method org.eclipse.core.resources.IResource.exists() will return false for somefile.TXT if there is already somefile.txt in the workbench. This cause problem if you are for example implementing wizard for creating new file resource – basing on the Eclipse API you cannot check if such file already exists. My workaround for this was using java.io classes directly for this. Another problem is if in you wizard you want to overwrite existing file with new one e.g. somefile.TXT with somefile.txt. If you try to use org.eclipse.ui.ide.IDE.openEditor(IWorkbenchPage page, IFile input, String editorId, boolean activate) for this overwritten file – it will fail opening it. In Eclipse 3.3 there was introduced method openEditor(IWorkbenchPage page, URI uri, String editorId, boolean activate) – which doesn’t have problem with case-sensitivity. Unfortunately it opens the file in read-only mode while the new resource is out of the workbench! I haven’t found any nice programmatic way to “refresh” workbench in order to reflect the changes that were made on file system behind the scene (as user can do manually by pressing F5). May workaround for this is opening the editor twice – first time using openEditor(IWorkbenchPage page, IFile input, String editorId, boolean activate) and closing it immediately in order to “refresh” workbench and after that using openEditor(IWorkbenchPage page, URI uri, String editorId, boolean activate) – now the new file is already in the workbench and the it’s not opened in read-only mode.

This is one of the problems I encountered while developing Eclipse plugins on Windows platform. I’m missing possibility for configuring all the resources related code for dealing with OS-dependent stuff like mentioned above problem with case-sensitivity.

Eclipse 3.3 API reference can be found here.

Jakarta BCEL

BCEL (Byte Code Engineering Library) gives a possibility to analyze, create and modify Java class files. It gives very nice API for manipulating inside bytecode. Here is an example of using BCEL. It adds instructions relevant to System.out.println(“About to call: METHOD_NAME METHOD_SIGNATURE”) before invocation of any method in the class.


import java.io.IOException;
import java.util.Iterator;

import org.apache.bcel.Repository;
import org.apache.bcel.classfile.ClassFormatException;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.*;

/**
 * Instruments byte-code by adding: 
 * System.out.println("About to call: METHOD_NAME METHOD_SIGNATURE");
 * 
 * before method invocation.
 *
 * @author Radoslaw Urbas
 * @since Oct 27, 2007
 *
 */
public class Transform
{

    private ClassGen classGen = null;

    /**
     *
     * @param className name of class to instrument
     * @throws ClassNotFoundException
     * @throws ClassFormatException
     * @throws IOException
     */
    public Transform(String className) throws ClassNotFoundException,
            ClassFormatException, IOException
    {
        this.classGen = new ClassGen(Repository.lookupClass(className));
    }

    /**
     * Instruments the class by displaying method information before invocation.
     *
     * @return instrumented ClassGen object
     */
    private ClassGen instrument()
    {
        ConstantPoolGen pgen = classGen.getConstantPool();
        String cname = classGen.getClassName();
        for (Method method : classGen.getMethods())
        {
            MethodGen methgen = instrumentMethod(pgen, cname, method);
            classGen.replaceMethod(method, methgen.getMethod());
        }
        return classGen;
    }

    /**
     * Instruments method by displaying information before method invocation.
     *
     * @param constantPoolGen constant pool for class containing method to
     *            instrument
     * @param className name of the class containing method to instrument
     * @param method method to instrument
     * @return instrumented MethodGen object
     */
    private MethodGen instrumentMethod(ConstantPoolGen constantPoolGen,
            String className, Method method)
    {
        InstructionFactory instructionFactory = new InstructionFactory(classGen);
        MethodGen methgen = new MethodGen(method, className, constantPoolGen);
        InstructionList originalInstructionList = methgen.getInstructionList();
        Iterator instructionIterator = originalInstructionList.iterator();
        while (instructionIterator.hasNext())
        {
            InstructionHandle ih = (InstructionHandle) instructionIterator
                    .next();
            if (ih.getInstruction() instanceof InvokeInstruction)
            {
                originalInstructionList.insert(ih, instructionFactory
                        .createPrintln(getMessage((InvokeInstruction) ih
                                .getInstruction(), constantPoolGen)));
            }
        }
        methgen.setMaxStack();
        return methgen;
    }

    /**
     *
     * @param invokeInstruction object representing invoke instruction
     * @param constantPoolGen
     * @return message based on method name and signature
     */
    private String getMessage(InvokeInstruction invokeInstruction,
            ConstantPoolGen constantPoolGen)
    {
        String text = "About to call: "
                + invokeInstruction.getMethodName(constantPoolGen)
                + invokeInstruction.getSignature(constantPoolGen);
        return text;
    }

    /**
     *
     * @param args requires one parameter: class name. Class should be available
     *            in directory ./classes
     * @throws ClassNotFoundException
     * @throws IOException
     */
    public static void main(String[] args) throws ClassNotFoundException,
            IOException
    {
        String className = args[0];
        Transform transform = new Transform(className);
        ClassGen classGen = transform.instrument();
        classGen.getJavaClass().dump(className + ".class");
    }
}

Homepage: http://jakarta.apache.org/bcel/

AppFuse – first impression

Couple days ago I was looking for some starter kit for Java web applications based on Spring framework. After short investigation I have decide to try some of Maven2 archetypes. If you just type: mvn archetype:create you get list of standard archetypes. Take a look on positions 1-9 (AppFuse starter-kits).

For further investigation I chose appfuse-modular-struts which is a solution based on Hibernate, Spring and Struts2.

To kickoff application kickoffs there are just few simple steps:

  • Launch database. I was trying it with Derby and PostgreSQL.
  • Configure database settings in pom.xml in main directory by adding line true in ‘profiles’ section after ‘id’ of DB of your choice and setting proper user/pass and database name if applicable.
  • Kickoff Maven build and run application:
    mvn
    cd web
    mvn jetty:run-war
  • Navigate to http://localhost:8080 in you browser.

You will see simple application that allows to:

  • Log in (admin/admin).
  • List the users.
  • Edit user data.

Everything looks great. That is the moment when you are starting to look for sources of this application. To get the source you need to invoke another Maven target
mvn appfuse:full-source.

Now you can rebuild the application and do the changes you want.
There is also nice feature for adding standard code. You can generate all required class and configurations for domain objects. To do this add new domain object in your.application.model package in core module and annotate it properly. After that:
cd core
mvn appfuse:gen -Dentity=YourNewObject
cd ..
cd web
mvn appfuse:gen -Dentity=YourNewObject

All the classes, configurations and webpages should be ready for performing CRUD operations for this POJO!

Everything looks great, but there is one concern. Don’t use Java 1.6. Use Java 1.5. It took me several hours to figure out that this is the problem while tests fails (just HTTP 500 respond, no exceptions, no logs). Haven’t investigated yet what’s it the core of the problem with using it on Java 6.

AppFuse homepage: http://appfuse.org/display/APF/Home

20 questions

I have just found out an interesting webpage: http://www.20q.net/

It’s sort of an expert system, which is reasoning based on human’s answer given for specific questions. Questions are quite generic. While the system is self-learning, the more people play the game, the more accurate results are.

Based on the authors’ information the accuracy is about 80%. Check it out and have fun!

Netbeans 6.0 Mobility – FileBrowser

Netbeans 6.0 gives really nice support for developing Java Micro Edition applications. It provides some useful classes which are not part of standard JME profiles.
One of them is class: org.netbeans.microedition.lcdui.pda.FileBrowser.
It provides file browser for mobile phone implementing JSR-75. It looks fine but there is a bug in it. Method getSelectedFileURL() returns incorrect value, e.g.: file:///E:/myfolder//myfile.mp3 instead of file:///E:/myfolder/myfile.mp3
Removing manually last extra slash fixes the problem.

Google’s Krakow Open House

Today Google opened its office in Krakow for non-googlers.

There was a TechTalk given by Michal Zalewski on “The evolution of web security: The unexpected pitfalls of web application programming”. It was mainly about cross-site-scripting techniques and browsers security gaps. The event was located at AGH University of Science and Technology.

After it every attendee could visit Google’s office in Krakow. It looks nice… rather like a big apartment with bunch of LCD monitors than usual office space. The office is located at Krupnicza Street.

Google is planning to expand Krakow’s office to 80 people till the end of 2008.