Tuesday, January 31, 2006

Unexpected side-effect

Learning to new features of Java 5 I've discovered new way to call the main method. I know, I'm not first but it's nice to see things in consequences. From now on I'll abandon good but old
 static void main (String [] args) {...}
I'll start to use
static void main (String ... args){...}
instead. It's a sing of a new era established by Java 5 ...

Project management ...

It's like I can see at out company. When we start to do out business we were a small firm ran by 3 so-called managers and the rest was a group of developers. These days, we have 4 level executive system :-( I'm directed by number of people which I don't know personally ...
LFO's Weblog

Axis rules ! :-)

Yesterday evening (as I always do what I like to on evenings and weekdns) I for a first time met Apache Axis. And I was really pleased by it. It's definitely the library as library should be. Well documented, supplied with all necessary binding (such as to ant, to log4j, to junit ...), so to establish connection to the webservice took me just a several minutes. And I've been poorly exapecting hours :-) Well, thank you very much Apache guys !!!

Monday, January 30, 2006

Put it to the test :-)

Question:
12. Which of the following may legally appear as the new type (between the parentheses) in a cast
operation?
A. Abstract classes
B. Final classes
C. Primitives
D. All of the above
Answer:
12. E. Any type, including classes with any kind of modifier, may appear inside the parentheses
of a cast.

And I was wrong again, because I overlooked the E choice :-)))

Eclipse java compilation ?!

I found something strange conrens Eclipse. The point is, that Eclipse compile even invalid java code - and, somehow runnable. Take a look on these source files:


package test;

public interface IntA {
void A();
void B();
void C();
void D();
void E();
}


package test;

public class ClsB implements IntA{

public void A() {
System.out.println("A");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Howdyyyy");
IntA a = new ClsB();
a.A();
// a.B(); when uncommented, class doesn't compile
}

}

All right. This class would be compilable even when is marked as "abstract". So, any attempt to compile with javac results to:


K:\UFO_G3\workspace\test>c:\jdk5\bin\javac.exe test/*.java
test/ClsB.java:3: test.ClsB is not abstract and does not override abstract metho
d E() in test.IntA
public class ClsB implements IntA{
^
1 error

as expected. But when in Eclipse, everything is OK but you can't even run such class with this result:

Nebylo možno načíst třídu prostředí Java: java.lang.UnsupportedClassVersionError: test/ClsB (Unsupported major.minor version 49.0)
And I'm asking: why is possible to compile an invalid class ? Why Eclipse using some internal compiler with a non-standard results ? Perhaps that's the reason why I'm using eclipse only as an editor and compiling classes with the Ant ...

Troubles with Wicket vs. Glassfish

Weekend is gone and here is a resultsheet of my work, study, tests, workarounds etc.
First of all - Java 6 Mustang has limited backward compatibility. I can't say more on this right now, but based on my experiments, it can't work with Java 1.3 classes. That's quite surprising ! I'll try to get more on the subject.
I didn't succeed to improve performance of the EJB with complex mapping. Persistence provider is still loading whole database with a sign of some kind of recursion when I'm trying to get just entity of one type (for example an employee). I've tried almost everything ! Bad luck though ...
All right, the next task was preparation for the certification. I've accomplished 3 chapters (out of 15 total) and my test ratio is cca. 90%. That's OK as required ratio is appriximately 60%. But what I hate about the certification test are questions like - given interface A with five methods and class B that claims to implement interface A but actually isn't implementing any method, what will be result of compilation attempt. a) the class will not be compiled b) ... c) ... d) class will be compiled but can't be instantioned e)class will be abstract. And correct answer is d) and e). But why ?! On Java 5 this example works and class is even runnable (as long as you don't call methods inherited from the interface). On JDK 4 it fails to compile at all. So what is conclusion ?!
Wicket - Wicket is excelent. So for I like it very match, but for reason unknown Wicket is in collision with Glassfish. When I deploy my Wicket application onto the Glassfish for a fiveth time Glassfish crash with strange message like "PrmGen" out of memory ... Anyway, Glassfish has a serious problem with webservices. Webservice with method that returns not elemental objects (not Strings, Lists ...) cause Glassfish to crash or if I'm lucky it just cause weird behaviour of the Glassfish ... Nobody knows why and I don't mind to find it. So I'll go to the Tomcat. Tomcat is a proven server so maybe, I'll be more lucky with this one.

Friday, January 27, 2006

On EJB3 again

So, recently I have posted the whole test project on my website. It is now available through this link so you can grab it if you want. This piece of code is designed to run on GlassFish build 34 and as a backend database it uses Oracle XE with HR scheme enabled.
Yesterday evening I successfuly overode annotations by xml descriptors so now I know how to do it. This is not a magic - just use your EJB 2.1 style descriptors and everything will be just fine. For more see example of EJB3Servlet - there is a call to fooQeueue that is actuelly mapped to testQueue.
What is now bear in my mind is perfomance of entity beans - it's back to the root problem because I didn't solve it yet and this problem occured in the begging of my work. I hope the persitence layer is somehow "confused" by so many circular mappings. I'll try to eliminate some of them (for example mappimg emloyee-manager department-manager and so on) and hope it helps.
Last week I found a great community of same thinking people around EJB3 at glassfish forum. They helped me to solve my initial problem with message driven bean (the problem when I forgot to implement MessageListener interface). Yesterday I posted there another problem and hopfuly they'll help to find some solution. It's about NativeNamedQuery but you better see for yourself here.
I don't know exactly what I'm goind to do next but I'll choose from these:
  • As part my certification preparation, improve example application by adding more features of Java 5.
  • Add Wicket support (even without any Java 5 or EJB3 feature) just to get familiar with this powerful framework
  • Try out Caché database. This "post relational" database has many uniques - it doesn't require object-relational mapping as data are stored as objects ! It would be fun :-)
    As you can see, I have a lot of challenges ahead ... And no time to waste :-)
  • Wednesday, January 25, 2006

    MDB problem solved - I'm moving for another challenge

    it maybe sounds like I'm talking only about my EJB3 presentation (what is almost truth :-)) but now I solved last crucial problem - message driven bean works for now, so I can stick myself for another. The last thing I want to show is NamedNativeQuery and then - hasta la vista EJB 3 - I will continue working to explore some new feature of Java 6 (Mustang) and I'll go for certification. If you'e curious what was the problem, well, it was really tricky byt definitely it was my fault. I forgot to implement MessageListenetr interface and every message driven bean must implement such interface. I read the documentation only once and very briefly so I overlooked the sentence that message driven bean should be annotated as @MessageDriven and should implement MessageListener interface too. Next time I'll be reading documentation carefully ...

    Monday, January 23, 2006

    Examples strike back :-)

    Ok, here we go. First of all, prerequisition:

  • EJB3 container (glassfish is used in this scenario)
  • Database (Oracle XE with activated HR scheme)
  • Ant
  • A lot of time :-)
    If you've downloaded all the software required, you can move on to second stage. First of all let's create entity beans. These're plain old java objects (POJO) with some annotations. I've created two version. One that contain full annotation, including relationships and the second one (with prefix Bare) that is relationshipless. Here is snapshot of class Employees with full links to other tables:

    package org.defectus.ejb3.ic2.entity.complex;

    import java.io.Serializable;
    import java.util.Collection;

    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.ManyToOne;
    import javax.persistence.NamedQuery;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;

    @Entity
    @Table(name = "EMPLOYEES")
    @NamedQuery(name = "selectAllEmps", query = "select object(o) from Employees o")
    public class Employees implements Serializable {
    private static final long serialVersionUID = 1987305452306161213L;

    private Double commissionPct;

    private String email;

    private Long employeeId;

    private String firstName;

    private String lastName;

    private String phoneNumber;

    private Double salary;

    private Departments department;

    private Employees manager;

    private Collection employees;

    private Jobs jobs;

    private Collection departments;

    public Employees() {
    }

    public Employees(String email, Long employeeId, Jobs jobs, String lastName) {
    this.email = email;
    this.employeeId = employeeId;
    this.jobs = jobs;
    this.lastName = lastName;
    }

    @Column(name = "COMMISSION_PCT")
    public Double getCommissionPct() {
    return commissionPct;
    }

    public void setCommissionPct(Double commissionPct) {
    this.commissionPct = commissionPct;
    }

    @Column(name = "EMAIL", nullable = false)
    public String getEmail() {
    return email;
    }

    public void setEmail(String email) {
    this.email = email;
    }

    @Id()
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "EMPLOYEES_SEQ")
    @Column(name = "EMPLOYEE_ID", nullable = false)
    public Long getEmployeeId() {
    return employeeId;
    }

    public void setEmployeeId(Long employeeId) {
    this.employeeId = employeeId;
    }

    @Column(name = "FIRST_NAME")
    public String getFirstName() {
    return firstName;
    }

    public void setFirstName(String firstName) {
    this.firstName = firstName;
    }

    @Column(name = "LAST_NAME", nullable = false)
    public String getLastName() {
    return lastName;
    }

    public void setLastName(String lastName) {
    this.lastName = lastName;
    }

    @Column(name = "PHONE_NUMBER")
    public String getPhoneNumber() {
    return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
    this.phoneNumber = phoneNumber;
    }

    @Column(name = "SALARY")
    public Double getSalary() {
    return salary;
    }

    public void setSalary(Double salary) {
    this.salary = salary;
    }

    @ManyToOne()
    @JoinColumn(name = "DEPARTMENT_ID", referencedColumnName = "DEPARTMENTS.DEPARTMENT_ID")
    public Departments getDepartment() {
    return department;
    }

    public void setDepartment(Departments departments) {
    this.department = departments;
    }

    @ManyToOne()
    @JoinColumn(name = "MANAGER_ID", referencedColumnName = "EMPLOYEES.EMPLOYEE_ID")
    public Employees getManager() {
    return manager;
    }

    public void setManager(Employees manager) {
    this.manager = manager;
    }

    @OneToMany()
    public Collection getEmployees() {
    return employees;
    }

    public void setEmployees(Collection employees) {
    this.employees = employees;
    }

    public Employees addToEmployeesCollection(Employees employees) {
    getEmployees().add(employees);
    employees.setManager(this);
    return employees;
    }

    public Employees removeFromEmployeesCollection(Employees employees) {
    getEmployees().remove(employees);
    employees.setEmployees(null);
    return employees;
    }

    @ManyToOne()
    @JoinColumn(name = "JOB_ID", referencedColumnName = "JOBS.JOB_ID")
    public Jobs getJobs() {
    return jobs;
    }

    public void setJobs(Jobs jobs) {
    this.jobs = jobs;
    }

    @OneToMany()
    public Collection getDepartments() {
    return departments;
    }

    public void setDepartments(Collection departments) {
    this.departments = departments;
    }

    public Departments addToDepartmentsCollection(Departments departments) {
    getDepartments().add(departments);
    departments.setManager(this);
    return departments;
    }

    public Departments removeFromDepartmentsCollection(Departments departments) {
    getDepartments().remove(departments);
    departments.setManager(null);
    return departments;
    }
    }
    As you can see, it's very straightward - nothing is hidden and, there is no logic ! No methods, except for constructor. But if you take a closer look on OneToMany mapping you can realize that there must be some kind of executive code out there. And it certainly is. Entity manager hides further logic behind the Collection of Departments. This logic is responsible for lazy fetching of Departments. As long as you run this code inside the container (ie. Glassfish) everything is all right but once you try to send such POJO over let's say webservice you can encounter a serious problem. As far as I'm aware there's no way how to detach such POJO and attached POJO can't be detached by SOAP message creator. And that's the reason why I have created second version of EJBs. In the next example you'll see the same table (Employees) but without any relationship included:

    package org.defectus.ejb3.ic2.entity.bare;

    import java.io.Serializable;

    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.EntityResult;
    import javax.persistence.FieldResult;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.NamedNativeQuery;
    import javax.persistence.NamedQuery;
    import javax.persistence.SqlResultSetMapping;
    import javax.persistence.Table;

    @Entity
    @Table(name = "EMPLOYEES")
    @NamedQuery(name = "selectAllEmps", query = "select object(o) from Employees o")
    @NamedNativeQuery(name = "selectNativeEmps", query = "SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY FROM EMPLOYEES WHERE EMPLOYEE_ID = ?", resultSetMapping = "employeeNamedMapping", resultClass=org.defectus.ejb3.ic2.entity.bare.BareEmployees.class)
    @SqlResultSetMapping(name = "employeeNamedMapping", entities = { @EntityResult(entityClass = org.defectus.ejb3.ic2.entity.bare.BareEmployees.class, fields = {
    @FieldResult(name = "employeeId", column = "EMPLOYEE_ID"), @FieldResult(name = "firstName", column = "FIRST_NAME"),
    @FieldResult(name = "lastName", column = "LAST_NAME"), @FieldResult(name = "salary", column = "SALARY") }) /*, discriminatorColumn="disc")*/})
    public class BareEmployees implements Serializable {
    private static final long serialVersionUID = 1987305452306161213L;

    private Double commissionPct;

    private String email;

    private Long employeeId;

    private String firstName;


    private String lastName;

    private String phoneNumber;

    private Double salary;

    private Long departments;

    private Long employees;

    private String jobs;

    public BareEmployees() {
    }

    public BareEmployees(String email, Long employeeId, String jobs, String lastName) {
    this.email = email;
    this.employeeId = employeeId;
    this.jobs = jobs;
    this.lastName = lastName;
    }

    @Column(name = "COMMISSION_PCT")
    public Double getCommissionPct() {
    return commissionPct;
    }

    public void setCommissionPct(Double commissionPct) {
    this.commissionPct = commissionPct;
    }

    @Column(name = "EMAIL", nullable = false)
    public String getEmail() {
    return email;
    }

    public void setEmail(String email) {
    this.email = email;
    }

    @Id()
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "EMPLOYEES_SEQ")
    @Column(name = "EMPLOYEE_ID", nullable = false)
    public Long getEmployeeId() {
    return employeeId;
    }

    public void setEmployeeId(Long employeeId) {
    this.employeeId = employeeId;
    }

    @Column(name = "FIRST_NAME")
    public String getFirstName() {
    return firstName;
    }

    public void setFirstName(String firstName) {
    this.firstName = firstName;
    }

    @Column(name = "LAST_NAME", nullable = false)
    public String getLastName() {
    return lastName;
    }

    public void setLastName(String lastName) {
    this.lastName = lastName;
    }

    @Column(name = "PHONE_NUMBER")
    public String getPhoneNumber() {
    return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
    this.phoneNumber = phoneNumber;
    }

    @Column(name = "SALARY")
    public Double getSalary() {
    return salary;
    }

    public void setSalary(Double salary) {
    this.salary = salary;
    }

    @Column(name = "DEPARTMENT_ID")
    public Long getDepartments() {
    return departments;
    }

    public void setDepartments(Long departments) {
    this.departments = departments;
    }

    @Column(name = "MANAGER_ID")
    public Long getEmployees() {
    return employees;
    }

    public void setEmployees(Long employees) {
    this.employees = employees;
    }

    @Column(name = "EMPLOYEES.JOB_ID")
    public String getJobs() {
    return jobs;
    }

    public void setJobs(String jobs) {
    this.jobs = jobs;
    }
    }
    In this example you perhaps lack the relationship annotations and structures but a native query has been add. Note that EJB3 easily fall to annotation defaulting. This means that even if you omit annotate class field as Column deployer will find that in related table is matching column and will bind tthe column and the filed together.
    And now for something completely different :-) Let's take look on a facade class. Its purpose is to create an interface and cover all the logic behind. There're some important things you should be noticed about. Class is annotated as Stateless - it means that class is stateless session bean. Also, class has interceptor. This feature will be discussed later. In a body of the class is something called EntityManager annotated with @PersistenceContext. It indicates that class uses persistence and container should inject EntityManager to given attribute. Note that this way of instructing container to inject EntityManager is not the only one way how to do it and the other ways are perhaps even better (consider for example usage of EntityManagerFactory). pu1 specified which persitence context should be used. Later in the code you'll see some methods, which, as I hope, should be easy to understand.

    package org.defectus.ejb3.ic2.session;

    import java.sql.Timestamp;
    import java.util.Date;
    import java.util.List;

    import javax.ejb.Interceptors;
    import javax.ejb.Stateless;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;

    import org.defectus.ejb3.ic2.entity.bare.BareDepartments;
    import org.defectus.ejb3.ic2.entity.bare.BareEmployees;
    import org.defectus.ejb3.ic2.entity.bare.BareJobs;
    import org.defectus.ejb3.ic2.entity.bare.BareLogs;
    import org.defectus.ejb3.ic2.entity.complex.Departments;
    import org.defectus.ejb3.ic2.entity.complex.Employees;
    import org.defectus.ejb3.ic2.entity.complex.Locations;

    @Stateless (mappedName="ejb/DataFacade")
    @Interceptors( { org.defectus.ejb3.ic2.session.DataInterceptor.class })
    public class DataFacadeBean implements DataFacade {
    @PersistenceContext(unitName = "pu1")
    private EntityManager _entityManager;

    public DataFacadeBean() {
    }

    public EntityManager getEntityManager() {
    return _entityManager;
    }

    public void setEntityManager(EntityManager entityManager) {
    _entityManager = entityManager;
    }

    public List findDept(String name) {
    @SuppressWarnings(value = { "unchecked" })
    List deps = getEntityManager().createQuery(
    "select object(o) from Departments o where o.departmentName=:name").setParameter("name", name).getResultList();
    return deps;
    }

    public List findAllDept() {
    @SuppressWarnings(value = { "unchecked" })
    List deps = getEntityManager().createQuery("select object(o) from Departments o").getResultList();
    return deps;
    }

    public Departments createDepartment(String departmentName, Long locationId) {
    final Departments dept = new Departments(departmentName);
    Locations location = getEntityManager().find(Locations.class, locationId);
    dept.setLocation(location);
    getEntityManager().persist(dept);
    return dept;
    }

    public BareLogs createLog(String message) {
    final BareLogs log = new BareLogs(message, new Date());
    getEntityManager().persist(log);
    return log;
    }

    public List findAllComplexEmployees() {
    @SuppressWarnings(value = { "unchecked" })
    List emps = getEntityManager().createNamedQuery("selectAllEmps").getResultList();
    return emps;
    }

    public List findAllBareEmployees() {
    @SuppressWarnings(value = { "unchecked" })
    List emps = getEntityManager().createQuery("select object(o) from BareEmployees o").getResultList();
    return emps;
    }

    public List findBareEmployees2() {
    @SuppressWarnings(value = { "unchecked" })
    List emp = getEntityManager().createNamedQuery("selectNativeEmps").setParameter(1,101).getResultList();
    return emp;
    }

    public BareJobs findBareJobs(String jobId) {
    return getEntityManager().find(BareJobs.class, jobId);
    }

    public BareEmployees findBareEmployee(Long emplId) {
    return getEntityManager().find(BareEmployees.class, emplId);
    }

    public BareDepartments findBareDepartment(Long depId) {
    return getEntityManager().find(BareDepartments.class, depId);
    }

    public List findAllDepartments() {
    @SuppressWarnings(value = { "unchecked" })
    List deps = getEntityManager().createNamedQuery("selectAllDeps").getResultList();
    return deps;
    }

    public Employees createEmployee(Double comm, Long deptno, String email, String firstName, String lastName,
    Timestamp hiredate, String job, Double sal) {
    final Employees emp = new Employees();
    Departments dep = getEntityManager().find(Departments.class, deptno);
    emp.setCommissionPct(comm);
    emp.setDepartment(dep);
    emp.setEmail(email);
    emp.setFirstName(firstName);
    emp.setLastName(lastName);
    emp.setSalary(sal);
    getEntityManager().persist(emp);
    return emp;
    }

    public void updateEntity(Object entity) {
    getEntityManager().merge(entity);
    }

    public void deleteEntity(Object entity) {
    final EntityManager em = getEntityManager();
    em.remove(em.merge(entity)); // interesting way how to delete entity of any type
    }

    public void refreshEntity(Object entity) {
    getEntityManager().refresh(entity);
    }

    public void shutdown() {
    getEntityManager().close();
    }


    }
    For the bean a remote interface is needed. To create one you have to annotate appropriate interface as @Remote and make the class above implement such interface. Note that the interface can be Remote, Local but can't be both.

    package org.defectus.ejb3.ic2.session;

    import java.sql.Timestamp;
    import java.util.List;

    import javax.ejb.Remote;
    import javax.persistence.EntityManager;

    import org.defectus.ejb3.ic2.entity.bare.BareEmployees;
    import org.defectus.ejb3.ic2.entity.bare.BareJobs;
    import org.defectus.ejb3.ic2.entity.bare.BareLogs;
    import org.defectus.ejb3.ic2.entity.complex.Departments;
    import org.defectus.ejb3.ic2.entity.complex.Employees;

    @Remote
    public interface DataFacade {

    public abstract EntityManager getEntityManager();

    public abstract void setEntityManager(EntityManager entityManager);

    public abstract List findAllDept();

    public abstract List findDept(String name);

    public abstract Departments createDepartment(String departmentName, Long locationId);

    public abstract BareLogs createLog(String message);

    public abstract List findAllBareEmployees();

    public abstract BareJobs findBareJobs(String jobId);

    public abstract BareEmployees findBareEmployee(Long emplId);

    public abstract List findAllComplexEmployees();

    public abstract List findAllDepartments();

    public abstract Employees createEmployee(Double comm, Long deptno, String email, String firstName, String lastName,
    Timestamp hiredate, String job, Double sal);

    public abstract void updateEntity(Object entity);

    public abstract void deleteEntity(Object entity);

    public abstract void refreshEntity(Object entity);

    public abstract void shutdown();

    }
    Interceptor is something that is called before any particular call to method of intercepted bean. From the code below it's easy to understand the way of interception

    package org.defectus.ejb3.ic2.session;

    import javax.ejb.AroundInvoke;
    import javax.ejb.InvocationContext;

    import org.defectus.ejb3.ic2.entity.bare.BareEmployees;

    public class DataInterceptor {

    @AroundInvoke()
    public Object myBeanInterceptor(InvocationContext ctx) throws Exception {
    if (ctx.getMethod().getName().equals("findDept")) {
    String name = (String) ctx.getParameters()[0];
    Object[] o = new Object[1];
    o[0] = name;
    ctx.setParameters(o);
    } else if (ctx.getMethod().getName().equals("findBareEmployee")) {
    Long id = (Long) ctx.getParameters()[0];
    if (id.longValue() == 888)
    return new BareEmployees(null, null, null, "Who wants to know ? :-)");
    }
    return ctx.proceed();
    }
    }
    The second IF is interesting - because it interrupts call to underlaying method so the method is actually not called at all ! This means - when you ask the bean for employee 888 interceptor returns one without even calling datafacade bean. Very nice. Note that specification have changed and Intercaption resides in different package (but it works the same way as before).In the next class you'll see is a servlet that acts as data provider to AJAX page. Although servlets are not annotated (you must provide valid web.xml) you can use annotations though. Annotation @EJB instructs server to inject reference to EJB. The rest of the class is servlet as usual. Just for your information, the last Java EE 5 specification prohibit usage of stateful bean in servlets.

    package org.defectus.ejb3.ic2.ws;

    import java.io.IOException;
    import java.util.Map;

    import javax.ejb.EJB;
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.defectus.ejb3.ic2.entity.bare.BareEmployees;
    import org.defectus.ejb3.ic2.session.DataFacade;

    public class DataProvider extends HttpServlet {
    private static final long serialVersionUID = -7542313195870441831L;

    @EJB(name = "org.defectus.ejb3.ic2.session.DataFacade")
    private DataFacade data;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    ServletOutputStream o = res.getOutputStream();
    res.setContentType("text/xml");
    res.setCharacterEncoding("utf-8");
    String action = null;
    Long id = null;
    try {
    action = req.getParameter("action");
    } catch (Exception e) {
    o.println("");
    o.println("");
    o.println("
    Invalid request !!! No action provided
    ");
    o.println("
    ");
    o.println("
    ");
    o.flush();
    o.close();
    return;
    }
    Map params = req.getParameterMap();
    if (action.equals("singleEmployee")) {
    printSingleEmployee(o, Long.getLong((String) params.get("id")));
    } else if (action.equals("employeeList")) {
    printEmployeeList(o);
    }
    }

    private void printSingleEmployee(ServletOutputStream o, Long value) throws IOException {
    o.println("");
    o.println("");
    o.println("
    " + data.findBareEmployee(value).getLastName() + "
    ");
    o.println("
    ");
    o.println("
    ");
    o.flush();
    o.close();
    }

    private void printEmployeeList(ServletOutputStream o) throws IOException {
    o.println("");
    o.println("");
    o.println("");
    o.println("
    ");
    o.println("
    ");
    o.flush();
    o.close();
    }
    }
    And that's all for now. I'll continue later and try to cover another techniques related to EJB 3.
  • Thursday, January 19, 2006

    Examples

    It maybe looks like don't keep my faith and I want to change it. I promised to put here some examples and I'll finally do. So tonight, you can expect some covering basic practices of EJB3. At least because right now I just playning with AJAX.
    My next task ? To get a Java 5 certification. Just another 2 tough months.

    Wednesday, January 18, 2006

    Breaking the ice

    So far so good. Yesterday I've finished my persistance comparison with interesting result. To get all employees took 13 seconds using complex O-R mapping with EJB3 but only 70 milliseconds using bare mapping (without relations ie. to get employees means to get data from employees table). I don't know what cause such performance degradation yet but I'll try to find out.
    As my second task I've tried interceptors. Pretty feature ! You can intercept any call to EJB (stateless or stateful) and add any functionality to it or supress execution of EJB at all. It's some kind of AOP but without AOP or filter known from servlets. For example at my application I add interceptor which check if you want to get an employee named "Ondra". If so, it will log such attempt and returns an empty Employees object (so one can't get info on me :-))
    Now I'm ready to write data provider servlet - the one which will return data to OpenRico AJAX ... and perhaps continue to fix performance of the complex EJB3 mapped entities.

    Tuesday, January 17, 2006

    Let's do it all over again (for persistance reasons)

    Hmm, it's sad but it's true. Firstly what makes me to rebuild the application. Till midnight everything went very well but then I realized, that performance of my example application is even worse that terrible ! As I mentioned before, I use Oracle's HR database. There are roughly 100 employees, some departmets, some countries etc. but initial load of such application was 20 almost seconds ! So I decided to use lazy fetching. Good idea but annotation @OneToMany(fetch = FetchType.LAZY) is just a suggestion - and for reason unknown, Toplink didn't follow it. I'm just a humble developer so I made up my mind and download latest build of Glassfish - b33 just to try my luck. You can't imagine my surprisal when I wasn't able to compile the project. Toplink has been turned upside-down and many annotation was deleted, renamed or rearranged. More on this here. After all I know what I'll be doing tonight :-)
    It's 1:10 pm and I've made the changes. Piece of cake I must admit. So, @Id no longer contain parameters, @GeneratedValue is newcomer (can be used with every generated field) and everyone is shinny happy. After this small intermezzo I will continue trying to fix the performance issue. All I need to do is to find a balance between code simplicity and application response time.

    Monday, January 16, 2006

    JSF 1.2 doesn't work on Glassfish b31 ?

    It seems to me true. I've tried hard to make it work and accomplish my presentation showing JSF 1.2 but it just doesn't work. Any attempt to call or ahow anything from JSF fails with uknown exception. Even supplied examples fail the same way.
    So I decided to create rich servlet accompanying servlet 2.5 features with some JAXB and on client side uses OpenRico AJAX framework. Perhaps it sounds as tough task, but actually it isn't. Integrations will be very easy as JAXB uses annotations as well as servlet, so everything I will need to do is to annotate my entity classes and add annotation to servlet. And of course, publish several AJAX methods ...
    Anyway, this weekend I even had to deal with camplex EJB3 entity mapping. Project Dali is really buggy (unable to create entity classes) so used JDeveloper 10.1.3. It created entities but ManyToMany mapping is invalid and ManyToOne dosn't conform specification. I didn't solve the first problem but the second one can be easily fixed by editing field annotations to contain only OneToMany (delete the JoinColumn annotation) pointing to referenced class and counterpart class should use JoinColumn annotation together with bare ManyToOne.

    @ManyToOne()
    //targetEntity=org.defectus.ejb3.ic2.entity.Departments.class)
    @JoinColumn(name = "EMPLOYEES.DEPARTMENT_ID", referencedColumnName = "DEPARTMENTS.DEPARTMENT_ID")


    @OneToMany(targetEntity=org.defectus.ejb3.ic2.entity.Employees.class)
    //@JoinColumn(name="EMPLOYEES.DEPARTMENT_ID", referencedColumnName="DEPARTMENTS.DEPARTMENT_ID")
    Hope that is clear - commented parts are these which were generated by JDeveloper but were not valid.

    Saturday, January 14, 2006

    Presentation partly done

    So, my presentation is almost done and can concetrate on examples. I'd like to present complete end to end scenario and show as much of new technoligy, as it will be possible. Perhaps you've seen my previous article and the examples seems to you be some kind of weird. Yes, these examples has been made quite quickly, so the next one will cover more and more of EJB3. I will post here example of ant build file, becasuse deployment is important part of EJB3. During deployment a lot of things take place - but invisibly. Did I mention that you don't need ejb-jar.xml at all ? Cool ! Or you can enjoy benefits of EJB3 persistency outside of application server - ideal for testing.
    Ok, next post will be mostly yellow, as I'm going to post here code of my examples. Hope it helps to anybody ...

    Friday, January 13, 2006

    Presentation - work in progress

    Yesterday I've started to write my presentation concerning EJB3. It covers more then just this - it's about whole Java EE 5 technologies including JAX WS, servlets, JSP, Common annotaton etc. Actually I have six pages and working examples.
    Basically I can say - EJB3 is all about annotations. But annotations are processed by application server or application client so in the end, on background it works similary to EJB 2.1. The main difference is in development point of view. You, as developer, don't need to care whenever you have all interfaces and stub classes, everything is done on deployment. Is very interesting to see what was done with our project after deployment. Just take a closer look to deployment directory and you'll see, that nothing important has changed.
    So stop just talking and watch this example:
    package com.blogspot.deftech.ejb3;
    @javax.ejb.Stateless (name="ejb/foo")
    public class FooBean {
    public String getString (String stringIn) {
    return "You said " + stringIn + " ... Unbelievable !";
    }
    }
    For such class we need an interface - lets create it (nothing complicated)
    package com.blogspot.deftech.ejb3;
    @javax.ejb.Remote
    public interface Foo {
    public String getString (String stringIn);
    }

    As you can see, to create ejb is very very simple. Of course, this one is the simpliest one, but the basic concept is clear. Use annotation and don't care. Everything else will be done by deployer or server itself. In other words - concentrate on business logic, not on support stuff.
    To generate server-side client is easy as one two three :-). Look at this piece of code:
    package com.blogspot.deftech.ejb3;
    public class FooTest {
    @javax.ejb.EJB (name="ejb/foo")
    private Foo fooObject;

    public static void main (String [] args) {
    FooTest test = new FooTest();
    test.run();
    }

    private void run () {
    System.out.println(fooObject.getString ("1+1=2"));
    }
    }
    To deploy such code you need to compile it and pack it into *.jar file. More on this later today. Be patient ...
    Ok this one will not work, but if you make a servlet based on this skeleton, you'll see, how application server literaly injects instance of class Foo to member variable fooObject. There is even another trick like. Let's examine this example:
    package com.blogspot.deftech.ejb3;

    public class ResourceExample {
    javax.sql.DataSource ds = null;

    @Resource(name="jdbc/OracleXE")
    public void setDataSource javax.sql.DataSource value) {
    ds = value;
    }
    }
    In this piece of code application server will inject JNDI resource into setter named setDataSource. Really clean and elegant way how to work with JNDI. No more JNDI lookups, no more narrowing references. But still keep in mind, that on background nothing changes ! The only thing which has changed is that the boring part of work is done by server ... Later I'll post here example of entity beans, which are even more interesting. And also a small example of Web service. But don't expect anything revolutionary - just another set of annotations :-).

    Thursday, January 12, 2006

    Computer technology

    Yes yes yes, it's like that. Technology rules the world and I'm really keen about it. As a java developer I'd like to write my thoughts on this famous language. My technology overview is really wide so I hope, that someone find this blog useful. My first article will cover upcoming Java EE 5 and will by posted soon. Work on thorough examples is done and I'll be glad to post it here ASAP. Till that, happy surfing and I'm looking forward to hearing from you !
    Defectus