fredag, november 23, 2007

Some Notes on the XX:AppendRatio JVM Parameter

If you install the Oracle Application Server 10.1.3.1+ you will see that the JVM parameter -XX:AppendRatio=3 is set for the OC4J instance by default, however there is not much describing it in the documentation, and it might not be exactly clear from its name what it is used for.

The only entry in the Oracle documentation is found in the Oracle Application Server Performance Guide 10g Release 3 (10.1.3.1.0), Chapter 3 - Top Performance Areas where we say that:

"With the Sun 5.0 JVM, under some circumstances under heavy load, synchronization in an application can result in thread starvation. This may cause some requests for an application to appear hung or to timeout after a long time.

In 10g Release 3 (10.1.3.1.0) the parameter: -XX:AppendRatio=3 is specified by default for managed OC4J. For standalone OC4J, if you believe your installation has this problem, we recommend setting the JDK parameter: -XX:AppendRatio=3 to avoid this problem."

There is also a reference to the Sun JVM Bug Database entry 4985566 that describes the details of the problem.

However, there is a better description of the problem and the purpose in the Sun JVM Bug Database entry 6383015.

Here the purpose of the parameter is described as: "The VM option -XX:AppendRatio=N can be used to control how often an append is done rather than an append. If set to 0 then every enqueue will be an append and the observed behaviour will be 'fair' if desiring FIFO like ordering."

It then continues a bit down with: "In 1.5.0 the monitor queuing policy is 'mostly prepend', which is essentially LIFO except that every N queue additions are done as an append rather than a prepend. Prepending yields better throughput/performance by trying to allow the most recently blocked thread to run next in the expectation that it will still have a warm cache etc."

So, with this is mind we can go to the following conclusions:

  • If the XX:AppendRatio parameter is unset in JDK 1.5 then the monitor queuing policy will be LIFO. This might cause some threads to be treated unfair, and lead to starvation.
  • If the XX:AppendRatio parameter is set to 0 then the monitor queuing policy will be almost like FIFO, however 100% FIFO is not guaranteed as described in bug 4985566 above.
  • If the XX:AppendRatio parameter is set to 3 then each 3:rd queue addition is done as an append rather than a prepend. This will take some advantage of the performance benefits using LIFO, but it will better ensure fairness trying to prevent thread starvation.

So, I hope this have given you a better understanding of what the XX:AppendRatio JVM Parameter does and why it is set by default when installing the Oracle Application Server 10.1.3.1+.

torsdag, november 22, 2007

Building a Web Service from a XSD using JDeveloper

Yesterday I was asked how to create a Web Service from a XSD file using JDeveloper by a colleague, so I thought I'd might share the answer I gave to a wider audience. Hopefully someone else out there might also have some use for it.

The purpose of this example is to show how you can build a Java Web Service starting with only a single XSD file using JDeveloper.

1. Create an empty project in JDeveloper (I used version 10.1.3.3).

2. Add the XSD to your project, in this example I use an XSD that looks like:

<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.oracle.com/pcbpel/CountryInfo"
elementFormDefault="qualified">
<element name="CountryInfo">
<complexType>
<sequence>
<element name="Country" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="Name" type="string"/>
<element name="Capital" type="string"/>
<element name="Area" type="decimal"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>

3. Select the XSD in the Applications Navigator

4. Select Tools -> JAXB Compilation from the Menu

5. Now you have JAXB generated Java classes based on your XSD in your project. This is described more in:

http://www.oracle.com/webapps/online-help/jdeveloper/10.1.3?navId=4&navSetId=_&vtTopicFile=working_with_xml/xml_pjaxb.html

6. Create a new Java class, this is the class that will be the Web Service

7. In this class create a method (this will be exposed as a Web Service method) it has a javax.xml.soap.SOAPElement as input parameter and void as return value, like:

public void testMethod(javax.xml.soap.SOAPElement myDoc)

8. In the method body, add code to unmarshal the document and in this example just write it to System.out:

try {
JAXBContext jc = JAXBContext.newInstance("project3");
Unmarshaller u = jc.createUnmarshaller();

CountryInfo countryInfo = (CountryInfo)u.unmarshal(myDoc);
List lst = countryInfo.getCountry();

for(Iterator iter = lst.iterator(); iter.hasNext();) {
CountryInfo.CountryType country = (CountryInfo.CountryType)iter.next();
System.out.println( country.getName() + ", " + country.getCapital());
}
}
catch (JAXBException je) { je.printStackTrace(); }


9. Start the Java Web Service wizard from the New Gallery, select the newly generated class and just use the default values in the Wizard, except for SOAP Format, here use Document/Literal.

10. Before deploying the Web Service, make sure that all needed files are included in the deployment profile.

11. Once done, either deploy the Web Service to an Application Server or standalone OC4J instance and test it using XML like:

<?xml version="1.0" encoding="UTF-8" ?>
<CountryInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.oracle.com/pcbpel/CountryInfo src/xsd/CountryInfo.xsd"
xmlns="http://www.oracle.com/pcbpel/CountryInfo">
<Country>
<Name>Sweden</Name>
<Capital>Stockholm</Capital>
<Area>1.0</Area>
</Country>
</CountryInfo>

this should give the following printed to System.out:

07/11/22 12:29:31 Sweden, Stockholm

fredag, november 16, 2007

Don't Forget of the Permanent Generation...

This week I was at a customer where we would install a SOA Suite server and deploy quite a lot of BPEL processes onto it. Most things went fine until the end of the deployment where we encountered a problem: java.lang.OutOfMemoryException, I was first a bit confused since we had assigned 2Gb of memory to the JVM - so how could that be?

Simple, I forgot about the Permanent Generation Size, and this post is my equivalent of writing it on the black board 100 times in order to remind myself to not forget about it again in the future...

We solved the problem by adding these 2 JVM parameters:

-XX:PermSize=256 -XX:MaxPermSize=256m

So, what do they do?

The permanent generation is allocated outside of the normal heap and holds objects of the VM itself such as class objects and method objects. If you have programs that load many classes (like deployment of many BPEL processes in a batch), you may need a larger permanent generation.

Since the sizing of this is done independently from the other generations, this means that even if you setup a heap of 2Gb, you might still encounter problems in the permanent generation cause if you do not specify this it will fallback on the defaults .

Why are they set to the same value above? Simply because we want to minimize large garbage collection here.

Once we had reconfigured the OC4J instance with these settings the deployment went fine.




torsdag, oktober 04, 2007

What is an Oracle SOA Suite 10.1.3.1+ Cluster?

"Cluster - a number of things of the same kind, growing or held together; a bunch: a cluster of grapes.".

This is how a cluster is defined in the dictionary (http://dictionary.reference.com). Not a particularly exact definition, at least not to me. Then, one often hears that a SOA Suite installation runs in a 'cluster'. But what does this actually means? The definition did not give a particularly good definition. Also, as there are several ways to connect instances together to form a cluster it could be good to know exactly which way that is used in each case. There are (at least) four different ways to form a cluster in Oracle SOA Suite 10.1.3.1+ ; these are:

  • ONS Topology
  • OC4J Group
  • BPEL JGroup Config
  • OC4J Session Replication

Let's now discuss them more in detail.


ONS Topology

This is a group of Oracle Notification Server (ONS) in a farm configured to run in same topology. Basically; two or more loosely connected Oracle Application Server nodes. You can create this by using either of the 4 methods Dynamic node discovery, Static hubs, Connection via gateways or Manual configuration. You can read more about these methods in:

http://download-uk.oracle.com/docs/cd/B32110_01/web.1013/b28950/topology.htm#CHDCAIFD

I assume that this is the way most people refer to when they are talking about an Oracle SOA Suite cluster.


OC4J Group

This is a management concept, which is a set of OC4J instances that belong to the same group. Groups enable you to perform common configuration, administration, and deployment tasks simultaneously on all OC4J instances in a group. Some people might argue that this is not a cluster, but is certainly "a number of things of the same kind held together", so according to the dictionary it would be a cluster.

Read more about OC4J Groups in:

http://download-uk.oracle.com/docs/cd/B32110_01/web.1013/b28950/topology.htm#BIHGICBJ


BPEL JGroup Config

This clustering concept allows defining a topology for BPEL instances, for example new processes. This concept uses an Active / Passive model (for the concerned process). In case of a server failure, another Oracle BPEL Server running on another server resumes the process from the last dehydration point.

Read more about this in:

http://download-uk.oracle.com/docs/cd/B31017_01/integrate.1013/b28980/clusteringsoa.htm


OC4J Session Replication


This is a way to replicate sessions in state across applications. This can also be referred to as an application cluster and is the same set of applications hosted by two or more OC4J instances. It can be enabled either globally for all applications running within an OC4J instance or on application basis. There are three ways to do this: multicast, peer-to-peer or database replication. Read more about these in:

http://download.oracle.com/docs/cd/B31017_01/web.1013/b28950/cluster.htm


To summarize, there are (at least) 4 different ways of creating an Oracle SOA Suite 10.1.3.1 cluster. These are the methods and also the intended purpose of them:

  • ONS Topology: To connect two or more loosely connected Oracle Application Server nodes.
  • OC4J Group: To create a group with a set of OC4J instances.
  • BPEL JGroup Config: A set of BPEL Servers that shares the same dehydration store and listens on the same JGroup channels.
  • OC4J Session Replication: Used to replicate state across an application deployed on two or more OC4J instances.

So, what do you mean when talking about clusters?

måndag, september 17, 2007

Using Berkeley DB Inside Your JDeveloper Project

Sometimes you need a small database within your JDeveloper project, but you don't want to install any of the usual suspects like Oracle Database 10g Express Edition or Oracle Lite. If so, Oracle Berkeley DB is an ideal candidate. It's very easy to get started with it inside JDeveloper; just follow the steps below, and you will be up and running in just 15 minutes. Start by downloading the Oracle Berkeley DB Java Edition from the OTN:

http://www.oracle.com/technology/software/products/berkeley-db/je/index.html

  1. Create a new Project in JDeveloper
  2. Create a new Library in the JDeveloper project that contains the lib/je-3.2.44.jar file from the Berkeley DB distribution.
  3. Save the Project.
  4. Create a new folder in the file system under the newly created JDeveloper project named: src/collections/hello
  5. In the file system, copy the file examples/collections/hello/HelloDatabaseWorld.java from the Berkeley DB distribution and put it into the src/collections/hello folder.
  6. In JDeveloper, refresh the project. The copied file should now appear in the JDeveloper project under Application Sources.
  7. Create a new directory under your project directory called tmp. This is were the database will reside. If you want to place the database somewhere else, change the line in the HelloDatabaseWorld.java that says:

    String dir = "./tmp";

  8. Run the project inside JDeveloper, the result should be similar to:

    Writing data
    Reading data
    0 Hello
    1 Database
    2 World

If you want to read more about Oracle Berkeley DB Java Edition, please refer to this URL:

http://www.oracle.com/technology/products/berkeley-db/je/index.html

fredag, september 14, 2007

Is it Enough with Business Analysts and Developers when Developing a Rule Based Application?

When talking about rule based programming one often hear that it enables business users and developers to work together. The business users can focus on the business rules part and the developers on the code writing part. This sounds good the first times you hear it, but after a while (at least for me) this sounds perhaps a bit too good to be true. Let me tell you why I believe this to be too good to be true.

If we start to look at the role of the developer; he or she should write the underlying code for the application, and not have to focus on the actual business rules that should be implemented in the system, i.e., should a certain threshold be above or below a certain level, and what should the level be? He should just know that based on this and that data that comes from these and those sources some rules should be applied and then this and that should happen. He should not have to care about exactly what the rules are, how many they are, what thresholds that should be set etc. These things should be left to the business analyst.

The business analyst should on the other hand not have to worry about how to get the data etc, he should just work on the business rules and set the right thresholds that should trigger certain things, for example a discount should be applied for certain customers, but not for others. He should just decide which customers the discount should be applied for and when it should be applied.

Now, don't get me wrong here, I firmly believe that this distinction is good, but I do not believe that it is enough, here are some reasons why:

  • The tools requires the business user to be aware of technical issue that he or should not have to be aware of.
  • I have not yet seen a tool that is easy enough for a business user to use.

There are further points on my list, but I will stick with these two for the rest of the discussion. This is not just only for our product in this area; this also goes for our competitors.

Normally the rules are stored in a repository, this requires from the end user to be aware of the location, how to open it, how to navigate to right screen, how to alter the rules and/or variables, how to add the syntax for new rules etc. I believe that any business analyst could learn these things, but is this really things that he/she should be focusing his time on? If I would run a business I would rather see them spend time on doing what they to best; not being a part time developer.

I would instead like to see that these things are handled by just a handful of people; I'll call them Business Rules Maintainers. These are the ones who should be working with the deeper maintenance of the rule repository; they could have a Business Analysts background but also needs to be aware of the technical parts of your rule product.

Now, the business analysts still needs to be there, and they need to be able to quickly adapt the rule system to the business, for example, one of you analysts suddenly discovers that a competitor has lowered the levels for being eligible for a discount and you think that this will impact your business if you do not do the same, so the analyst needs to quickly adjust your current discount levels in the system. At this point he should not have to open a full blown rule administration tool for this, he should just have to open a custom GUI in where he could quickly see what the current discount levels are and equally fast alter and save them.

So, to summarize, I believe that when you are designing the system, you should also start to think if your standard rule administration tool is easy enough to use for all your business analysts. If you come to this conclusion, fine. If not, start to think in terms how you could build a custom GUI for your business analysts that they could easy use to quickly tune your business to sudden changes in the environment, and make this GUI as simple as possible to use so that you won't have to turn your analysts into part time programmers. It might not be necessary to incorporate all your rules and threshold variable in this GUI, just the ones that are most critical to your business, and leave the rest to be maintained by the subset of your analysts that are the Business Rules Maintainers.

So to finalize the discussion, I think that when talking about developing and maintaining a rule based system, it is not enough to split the roles into developers and business analysts, I believe that at least one more role is necessary. It could also be that even further roles are necessary, but that is another discussion.

onsdag, september 12, 2007

Introduction Into Oracle Business Rules and Rule Based Programming

I was asked the other day by a colleague who wanted to get an introduction into Oracle Business Rules if I had some tips & pointers in order to get started, so I thought I'd might put the answer here; perhaps some more people can use it as well.

For a short, but good introduction to what rule based programming is, please check:

http://www.webreference.com/programming/rule/

The article describes short and concise what rule base programming is all about.

OK, so now you know what it is, but how to get started using it? If you are using the Oracle SOA Suite, then you already have a rule engine in place, so why not start using it?

To see a viewlet on how-to use it, go to the Rules section in OTN: http://www.oracle.com/technology/products/ias/business_rules/index.html

It is available under the 'Viewlets and Tutorials' section. After that, it is time to start learning more about it.

If you have a developer's background, I would suggest that you start with the 'Oracle Business Rules Language Reference' (available at: http://download.oracle.com/docs/cd/B32110_01/web.1013/b28964/toc.htm), this will give you a feel for how the Rule language works; after all this is really the foundation. When going through this document, you will of course need the API, it's available here: http://download.oracle.com/docs/cd/B32110_01/web.1013/b28966/toc.htm.

The document contains many small examples that will help you to get started and get familiar with the language. The examples are run using a command line interface that ships with the product. An alternative is to download the RulesTools extension for JDeveloper 10.1.3.x. This will give you the option to execute script files written in the Rules Language directly in JDeveloper, as well as some other stuff that will ease programming in the Rules Language.

Once you are familiar with the Rule language, or if you are coming from a more business oriented background, you should start to have a look into the Oracle Business Rules Rule Author; it is the GUI that is used for creating the rules. The documentation for it is available here: http://download.oracle.com/docs/cd/B32110_01/web.1013/b28965/toc.htm.

In the previous given link to the Rules section on OTN you will find even more demos and tutorials to help you get started with the Oracle Business Rules.

I hope this will help you to take your first steps down the road of Oracle Business Rules and rule based programming. Good luck!

onsdag, september 05, 2007

Oracle Lite, JDeveloper and Invalid Oracle URL specifiedError Code 17067

Oracle Lite and me have never been friends, but I think that I now have finally beaten the ghost. The background is that I simply wanted to use the OLite in order to do some testing, instead of having run to run a full DB, I wanted to use OLite. So far so good.

I started to configure a DB connection in JDeveloper towards the OLite, and this part went smooth and without problem. Next, I created a small project in JDeveloper based on TopLink and session facade beans. This went fine as well, JDeveloper nicely created my POJO's based on the tables. Finally I created a JSF page to display the data. All in all, the design process went smooth as silk.

The problems started when running the project on the embedded OC4J. All I got was a little error saying:

Internal Exception: java.sql.SQLException: Invalid Oracle URL specifiedError Code: 17067

I performed a few searches on this, but could not really find any useful information, so it was time to start to dig. My first thought was that this was a class loading issue, and that the error was not really the real error; so I added the olite40.jar to about all places that would be relevant for my JDeveloper installation. It did not help; I still ended up with the same error.

Next thought, perhaps the error message was a bit relevant after all, so I added a data-sources.xml file to my project (and an orion-application.xml) to get better control of the data sources. Further, I added a new data source based on the predefined OLite connection and told the session.xml file to use this connection. I did not yet make any further modifications, the new data source was correctly picked up, but I ended up with the same error.

Here was what the original data source looked like:

<connection-pool name="jdev-connection-pool-LocalSoaSuiteOLitee">
<connection-factory factory-class="oracle.jdbc.pool.OracleDataSource"
user="username" password="password" url="jdbc:polite4@localhost:1531:orabpel"/>
</connection-pool>
<managed-data-source name="jdev-connection-managed-LocalSoaSuiteOLitee"
jndi-name="jdbc/LocalSoaSuiteOLiteeDS" connection-pool-name="jdev-connection-pool-LocalSoaSuiteOLitee"/>

I noticed the small piece: factory-class="oracle.jdbc.pool.OracleDataSource", this looked a bit strange to me, so I tested to change this into: factory-class="oracle.lite.poljdbc.POLJDBCDriver" instead, like:

<connection-pool name="jdev-connection-pool-LocalSoaSuiteOLitee">
<connection-factory factory-class="oracle.lite.poljdbc.POLJDBCDriver"
user="username" password="password" url="jdbc:polite4@localhost:1531:orabpel"/>
</connection-pool>
<managed-data-source name="jdev-connection-managed-LocalSoaSuiteOLitee"
jndi-name="jdbc/LocalSoaSuiteOLiteeDS" connection-pool-name="jdev-connection-pool-LocalSoaSuiteOLitee"/>

Once I restarted the project, it all went fine. So, why this did happen after all? Well, it looks as JDeveloper treats an OLite connection as an Oracle connection, so when it generates the data-sources.xml file for the embedded OC4J instance is sets the factory class to what it would be for an Oracle database. With this mind, I can summarize what I did into these steps:
  1. Add a data-sources.xml file and an orion-application.xml file to the project.
  2. Create a new data source.
  3. Change the factory-class to oracle.lite.poljdbc.POLJDBCDriver.

tisdag, september 04, 2007

A Small Comment on MySQL in JDeveloper 11 (Preview Release)

Today I've been doing some tests using MySQL together with the JDeveloper 11 Preview Release. This worked fine, most of the info is covered in the Help chapter, "Working with Non-Oracle Database". However, I missed out one small piece; how to get it to work together with the Embedded OC4J, or rather, where to put the MySQL JDBC JAR file? This as I got an

"Exception: oracle.oc4j.sql.config.DataSourceConfigException: Unable to create : com.mysql.jdbc.Driver"

when trying to run my application.

As of JDeveloper 11, a new default directory structure for user-specific content in JDeveloper for Windows is used. The default location for the system subdirectory is now %APPDATA%\JDeveloper\systemXX.XX.XX.XX, where:

  • %APPDATA% is the Windows Application Data directory for the user (usually C:\Documents and Settings\<username>\Application Data)
  • XX.XX.XX.XX is a unique number of the product build, for example, system11.1.1.0.17.45.02

So, in my case, the MySQL JDBC JAR file (mysql-connector-java-3.1.12-bin.jar) should go into the directory:

C:\Documents and Settings\
<username>\Application Data\JDeveloper\system11.1.1.0.17.45.24\o.j2ee\embedded-oc4j\applib

Once I put it there, and restarted the embedded OC4J, it worked fine.

måndag, september 03, 2007

Combining Information

It exists countless articles & blog entries about ADF, however, I have found that quite often do they not exactly cover the exact topic that I am looking for, but, if I combine a few of them they can often together build a solution that is useful for me.

For example, in most cases when you want to display a certain record, the easiest approach if to use a ViewObject with a bind variable and then use the executeWithParams approach, as described in Duncan's blog here:

http://groundside.com/blog/DuncanMills.php?title=executewithparams_my_new_best_buddy&more=1&c=1&tb=1&pb=1

Last week I was assisting one of our partners in a project, and they wanted to display a certain record, but they did not want to use this approach. Instead they wanted to set the selected record based on a parameter sent to the page, and set the record is something like an 'onLoad' event for the page. So, what we did here was to use the processScope variable as described in this article to send the parameter:

http://www.oracle.com/technology/products/jdev/htdocs/partners/addins/exchange/jsf/doc/devguide/communicatingBetweenPages.html

and then combining this with an ADF Page Phase Listener as described here to set the record:

http://groundside.com/blog/DuncanMills.php?title=adf_executing_code_on_page_load&more=1&c=1&tb=1&pb=1

The PagePhaseListener is implemented in the backing bean and this then uses the setCurrentRowWithKeyValue to set the correct row in the iterator, something like:

if (event.getPhaseId() == Lifecycle.PREPARE_MODEL_ID) {
AdfFacesContext afContext = AdfFacesContext.getCurrentInstance();
String myValue = (String)afContext.getProcessScope().get("myKey");
FacesPageLifecycleContext ctx = (FacesPageLifecycleContext)event.getLifecycleContext();
DCIteratorBinding iter = ((DCBindingContainer)ctx.getBindingContainer()).findIteratorBinding("
DepartmentsView1Iterator");
iter.setCurrentRowWithKeyValue(myValue);
}

So, all-in-all, by combining 2 useful articles, I were able to solve the problem, even if no single article covered the problem.