28 April 2010

Weblogic Server 10.3.3 available on OTN

News at hand! We've just released WebLogic Server 10.3.3 and it's now available for download on OTN:

http://www.oracle.com/technology/software/products/middleware/htdocs/fmw_11_download.html

You may also note the addition of a new zip file download for WLS itself:

http://download.oracle.com/otn/nt/middleware/11g/wls1033_dev.zip

This is a new smaller distribution of WLS that we are making available as a zip file, which can be simply extracted to a local directory, one script executed to specify some access control settings, and then launch WLS directly from the command line. A new domain will automatically created if none is found.

This is a really good step forward for WLS, making it more easily installed and incorporated into development and testing environments. Please read the README.txt embedded within the zip file for more details on how to start and use the server. Note that this is only supported for development use, not for use in production deployment environments.

By the way, this new WLS zip file distribution has been tested, and is supported on Mac OS X for development use. Enjoy!

Note: an issue was identified by a reader below showing that the upgrade utility was not launching successfully.  We have identified a workaround for this which involves adding two additional libraries to the PRE_CLASPATH environment variable before running the upgrade utility.

$ export PRE_CLASSPATH="${MW_HOME}/modules/features/com.bea.cie.common-plugin.launch_2.5.0.0.jar:${MW_HOME}/utils/config/10.3/config-launch.jar"
 

Then run upgrade command as usual.

$ ${MW_HOME}/wlserver/common/bin/upgrade.sh

01 March 2010

The Obligatory Calculator in JSF 2.0




Checked out some of the high level JSF 2.0 new features recently using NetBeans 6.8 and GlassFish v3.  For what it's worth, I think they are very usable, feature rich and effcient pairing for conducting Java EE 6 development.

As with all old habits, some won't die.  And my habit for taking a quick look at any new programming language/framework is to build a very simple calculator with one screen and some simple calculation logic.

With NetBeans, creating a new Web project is trivial.  To add JSF support select it as a framework to use.

After a bit of navel gazing, I realized a significant part of the unholy dislike I had for JSF 1.2 and its earlier versions predominantly stemmed from the need to live in the configuration red zone -- faces-config.xml. Every damned thing that you wanted to use or access pretty much needed to be defined in the configuration file: managed beans definitions with packages/classes and names and scopes, even the most simples of page navigation paths, etc.

But as of JSF 2.0, that has mostly changed! Accomodating a convention over configuration model for page navigation and making use of annotations for declaring managed bean components (and associated runtime attributes and property values) in my simple example, I didn't have to even look at the faces-config.xml file.  Happy Days.

Here's my simple CalculatorManagedBean, which is responsible for performing the arduous task of calculating a result from a given two values and an operand. It also supplies the operand values for the screen to display.

To declare this as a ManagedBean, all I had to do was to add the @ManagedBean annotation. I also decided to bind this ManagedBean into each clients HttpSession so it was created once, and was able to store property values set from eacg clients page.

 1 package sab.demo.calc.beans;
 2 
 3 import java.io.Serializable;
 4 import javax.annotation.PostConstruct;
 5 import javax.faces.bean.ManagedBean;
 6 import javax.faces.bean.SessionScoped;
 7 
 8 @ManagedBean(eager=true)
 9 @SessionScoped
10 public class CalculatorManagedBean implements Serializable {
11 
12     public static char[] operands = { '+', '-', '*', '/' };
13 
14     int value1;
15     int value2;
16     char operand;
17     String result;
18 
19     public CalculatorManagedBean() {
20     }
21 
22     public char[] getOperands() {
23         return operands;
24     }
25     
26     public char getOperand() {
27         return operand;
28     }
29 
30     public void setOperand(char operand) {
31         System.out.printf("setOperand: %s", operand);
32         this.operand = operand;
33     }
34 
35     public String getResult() {
36         return result;
37     }
38 
39     public void setResult(String result) {
40         this.result = result;
41     }
42 
43     public int getValue1() {
44         return value1;
45     }
46 
47     public void setValue1(int value1) {
48         System.out.printf("setValue1: %s\n", value1);
49         this.value1 = value1;
50     }
51 
52     public int getValue2() {
53         return value2;
54     }
55 
56     public void setValue2(int value2) {
57         System.out.printf("setValue2: %s\n", value2);
58         this.value2 = value2;
59     }
60 
61     public void calculate() {
62         switch(getOperand()) {
63             case '+' :
64                 result = String.valueOf(value1 + value2);
65                 break;
66             case '-' :
67                 result = String.valueOf(value1 - value2);
68                 break;
69             case '*' :
70                 result = String.valueOf(value1 * value2);
71                 break;
72             case '/' :
73                 double v1 = value1;
74                 double v2 = value2;
75                 result = String.valueOf(v1 / v2);
76                 break;
77         }
78         System.out.printf("Calculate: %s %s %s = %s\n",
79                 getValue1(),
80                 getOperand(),
81                 getValue2(),
82                 getResult());
83 
84     }
85 
86     @PostConstruct
87     public void postConstruct() {
88         System.out.println("postConstruct");
89         operand = '+';
90         value1 = 0;
91         value2 = 0;
92         result = "n/a";
93     }
94 }
95 
96 

With the ManagedBean taken care of, the next step was to create the JSF page. With JSF 2.0, it now uses Facelets as the default view technology instead of JSP. This means there are lots of things that are able to be expressed more naturally in the view layer, which were previously difficult or cumbersome in the older JSP model.

A really useful thing I found in facelets was the ability to render a ManagedBean property directly in the page, without needing to surround it with other tag library calls.

So to create my calculator screen, I simply added a couple of fields, and wired them into the CalculatorManagedBean that I'd developed. Again, following convention over configuration, the default name for a ManagedBean is a lower case version of the classname, which makes them easy to remember/lookup from a project hierachy (as opposed to hunting through XML). Of course NetBeans makes this easy since it has code-insight which presents the names of known ManagedBeans and their available properties for insertion via a few keystrokes.

The list of operands values shown in the select list are populated from a property on the ManagedBean which returns an array of char.

The "=" button is wired into the calculate operation, which takes its current property values, performs the desired operation and sets the result property, which is then displayed in the result field on the page.

 1 <?xml version='1.0' encoding='UTF-8' ?>
 2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 3 <html xmlns="http://www.w3.org/1999/xhtml"
 4       xmlns:f="http://java.sun.com/jsf/core"
 5       xmlns:h="http://java.sun.com/jsf/html">
 6     <h:head>
 7         <title>Calculator Facelet</title>
 8     </h:head>
 9     <h:body>
10         <h:column><h3 style="font-family: arial; font-variant: small-caps; color: #336699">Calculator</h3></h:column>
11         <h:form>
12             <h:panelGrid columns="1" style="text-align: center; border: 1px solid #336699; padding: 5px; ">
13             <h:column>
14                 <h:inputText id="value1" value="#{calculatorManagedBean.value1}" 
15                              size="5" maxlength="5" style="text-align: right;"/>
16             </h:column>
17             <h:column>
18                 <h:inputText id="value2" value="#{calculatorManagedBean.value2}" 
19                              size="5" maxlength="5" style="text-align: right"/>
20             </h:column>
21             <h:panelGrid columns="2">
22                 <h:column >
23                     <h:selectOneMenu id="operand" value="#{calculatorManagedBean.operand}" 
24                                      style="text-align: center;">
25                         <f:selectItems value="#{calculatorManagedBean.operands}"/>
26                     </h:selectOneMenu>
27                 </h:column>
28                 <h:column><h:commandButton value="=" action="#{calculatorManagedBean.calculate}"/></h:column>
29             </h:panelGrid>
30             <h:column>
31                 <h:inputText id="result" value="#{calculatorManagedBean.result}" 
32                              readonly="true" size="5" style="font-weight: bold; text-align: right"/>
33             </h:column>
34         </h:panelGrid>
35         </h:form>
36     </h:body>
37 </html>
38 
39 
40 

Put it all together and run using the local GlassFish instance, the page works and looks like this.


So there it is, a JSF 2.0 version of my old habit up and running in a few minutes. I like what I've seen with JSF 2.0 so far.

Of course, the use of @ManagedBean annotation in JSF 2.0 may be dead already with the arrival of CDI in Java EE 6 and its @Named annotation, but that's not an issue I'm going to explore here.

13 October 2009

Exploring EclipseLink @OptimisticLocking

Been a while since I've had some fun with JPA, so I decided to spend a little time with it today.

I created a very simple domain model (Employee --> LeaveRecord) to use.



Since I was just intent of doing some quick testing, instead of following the usual route of creating an EJB session facade to expose the @Entity objects, and then exercising that from a client to test things out, I simply created some JUnit4 @Test cases to act as the test clients. These @Test cases exercised the @Entity objects from outside the container, so it was actually a very easy way to go.





One thing I'd never looked at much was the EclipseLink specific annotations, so I decided to take a quick peek around there for something interesting to test. A quick peruse of the EclipseLink documentation drew me to the @OptimisticLocking annotation.  How could you not be optimistic with that!

The goal of the @OptimisticLocking annotation is to direct EclipseLink to use an optimistic locking strategy for the @Entity, directing it to the current property values from the object it is persisting against the data currently in the database to ensure it hasn't changed since it was last read. 

There are several different options available, so I took a look at the differences between the OptimisticLockingType.ALL_COLUMNS and the OptimisticLockingType.CHANGED_COLUMNS options.

The @OptimisticLocking annotation is specified on the POJO.

  @Table(name = "EMPLOYEES")
  @OptimisticLocking(type=OptimisticLockingType.ALL_COLUMNS)
  public class Employee implements Serializable {
      ...
  }
 
Doing simple reads and updates of the Employee @Entity with the eclipselink.logging.level set to FINEST shows the SQL that is created when the different types are applied.

@OptimisticLocking(type=OptimisticLockingType.ALL_COLUMNS)
Connection(26174809)--UPDATE EMPLOYEES SET VACATION_HOURS = ? 
  WHERE ((EMPLOYEE_ID = ?) AND 
  (((((EMAIL_ADDRESS = ?) AND 
      (FIRST_NAME = ?)) AND 
      (LAST_NAME = ?)) AND 
      (SALARY = ?)) AND 
      (VACATION_HOURS = ?)))
   bind => [999, 1, jack.rooster@anon.org1, Jack1, Rooster1, 1.0, 1]

In this configuration, all the fields of the @Entity are contained in the WHERE clause of the UPDATE statement.

@OptimisticLocking(type=OptimisticLockingType.CHANGED_COLUMNS)
Connection(2554341)--UPDATE EMPLOYEES SET VACATION_HOURS = ? 
  WHERE ((EMPLOYEE_ID = ?) AND (VACATION_HOURS = ?))
  bind => [999, 1, 1]

In this configuration, only the updated fields of the @Entity are contained in the WHERE clause of the UPDATE statement.

After testing the @OptimisticLocking annotation and observing that I worked as expected in my test environment, the next step was to test what happens when a change is made to an object after it has been read, but before it is updated.

The flow is essentially this:

  T1 --> read employee 1
  T1 --> create and start T2
    T2 --> read employee 1
    T2 --> update employee 1
    T2 --> persist employee 1
  T1 --> update employee 1
  T1 --> persist employee 1  *expect OptimisticLockingException*

The @Test case below represents this sequence.

@Test(expected = RollbackException.class, timeout = 20000)
public void checkOptimisticLocking() throws Exception {

    Employee pre = employeePM.find(Employee.class, Long.valueOf(1));

    // do the separate thread update of the specified employee with value
    EmployeeTestOptimisticLockingHelper t = 
        new EmployeeTestOptimisticLockingHelper(1L, -999L);

    t.start();
    t.join(10000);

    // Now do the local the update
    // should throw OptimisticLockException
    employeePM.getTransaction().begin();
    pre.setVacationHours(999L);
    employeePM.getTransaction().commit();
}

The EmployeeTestOptimisticLockingHelper is a separate class that is executed via another Thread.  This allows it to perform the change using a separate EntityManager.

public class EmployeeTestOptimisticLockingHelper extends Thread {

    private Long id;
    private Long newval;

    public EmployeeTestOptimisticLockingHelper(Long id, Long newval) {
        this.id = id;
        this.newval = newval;
    }

    @Override
    public void run() {
        EntityManager em = null;
        try {
            em = Persistence.createEntityManagerFactory("CompanyUnit")
                            .createEntityManager();
            Employee emp = em.find(Employee.class, id);
            em.getTransaction().begin();
            emp.setVacationHours(newval);
            em.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            em.close();
            interrupt();
        }
    }
}

When this @Test is executed, it results in the following exception being thrown, demonstrating that the specified @OptimisticLocking model is working as expected.

[EL Finer]: 2009.10.13 14:54:43.796--ClientSession(14031599)--Connection(26174809)--rollback transaction
[EL Warning]: 2009.10.13 14:54:43.796--UnitOfWork(26953544)--javax.persistence.OptimisticLockException: Exception [EclipseLink-5006] (Eclipse Persistence Services - 1.0.2 (Build 20081024)): org.eclipse.persistence.exceptions.OptimisticLockException
Exception Description: The object [Employee 1 Jack1 Rooster1 jack.rooster@anon.org1 999 $1.0] cannot be updated because it has changed or been deleted since it was last read. 
Class> sab.demo.company.domain.Employee Primary Key> [1]
 at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:480)
 at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1330)
 at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:159)
 at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1002)
 at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84)
 at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
 at sab.demo.testdomains.EmployeeTest.checkOptimisticLocking(EmployeeTest.java:149)

And the JUnit runner shows the @Test passes as expected, since it is configred to expect the wrapper javax.persistence.RollbackException to occur.



07 October 2009

Getting samples schema to run against an Oracle DB

The samples domain that is able to be optionally created with a WebLogic Server installation provides a wealth of useful examples, covering core JavaEE APIs through to an full sample application called MedRec.

By default, the samples domain installs and uses a PointBase database to host its application data, which allows it to work immediately after installation with no additional requirements to install, configure a database.

It probably goes without saying, but there is interest in making the samples also work with an Oracle database.

When the samples domain is created, it provides its own set of online documentation that describes how to configure, install and use the various samples.

One section in the doc notes how to install the sample schema against an Oracle database, which ultimately results in the execution of the demo.ddl file against the specified Oracle database instance.

>ant db.setup.oracle


I just tried it against an Oracle XE (10.2) database I have lying around and noticed some problems when it executed, based on inserting date format data into several of the tables used by the MedRec application.

[sql] Failed to execute:   INSERT INTO patient (id,first_name,middle_name,last_name,dob,gender,ssn,address_id,phone,email) VALUES (101,'Fred','I','Winner','1965-03-26','Male','123456789',101,'4151234564','fred@golf.com')
[sql] java.sql.SQLDataException: ORA-01861: literal does not match format string

[sql] Failed to execute:   INSERT INTO record (id,pat_id,phys_id,record_date,vital_id,symptoms,diagnosis,notes) VALUES (101,101,102,'1999-06-18',101,'Complains about chest pain.','Mild stroke.  Aspiran advised.','Patient needs to stop smoking.')
[sql] java.sql.SQLDataException: ORA-01861: literal does not match format [sql] 

[sql] Failed to execute:   INSERT INTO prescription (id,pat_id,date_prescribed,drug,record_id,dosage,frequency,refills_remaining,instructions) VALUES (101,101,'1999-06-18','Advil',101,'100 tbls','1/4hrs',0,'No instructions')
[sql] java.sql.SQLDataException: ORA-01861: literal does not match format string


To workaround this, I found that by editing the $WLS_HOME\wlserver_10.3\samples\server\examples\src\examples\common\demo.ddl and appending the DATE function to the respective insert statements, the demo.ddl script executed without error and the data was inserted correctly.

Here are examples of the row inserts that have been modified:

INSERT INTO patient (id,first_name,middle_name,last_name,dob,gender,ssn,address_id,phone,email) 
VALUES 
(101,'Fred','I','Winner',DATE'1965-03-26','Male','123456789',101,'4151234564','fred@golf.com');

INSERT INTO record (id,pat_id,phys_id,record_date,vital_id,symptoms,diagnosis,notes) 
VALUES 
(101,101,102,DATE'1999-06-18',101,'Complains about chest pain.','Mild stroke.  Aspiran advised.','Patient needs to stop smoking.');

INSERT INTO prescription
(id,pat_id,date_prescribed,drug,record_id,dosage,frequency,refills_remaining,instructions) VALUES
(101,101,DATE'1999-06-18','Advil',101,'100 tbls','1/4hrs',0,'No instructions');

Once that was done, the demo.ddl executed successfully and the schema was created in the specified Oracle database.

25 September 2009

14 September 2009

Using Identity Based Connection Pooling with WebLogic Server

From an OTN how-to I recently created:

Using Identity Based Connection Pooling with WebLogic Server

The typical model of interaction an application server has with a database is through the use of datasources.

A datasource is an entity that is configured with appropriate information to allow it to create and manage connections with a database, and to hand these out to applications when they request them. A datasource typically creates pools of connections for effiency purposes and shares these amongst applications that make use of it.

In the typical datasource use case, all the connections the datasource creates use the same username and password. This results in all access to the database being performed using the same database credentials. In most cases this is perfectly acceptable and handled as part of the overall application architecture when needing to dealing with shared, partioned data.

For some rare cases, requirements can exist where it’s necessary to preserve the application user identity in some form all the way down to the database. This could be for the purposes of restricting information access, establishing audit trails, resource scheduling based on user context, etc.

To support these two different usage requirements, WebLogic Server supports two different types of connection pools through its datasource implementation:
  • Homogeneous: Regardless of the current user of the application, all connections in the pool use the same security credentials to access the DBMS.
  • Heterogeneous: Allows applications to use a JDBC connection with a specific DBMS credential by pooling physical connections with different DBMS credentials.
[See full article on OTN: http://www.oracle.com/technology/products/weblogic/howto/identity-pools/index.html]

03 September 2009

Switching Between JRockit and Sun JDK with WebLogic Server

Need to swap between JRockit and the Sun JDK when starting your WebLogic Server instance?

Looking at the start scripts $DOMAIN_HOME/bin/setDomainEnv.cmd, I just realized that this operational task is basically taken care of in the scripts we have.

To swap between the Sun JDK and JRockit to launch a WLS instance, all you need to do is set the JAVA_VENDOR environment variable to either "Sun" or "Oracle" and the scripts will take of launching WLS using the specified JDK.

Snippets from setDomainEnv.cmd:
set BEA_JAVA_HOME=d:\wls1031\jrockit_160_05_R27.6.2-20
set SUN_JAVA_HOME=d:\wls1031\jdk160_11

if "%JAVA_VENDOR%"=="Oracle" (
set JAVA_HOME=%BEA_JAVA_HOME%
) else (
if "%JAVA_VENDOR%"=="Sun" (
set JAVA_HOME=%SUN_JAVA_HOME%
) else (
set JAVA_VENDOR=Sun
set JAVA_HOME=d:\wls1031\jdk160_11
)
)

Where JAVA_HOME is then used by startWebLogic.cmd script when it launches the WLS instance to identify the JDK to use.

Snippets from startWebLogic.cmd
%JAVA_HOME%\bin\java %JAVA_VM% %MEM_ARGS% 
-Dweblogic.Name=%SERVER_NAME% 
-Djava.security.policy=%WL_HOME%\server\lib\weblogic.policy 
%JAVA_OPTIONS% 
%PROXY_SETTINGS% 
%SERVER_CLASS%

With this information at hand, then switching between the two different JDKs is as simple as setting an environment variable before launching WebLogic Server.

Using JRockit:
>set JAVA_VENDOR=Oracle
>startWebLogic.cmd
...
d:\wls1031\JROCKI~1.2-2\bin\java -jrockit -Xms512m -Xmx512m -Dweblogic.Name=AdminServer ...

And just as easy to switch back to Sun. Note here that you could just unset the JAVA_HOME environment variable, which will set the script to use whatever default was configured when the domain was created.

Using Sun JDK:
>set JAVA_VENDOR=Sun
>startWebLogic.cmd
...
d:\wls1031\JDK160~1\bin\java -client -Xms256m -Xmx512m -Dweblogic.Name=AdminServer ...

WebLogic Server Startup and Shutdown Classes

WebLogic Server supports the use of server level startup and shutdown (SU/SD) classes, which are invoked by the server when it is starting up, and conversely when it is shutting down.

The initial implementation of this functionality (not sure of the release but circa 6.x I believe) required the SU/SD classes to implement proprietary WebLogic Server interfaces:
  • weblogic.common.T3StartupDef
  • weblogic.common.T3ShutdownDef
As of WebLogic Server 9.0, these interfaces were marked as deprecated.

It appears that with the introduction of the new application lifecycle listeners feature at the same time, this has resulted in reduced visbility of the new POJO based SU/SD class approach in the documentation.

So here's a brief explanation.

With the deprecation of the earlier SU/SD interfaces, a new and simpler POJO based was introduced for SU/SD classes. This requires only that a SU/SD class only has to have a static main(String args[]) method, which the server will invoke after instantiating the class. No WLS specific interfaces are needed any longer. Any arguments that were configured for the SU/SD class configuration are passed to it via the String[] args parameter.

The POJO based SU/SD class still follows all the same deployment and configuration steps used by the previous model -- the class needs to be made available on the server classpath, the SU/SD class is configured via the console with the requisite parameters and settings, and ultimately stored as an entry in config.xml.

Startup Class:
package sab.demo.utils;

public class StartupMain {
/**
* @param args
*/
public static void main(String[] args) {

log(StartupMain.class.getName() + "::main");
log("Arguments::");
for(int i=0;args!=null && i<args.length;i++) {
log("  arg[" + i + "]: " + args[i]);
}
}

private static void log(String msg) {
System.out.printf("  --> [SAB]: %s\n", msg);
}
}


WLS Console:


config.xml:
<startup-class>
<name>StartupMain</name>
<target>AdminServer</target>
<deployment-order>1000</deployment-order>
<class-name>sab.demo.utils.StartupMain</class-name>
<arguments>arg1 arg2 arg3</arguments>
<failure-is-fatal>false</failure-is-fatal>
<load-before-app-deployments>false</load-before-app-deployments>
<load-before-app-activation>true</load-before-app-activation>
</startup-class>