Thursday, April 10, 2014

Host a Soap Web Service on Google App Engine with JAX-WS

We are about to release a great addon for JDeveloper that can access a SOAP web service. For demonstration purposes we want to have a publicly available web service that anyone can use. Having this web service hosted on Google App Engine has two major benefits: it is free and is accessible for anyone on the internet 24x7.

We wanted to implement a simple Java (JAX-WS) webservice on Google App Engine, but unfortunately this is not fully supported. All the javax.xml.* classes are available on Google App Engine, but not the com.sun.xml.ws.* classes that are normally used to implement a JAX-WS service. But with a little bit of custom code we can get a JAX-WS service to run on Google App Engine as can be seen in the SoapUI screenshot. You can download the public WSDL at https://redheap-jaxws.appspot.com/HelloWorldService.wsdl
SoapUI test invoking HelloWorld service on Google App Engine

You can use the normal JAX-WS annotations in your service class and use JAXB to marshal and unmarshal the request and responses. This is all very similar to a JAX-WS service on a JEE container. The thing you need extra is a custom HttpServlet that handles the HTTP POST, unmarshals the request payload to a java object using JAXB, invoke the actual web service class, marshal the web service class response back to XML and send it to the client.

This post describes all the steps to create a project using maven and complete it in JDeveloper 12c as well as deploying it to a local and remote server. If you prefer other build tools, like Apache ANT, or other Java IDE's you can still use similar steps but you might need to adjust them for your environment. The key part is the custom servlet which is the same for each setup.

Monday, March 31, 2014

Managed Bean changes should mark their ADF Scope dirty in a HA cluster

We're starting development on a new ADF application and the plan is to run this in a high-available weblogic cluster. The documentation clearly states it is the responsibility of the developer to make ADF aware of any changes to managed beans in an ADF scope with a lifespan longer than one request. This means it is up to you to notify ADF of each change in a viewScope or pageFlowScope bean with the following code:
Map viewScope = ADFContext.getCurrent().getViewScope();
ControllerContext.getInstance().markScopeDirty(viewScope);

That's not too difficult but it's a matter of time before a developer forgets about this. That would mean the ADF scope is not marked dirty and the changed managed bean is not replicated to the other nodes in the cluster. We wanted to implement a check (at least during development) that developers do not forget about this. JSF PhaseListener to the rescue!

Full source code is at the end of this posting, but I'll explain the vital parts first. We've create a JSF PhaseListener that listens to each JSF phase transition:
public PhaseId getPhaseId() {
    return PhaseId.ANY_PHASE;
}

In the beforePhase method for the RESTORE_VIEW phase we retrieve the viewScope and pageFlowScope maps. Next, we serialize these and calculate a MD5 hash. These hashes are store in the requestScope

In the afterPhase method for the RENDER_RESPONSE phase we calculate the same MD5 digests and compare these with the ones stored at the beginning of the request. We know we're in trouble when the digests changed and the developer has not invoked ControllerContext.markScopeDirty. When this happens we simple log an exception to the console without actually throwing it. This is more of a development/debugging tool and shouldn't actually abort JSF processing as that would also cancel any other PhaseListeners. We don't want to make things worse.

You probably want this enabled during development all the time. However, there is a performance overhead in serializing the viewScope and pageFlowScope twice per request and calculating a MD5 digest. It might be a good idea to disable this in production. That's why we opted to use the ADF logging framework for this. First, you can set the log levels that will be used for the output through web.xml context-parameters. By default, these are set to WARNING to ensure all logging is enabled in a default development environment. In production you want to use deployment plans to override this to something like FINE or FINEST. Once you know the logging level that is being used, you can even enable/disable these checks in a deployed application by tweaking the log levels of your weblogic container. The JSF PhaseListener is smart enough to not even perform the serialization and digest calculation of logging levels are setup so that logging doesn't occur. This means you could even leave the loggers in there for production so you could still enable them when cluster replication issues occur.

The demo workspace includes a singe page application to demonstrate the DirtyScopePhaseListener. Simply run that page and press the button marked "change viewState without marking dirty". This will log an error in the console that neatly explains the internal state of myViewScopeBean in the ADF viewScope was changed:

Hopefully this JSF PhaseListener can be a valuable tool for anyone building a ADF application intended to run on a session-replicating cluster.

As always you can download the full sample application or browse the subversion repository to look at the source code. If you want to have a quick look at the solution start with the com.redheap.dirtyscope.DirtyScopePhaseListener phase listener and the com.redheap.dirtyscope.ADFScopeChecker class that does all the digest calculating and checking.

Monday, February 24, 2014

ADFLogger JAX-WS SoapHandler to log request, reponse and faults

Lately I see a lot of ADF projects consuming SOAP web services. This is typically done by creating a JAX-WS Proxy in JDeveloper and invoking this proxy from java beans exposed through the Bean Data Control or through programmatic ADF Business Components. This post will show how to instrument your JAX-WS proxy so it can log the SOAP request, payload and potential fault to an ADFLogger. This can be a very valuable tool during development and when diagnosing production issues.

Let's start with the final result, the weblogic console when invoking a web service that returns a soap fault. The nice thing is that it not only logs the fault but also the request that caused it:
SOAP request and response logged when receiving SOAP fault
When you crank up the log level you can even see all requests and responses that complete successful. As I described earlier this also allows for performance analysis with the Log Analyzer. This breaks down your entire request and our LoggingSoapHandler times the milliseconds it took to invoke the web service.
Log Analyzer showing this web service call took 5 msecs
This magic is performed by a JAX-WS SoapHandler. It can be registered with a JAX-WS proxy and has access to the web service request and response messages. Handlers can even change these, but in this example all we do is logging to the ADFLogger. You can setup handlers when creating the web service proxy or by right clicking an existing one and changing its properties.
Add LoggingSoapHandler as a Handler on the JAX-WS Proxy
You can get the full source code for the com.redheap.soaplog.LoggingSoapHandler class so you can add it to your own project or library. The embedded documentation is rather elaborate but I'll also explain the most important bits here.

Friday, January 3, 2014

Configuring ADF Faces for development

This post will describe how to configure your ADF Faces project for development through web.xml context parameters as well as enabling debug mode in trinidad-config.xml. It will also show how to override these settings for production deployment with a deployment plan even though the setting in trinidad-config.xml cannot be altered directly with a deployment plan.

More background information on all ADF Faces configuration parameters can be found in the appendix of the Web User Interface Developer's Guide. The ones we want to change during development are:
  • org.apache.myfaces.trinidad.CHECK_FILE_MODIFICATION to true to check for source files being modified on disk while the application is running and reloading them. Be sure to clear your browser cache after changing this value to clear out any old cached versions.
  • org.apache.myfaces.trinidad.resource.DEBUG to true to enable resource debugging and prevent the client from caching resources (eg javascript libraries, images, CSS, etc)
  • org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION to true to disable CSS content compression and use human-readable CSS class names for skinning
  • org.apache.myfaces.trinidad.DEBUG_JAVASCRIPT to true to non-obfuscated javascript
  • oracle.adf.view.rich.LOGGER_LEVEL to FINE to enable client side javascript logging. Other allowed values are SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, and ALL
  • oracle.adf.view.rich.ASSERT_ENABLED to true to enable client-side javascript assertions

Tuesday, November 19, 2013

JDeveloper Extension To Suppress Warnings

The JDeveloper auditing framework can be a very valuable tool in delivering high quality code. It not only gives you warnings and errors during development, but can also be run from the command-line on a build server. One thing that always annoyed me is the limited possibilities for suppressing individual warnings. Sure, there is the @SuppressWarnings annotation for Java code. JDeveloper 12c can even use this annotation to suppress any warning, not only the ones supported by the java compiler.

However, much of an ADF (or SOA) application is XML files, not java. JDeveloper 12c doesn't offer a way to suppress warnings in these files. Luckily the auditing framework is highly pluggable and after some inspection how the @SuppressWarning annotation is implemented in the auditing framework, I could create something similar for XML files.

Suppressing a warning in a JSF file

The screenshot above shows how the extension works. See the warning for the value property of the af:outputText component and how it marks this entire document as warning. Simply click the balloon in the gutter of the editor and select to suppress this warning. This adds a comment to the XML file to suppress the warning, very similar to a @SuppressWarnings annotation in java.

Suppressed warning in a JSF file
Notice how the document is now marked green an no more warnings appear. With this extension you can keep the number of warnings down so the real warnings get the attention they need.

I have plans on building a SonarQube extension to run ojaudit (the command line JDeveloper auditing tool) to keep track of your quality. Suppressing warnings can be especially valuable in that situation where you can use SonarQube to keep metrics and track unexpected warnings and errors.

The extension is already live, so simply start JDeveloper 12c and use the Help > Check for Updates feature. Be sure to check "Open Source and Partner Extensions". You should be able to find the "Suppress Audit Warnings" extension. Please leave a comment below if you have any questions or suggestions for a future version.

If you want to see how a custom suppression scheme is built you can download the full workspace or simply browse the subversion repository to look at the source code.

Wednesday, November 13, 2013

Overriding Entity doDML or prepareForDml Causes Locking Issues

It is not uncommon for people to override the doDML or prepareForDml method in an ADF BC Entity to do some additional work just before posting changes to the database. The official documentation even describes this extension point as being an equivalent to the Oracle Forms Post Processing triggers.
Today I discovered this can lead to locking issues in the database when this additional work changes other view objects or entities. The investigation is based on JDeveloper version 11.1.1.7 and this behavior might differ for other versions.

Update Nov 14: The issue doesn't reproduce in ADF 12.1.2.0. Inspecting of the source code seems to indicate (unpublished) bug 11896369 is to blame. Currently working with Oracle support to further investigate and ask for fix backport to 11.1.1.7

Update Jan 2: Oracle development acknowledged this behavior is caused by bug 11896369 and a backport request has been filed to bring the fix to 11.1.1.7.

Update Jan 10: Patch 11896369 is now available for download.

Let's start with an simplified example of an entity mutation another one. Below is the doDML method of the Department entity. Whenever a change happens to a department it sets the commission of its first employee to 99%. Not a very likely business scenario, but enough to demonstrate the issue.

@Override
protected void doDML(int i, TransactionEvent transactionEvent) {
    RowIterator employees = getEmployees();
    EmployeeImpl firstEmployee = (EmployeeImpl)employees.first();
    try {
        firstEmployee.setCommissionPct(new Number(0.99));
    } catch (SQLException e) {
        throw new JboException(e);
    }
    super.doDML(i, transactionEvent);
}

What we also need is a entity level validation on Employee that will be violated by this change. For demonstration purposes I've setup a range validation for CommissionPct to be between 0.00 and 0.50:
Entity-level Validation Rule

Now let's build a very simple ADF page to change a department and try to save the changes to the database. Here is what happens:
Validation Error in ADF Application

Everything appears to be okay. The user is confronted with the validation error as expected. But now let's try to update the same record from a different database session:
Database record locked after validation exception

Friday, November 8, 2013

Vodafone Content Tampering Making Sites Very Slow On Wi-Fi

I've had issues with this blog sometimes being very slow on my iPhone when using Wi-Fi. I finally figured out what is going and it seems like Vodafone (Netherlands) are to blame.

I noticed my browser is trying to download http://1.2.3.50/jsi/flash.php?file=gordon.js&max-age=3600 which never succeeds on Wi-Fi. A whois search seems to indicate the entire 1.2.3.0/24 address block is invalid and shouldn't be used on the public internet. All traffic to this address block is dropped along the route and it takes the browser (or TCP/IP stack) a full minute to give up and continu loading my blog. Strangely enough downloading this script on a Vodafone NL 3G connection does succeed.

But why is my client requesting this bizarre URL? It is actually part of http://googleads.g.doubleclick.net/pagead/blank.html which is used on my blog pages. When requesting this page over a Vodafone NL 3G mobile connection the content of this blank page is:
<html><script src="http://1.2.3.50/jsi/flash.php?file=gordon.js&max-age=3600" language="javascript"></script>
<body style="background-color: transparent"></body></html>

There it is; this blank.html page contains a script tag to load the mysterious resource from 1.2.3.50. When requesting this same blank.html from my Wi-Fi connection I get a trully blank page:
<html><body style="background-color: transparent"></body></html>

You don't really notice the difference while your are on Vodafone NL 3G network. Your browser will download the file from 1.2.3.50 and the site seems to function okay. But what happens when your device (re)connects to Wi-Fi? Google sends response headers with blank.html telling your browser it is okay to cache the page for 24 hours. So your device will simply use the cached (tampered) version of blank.html it retrieved through Vodafone's network. But now you are on Wi-Fi and your device can't load the file from 1.2.3.50 and the site is dead slow.

Okay, this is bad, but let's hope the problem clears after 24 hours. After all your browser is only allowed to cache the tampered blank.html page for 24 hours. Unfortunately the problem doesn't disappear after 24 hours. This is caused by Google sending an ETag response header with blank.html as well. An ETag is an opaque identifier assigned by a web server to a specific version of a resource found at a URL. If the resource content at that URL ever changes, a new and different ETag should be assigned. Google sending an ETag is a good thing, but Vodafone is altering the content so they should also change the ETag. Unfortunately they don't so your browser is caching this altered version under Google's original ETag. So even when the cache expires after 24 hours and your browser is asking for a fresh copy of blank.html it will include the ETag with this request. Whether you are on Wi-Fi or 3G, Google will always respond that blank.html hasn't changed since your request includes their original ETag. This instructs your browser to keep using the (tampered) cached version. In the end, you are stuck with the altered version of blank.html until you clear your browser cache.

Vodafone is altering pages I request from the internet and to make things worse they are altering them in such a way that these pages won't work outside of their network while allowing my browser to cache this crippled content. This really sucks! I want the real internet and not some crippled version! Vodafone support is acknowledging they are injecting javascript through a transparent proxy. They state the only way to get rid of this is to use a different APN setting on your mobile device which first has to be activated for your account through technical support. This sucks big time! Sure I can get my account fixed, but who knows how many more people are running into this issue without ever figuring out what is going on.

Hopefully this rant can help others understand what is going on when they see this failed downloads from the 1.2.3.50 or 1.2.3.4 IP address.