Archive for the 'Java' Category

May 22 2008

Eclipse DemoCamp is coming to town

Published by under Eclipse,IT,Java

Eclipe 3.4 Ganymede It looks like Eclipse DemoCamp will come to Krakow sometime in June. The agenda is not available now, but I hope it will be interesting. There is a lot of exciting stuff coming with Eclipse 3.4 (I’m currently working with Eclipse 3.4 M7 platform and looking forward for final release that is coming in end of June).

Agenda, specific date and place should be announced here

No responses yet

Apr 18 2008

NetBeans World Tour 2008 in Krakow

Published by under IT,Java

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 ;-)

No responses yet

Mar 15 2008

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

Published by under Eclipse,IT,Java

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.

No responses yet

Feb 28 2008

Jakarta BCEL

Published by under IT,Java

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: <code>
 * System.out.println("About to call: METHOD_NAME METHOD_SIGNATURE");
 * </code>
 * 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/

One response so far

Feb 12 2008

AppFuse – first impression

Published by under Java

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

No responses yet

Dec 17 2007

Netbeans 6.0 Mobility – FileBrowser

Published by under IT,Java

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.

One response so far

Sep 25 2007

Spring remoting quickstart

Published by under IT,Java

I have spent a lot of time on configuring Spring remoting properly (mostly because of problems with DTD).
To expose business logic via for example XFire Web Services we have to define context and listeners in web.xml, example:

<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<!DOCTYPE web-app
PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN”

“http://java.sun.com/dtd/web-app_2_3.dtd”>
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.util.Log4jConfigListener
</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>
<servlet>
<servlet-name>XFireServlet</servlet-name>
<servlet-class>org.codehaus.xfire.spring.XFireSpringServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/servlet/XFireServlet/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>

Configuration of beans that are going to be exposed via WS is stored in separate file, in this case in applicationContext.xml. Example of the content of the file:

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE beans PUBLIC “-//SPRING//DTD BEAN//EN” “http://www.springframework.org/dtd/spring-beans-2.0.dtd”>
<beans>
<bean class=”org.springframework.web.servlet.handler.SimpleUrlHandlerMapping”>
<property name=”urlMap”>
<map>
<entry key=”/WorkflowRegister”>
<ref bean=”workflowRegister”/>
</entry>
</map>
</property>
</bean>
<bean id=”workflowRegister” class=”org.codehaus.xfire.spring.remoting.XFireExporter”>
<property name=”serviceFactory”>
<ref bean=”xfire.serviceFactory”/>
</property>
<property name=”xfire”>
<ref bean=”xfire”/>
</property>
<property name=”serviceBean”>
<ref bean=”worklfowRegisterBean”/>
</property>
<property name=”serviceClass”>
<value>pl.edu.agh.gemini.adds.core.IWorkflowRegister</value>
</property>
</bean>
<bean id=”worklfowRegisterBean” class=”pl.edu.agh.gemini.adds.core.WorkflowRegister” factory-method=”getInstance” />
<import resource=”classpath:org/codehaus/xfire/spring/xfire.xml”/>
</beans>

As you can see defining new WS which is based on already implemented bean requires just few lines of XML. Business logic is totally separated from the way of exposing it. No changes are required in logic to expose it as Web Service! Also changing transport layer from XFire to e.g. Burlap/Hessian/RMI is just a matter of configuration in those two files.

Dependencies for Spring remoting (part of Maven pom.xml):

<dependencies>
<dependency>
<groupId>pl.edu.agh.gemini.adss</groupId>
<artifactId>adsscore</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>pl.edu.agh.gemini.adss</groupId>
<artifactId>adsscoreapi</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-remoting</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.codehaus.xfire</groupId>
<artifactId>xfire-jaxb2</artifactId>
<version>1.2-RC</version>
</dependency>
<dependency>
<groupId>org.codehaus.xfire</groupId>
<artifactId>xfire-spring</artifactId>
<version>1.2-RC</version>
</dependency>
<dependency>
<groupId>org.codehaus.xfire</groupId>
<artifactId>xfire-java5</artifactId>
<version>1.2-RC</version>
</dependency>
</dependencies>

Application can be simply deployed as war file in servlet container (e.g. Tomcat), no J2EE application server is required.

Have fun with Spring remoting!

No responses yet

May 04 2007

Injecting EJB 3.0 beans into Struts 2.0

Published by under IT,Java

EJB 3.0 provides easy bean injection. While developing web layer in Struts 2.0 you can use similar mechanism as well. Struts 2.0 is using Spring libraries for implementing Inversion of Control design pattern.

EJB 3.0 is based on using Java 1.5 annotations. It simplifies deployment process.

Let define example Session Bean.

@Stateless(mappedName=”ejb/EmployeeManager”)
public class EmployeeManagerSB implements IEmployeeManager {

public Long createAccount(String loginName) {
// Implementation of creating an account…
}

}

It implements interface:

@Remote
@Local

public interface IEmployeeManager {

Long createAccount(String loginName);

}

To use EmployeeManager session bean in Struts 2.0 reference to this object has to be retrieved.

Let define Struts action class which will use EmployeeManager session bean.

@Validation()
public class NewEmployeeAction extends ActionSupport {

private IEmployeeManager employeeManager;
private String loginName;
private long id;
private String redirectURL;

public String execute() throws Exception {
Long id = this.employeeManager.createAccount(this.loginName);
this.setId(id.longValue());
return SUCCESS;
}

public IEmployeeManager getEmployeeManager() {
return employeeManager;
}

public void setEmployeeanager(IEmployeeManager employeeManager) {
this.employeeManager = employeeManager;
}

public String getLoginName() {
return loginName;
}

@RequiredStringValidator(message = “Please enter a login name”, trim = true)
public void setLoginName(String loginName) {
this.loginName = loginName;
}

public long getId() {
return id;
}

public String getRedirectURL() {
return redirectURL;
}

public void setRedirectURL(String redirectURL) {
this.redirectURL = redirectURL;
}

}

Framework is taking care of injecting proper object while creating this action object. In Struts 2.0 the only thing that has to be done to do this is defining it in applicationContext.xml configuration file.

<jee:jndi-lookup id=”employeeManager” name=”ejb/EmployeeManager“>

<bean id=”newEmployeeAction” class=”pl.edu.agh.sius2007.jspynet.struts.NewEmployeeAction”>
<property name=”employeeManager” ref=”employeeManager”>
</bean>

The only configuration in Struts is defining two beans.

  • employeeManager which will be retrieved from JNDI;
  • newEmployeeAction which is Struts action.

employeeManager bean will be retrieved automatically and injected into newEmployeeAction.

No responses yet

« Prev