<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4865637371278230637</id><updated>2025-11-03T09:51:25.997+01:00</updated><category term="Selenium"/><category term="Test"/><category term="Testing"/><category term="ClientBehavior"/><category term="JSP"/><category term="JSPX"/><category term="ShowAlertBehavior"/><category term="TLD"/><category term="javascript"/><category term="EL expression"/><category term="ELContext"/><category term="PPR"/><category term="StringEscapeUtils"/><category term="ValueExpression"/><category term="WebDriver"/><category term="adf faces"/><category term="adf-js-features.xml"/><category term="components demo"/><category term="getBehavior"/><category term="getBehaviorExpression"/><category term="iterator"/><category term="org.apache.commons.lang"/><category term="partialPageRendering"/><title type='text'>Red Heap</title><subtitle type='html'>Oracle ADF &amp;amp; Fusion Middleware stuff by Wilfred van der Deijl</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.redheap.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://www.redheap.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>26</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-1280056024055053032</id><published>2015-10-09T13:31:00.003+02:00</published><updated>2016-01-15T09:32:23.595+01:00</updated><title type='text'>ADF Session Replication on a Cluster for High Availability</title><content type='html'>Running an ADF application on a weblogic cluster is fairly simple. Just deploy the application to the cluster and your done. This gives you scalability as the load is distributed over multiple managed servers. However, it does not give you protection against machine failure out of the box. For that to work, you need to make sure all state in your ADF application is replicated across multiple nodes in the cluster. This post will explain the things you have to think about when setting up this session replication.&lt;br /&gt;
&lt;br /&gt;
Most of this information is based on&amp;nbsp;&lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop/adf-web-high-availability.htm#ADFFD53964&quot; target=&quot;_blank&quot;&gt;Configuring High Availability for Fusion Web Applications&lt;/a&gt; chapter of the Fusion Web Applications Developer&#39;s Guide but we&#39;ve added some undocumented features and best practices based on our experience.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
View&lt;/h3&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;First thing you need to do is &lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop/adf-web-high-availability.htm#ADFFD53975&quot; target=&quot;_blank&quot;&gt;tell weblogic to replicate a http session&lt;/a&gt; to other nodes in the cluster. This is done by setting &lt;tt&gt;persistent-store-type&lt;/tt&gt; to &lt;tt&gt;replicated_if_clustered&lt;/tt&gt; in your &lt;tt&gt;weblogic.xml&lt;/tt&gt; file:
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;weblogic-web-app&amp;gt;
  &amp;lt;session-descriptor&amp;gt;
    &amp;lt;persistent-store-type&amp;gt;
      replicated_if_clustered
    &amp;lt;/persistent-store-type&amp;gt;
  &amp;lt;/session-descriptor&amp;gt;
&amp;lt;/weblogic-web-app&amp;gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;During development on my local workstation I like to set the &lt;a href=&quot;http://docs.oracle.com/cd/E24329_01/web.1211/e21049/weblogic_xml.htm#WBAPP587&quot; target=&quot;_blank&quot;&gt;session-description&lt;/a&gt; slightly differently:
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;weblogic-web-app&amp;gt;
  &amp;lt;session-descriptor&amp;gt;
    &amp;lt;persistent-store-type&amp;gt;file&amp;lt;/persistent-store-type&amp;gt;
    &amp;lt;persistent-store-dir&amp;gt;c:/temp/&amp;lt;/persistent-store-type&amp;gt;
    &amp;lt;cache-size&amp;gt;0&amp;lt;/cache-size&amp;gt;
  &amp;lt;/session-descriptor&amp;gt;
&amp;lt;/weblogic-web-app&amp;gt;
&lt;/pre&gt;
This tells weblogic to write the http session request to file after each request. Since the cache-size is set to 0 it will not keep any session in memory. This means each subsequent request from the same session has to restore the session from file first. Since this (de)serializes the http session on each request it behaves the same as a session failover on a cluster after each request. This is a great way to test if you application is really cluster-safe and if none of the managed beans or other objects will loose their state.&lt;/li&gt;
&lt;li&gt;In your web.xml you have to &lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop/adf-web-high-availability.htm#ADFFD53979&quot; target=&quot;_blank&quot;&gt;set CHECK_FILE_MODIFICATION to false&lt;/a&gt;:
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;web-app&amp;gt;
  ...
  &amp;lt;context-param&amp;gt;
    &amp;lt;param-name&amp;gt;
      org.apache.myfaces.trinidad.CHECK_FILE_MODIFICATION
    &amp;lt;/param-name&amp;gt;
    &amp;lt;param-value&amp;gt;false&amp;lt;/param-value&amp;gt;
  &amp;lt;/context-param&amp;gt;
&amp;lt;web-app&amp;gt;
&lt;/pre&gt;
Having this on could lead to errors when a failover occurs. It is best practice to disable this for a production system anyhow. If you want this on during local development you should look into deployment plans to override such a setting per environment.&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h3&gt;
Controller&lt;/h3&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Next thing you have to do is to &lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop/adf-web-high-availability.htm#ADFFD53977&quot; target=&quot;_blank&quot;&gt;tell the ADF Controller you&#39;re running in a replicated cluster&lt;/a&gt; so all managed beans will be replicated. You do this by setting &lt;tt&gt;adf-scope-ha-support&lt;/tt&gt; to &lt;tt&gt;true&lt;/tt&gt; in your &lt;tt&gt;adf-config.xml&lt;/tt&gt;:
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;adf-controller-config xmlns=&quot;http://xmlns.example.com/adf/controller/config&quot;&amp;gt;
    &amp;lt;adf-scope-ha-support&amp;gt;true&amp;lt;/adf-scope-ha-support&amp;gt;
&amp;lt;/adf-controller-config&amp;gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;If you&#39;re application is also using database based MDS and that database is also a (RAC) cluster you need to tell the ADF Controller to retry any failed database connection in case a database failover occurs. You do this in the &lt;tt&gt;persistence-config&lt;/tt&gt; section of &lt;tt&gt;adf-config.xml&lt;/tt&gt; where you already configured MDS:
&lt;pre class=&quot;brush:xml;highlight:6&quot;&gt;&amp;lt;persistence-config&amp;gt;
  &amp;lt;metadata-namespaces&amp;gt;...
  &amp;lt;metadata-store-usages&amp;gt;...
  &amp;lt;external-change-detection enabled=&quot;false&quot; /&amp;gt;
  &amp;lt;read-only-mode enabled=&quot;true&quot;/&amp;gt;
  &amp;lt;retry-connection enabled=&quot;true&quot;/&amp;gt;
&amp;lt;/persistence-config&amp;gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Managed beans that live longer than a single request need to implement &lt;a href=&quot;http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html&quot; target=&quot;_blank&quot;&gt;Serializable&lt;/a&gt; to enable them to transfer &quot;over the wire&quot; to other nodes in the cluster. This means this is not needed for request-scope and backingbean-scope beans as the do not live longer than a single request and will not be replicated to other nodes in the cluster. You do need to do this for every viewScope, pageFlowScope and sessionScope bean.&lt;/li&gt;
&lt;li&gt;According to the &lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop/adf-ui-get-started.htm#ADFFD22271&quot; target=&quot;_blank&quot;&gt;documentation&lt;/a&gt; you need to let the ADF Controller know each time a managed bean changes so it knows to replicate that bean (or that scope) to the other node in the cluster. You have to do this by invoking &lt;a href=&quot;https://docs.oracle.com/middleware/1213/adf/api-reference-controller/oracle/adf/controller/ControllerContext.html#markScopeDirty(java.util.Map)&quot; target=&quot;_blank&quot;&gt;ControllerContext.markScopeDirty&lt;/a&gt;&amp;nbsp;and giving it the viewScope or pageFlowScope that contains the changed bean. This sounds like a useful performance optimization that only the changed scopes are replicated across the cluster. However, if you inspect the source code it doesn&#39;t really matter which scope you pass to the markScopeDirty. It sets a global flag on the request that will replicate all ADF Controller scopes at the end of the request, not just the ones that you marked dirty. Obviously this might change in a future version so you&#39;re safest bet is to nicely invoke markScopeDirty whenever you change a bean. One other caveat is that ADF (at least version 12.1.3) internally always changes two internal values in a scope in every request. This means that ADF internally invokes markScopeDirty on each request which means all scopes are replicated on each request regardless what you do. We&#39;ve filed bugs for this so this might also change in the future and you shouldn&#39;t rely on these bugs and assume that everything is replicated anyhow.&lt;br /&gt;I typically create a number of base classes that I use as superclasses for all of my viewScope or pageFlowScope beans. Than all you need to do is invoke markDirty from the superclass in each setter or other method that alters the state of its bean:
&lt;pre class=&quot;brush:java&quot;&gt;public abstract class ManagedBean implements Serializable {
  public ManagedBean() {
    /* Workaround voor Oracle bug #18508781. When bean is
       instantiated by the scope itself on first usage it
       does not automatically mark the scope as dirty
       even though the documentation states it does */
     markDirty();
  }
  protected void markDirty() {
    ControllerContext.getInstance().markScopeDirty(getScope());
  }
  // use this in a setter to only mark dirty if a property really changes
  protected void markDirty(Object oldValue, Object newValue) {
    if (!((oldValue == null &amp;amp;&amp;amp; newValue == null) ||
          (oldValue != null &amp;amp;&amp;amp; newValue != null &amp;amp;&amp;amp;
           oldValue.equals(newValue)))) {
      markDirty();
    }
  }
  // should return the scope map the managed bean lives in
  protected abstract Map&amp;lt;String, Object&amp;gt; getScope();
}
&lt;/pre&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class ViewScopeBean extends ManagedBean {
  @Override
  protected Map&amp;lt;String, Object&amp;gt; getScope() {
    return ADFContext.getCurrent().getViewScope();
  }
}
&lt;/pre&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class PageFlowScopeBean extends ManagedBean {
  @Override
  protected Map&amp;lt;String, Object&amp;gt; getScope() {
    return ADFContext.getCurrent().getPageFlowScope();
  }
}&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;font-family: monospace;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;h3&gt;
Model&lt;/h3&gt;
&lt;div&gt;
Finally you also need to make sure the state (data) in your ADF data controls is replicated across the cluster. This is not handled by the normal state replication by the http session or the ADF controller. It is the responsibility of the data control itself.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
ADF Business Components&lt;/h4&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;For ADF Business Components you only have to change jbo.dofailover in the bc4j.xcfg configuration file. This is easiest done through the&lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop/adf-web-high-availability.htm#ADFFD53973&quot; target=&quot;_blank&quot;&gt; declarative editors in JDeveloper&lt;/a&gt;. Alternatively you could also set this as a system property on the command line to start your weblogic server: &lt;tt&gt;-Djbo.dofailover=true&lt;/tt&gt;&lt;br /&gt;This ensures that ADF business components writes it entire state to a XML document at the end of each request so that other nodes in the cluster can read the XML and continue the session. You can &lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop/adf-bc-state-management.htm#ADFFD1305&quot; target=&quot;_blank&quot;&gt;configure&lt;/a&gt; whether this state is saved to a shared filesystem that all nodes in the cluster can access or to a shared database. You do this by setting &lt;tt&gt;jbo.passivationstore&lt;/tt&gt; to either &lt;tt&gt;file&lt;/tt&gt; or &lt;tt&gt;database&lt;/tt&gt;, where database is the default. When persisting to a&amp;nbsp;database it is advised to &lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop/adf-bc-state-management.htm#ADFFD1307&quot; target=&quot;_blank&quot;&gt;setup a special JDBC datasource&lt;/a&gt; to be used for this using the &lt;tt&gt;jbo.server.internal_connection&lt;/tt&gt; property. If you do not set one the normal datasource of your ADF BC application module will be used to save this state. Having a dedicated datasource for state saving allows you to store this in a different database schema or tune the datasource for this behaviour.&lt;br /&gt;Also be sure to &lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop/adf-bc-state-management.htm#ADFFD1309&quot; target=&quot;_blank&quot;&gt;periodically clean up&lt;/a&gt; this persisted ADF business components state for situations where ADF BC failed to clean it up automatically. On a file system this is fairly straightforward and for database storage Oracle supplies a &lt;tt&gt;adfbc_purge_statesnapshots.sql&lt;/tt&gt; script in your &lt;tt&gt;oracle_common/common/sql&lt;/tt&gt; directory.&lt;/li&gt;
&lt;li&gt;When using the database as a store for ADF Business Component state and the database is also a cluster or some other type of database that supports failover, be sure to &lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop/adf-web-high-availability.htm#ADFFD53971&quot; target=&quot;_blank&quot;&gt;use a GridLink data source&lt;/a&gt; for state passivation as GridLink data sources are capable of switching between nodes in a database cluster when a failover of the database node occurs.&lt;/li&gt;
&lt;li&gt;The same applies for the normal data source used by ADF BC to get your business data. If it connects to a clustered database it should be using a GridLink data source to support failover.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h4&gt;
Data Controls that are not ADF BC&lt;/h4&gt;
&lt;div&gt;
When you are not using ADF Business Components, but another type of ADF Data Control like the bean data control or the &lt;a href=&quot;https://adfxmldc.atlassian.net/wiki/&quot; target=&quot;_blank&quot;&gt;XML Data Control&lt;/a&gt; things get a bit more complicated. As stated before the datacontrol is responsible for replicating its state across a cluster. The Oracle documentation even describes how a &lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop-data-controls/data-controls-bean.htm#ADFDC751&quot; target=&quot;_blank&quot;&gt;datacontrol should create and restore snapshots&lt;/a&gt;. Unfortunately this doesn&#39;t really work in real life, at least not in version 12.1.3 and earlier (this might be fixed in future versions). The reason behind this is that a data control can replicate its state using this method but your ADF Model is more than just the raw data. It is also the state of every iterator in your page that &quot;knows&quot; which row in a collection is the current row. These iterators are not implemented by the data controls themselves but are supplied by the ADF framework. In fact, ADF uses an ADF Business Components wrapper around each non-BC data control to get these iterators, the so called &lt;tt&gt;InternalDCAM&lt;/tt&gt; (internal data control application module).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
This made us wonder if we can get this &lt;tt&gt;InternalDCAM&lt;/tt&gt; to also replicate its state across a cluster. Since it is just an ADF Business Components Application Module we might have a chance. Since this is an internal application module there is no &lt;tt&gt;bc4j.xcfg&lt;/tt&gt; configuration file that is normally used to configure ADF Business Components. But you can also use system properties to set the default for ADF BC configuration and these defaults should also be used for this internal application module. For this we added a number of system properties to the weblogic startup script:&lt;br /&gt;
&lt;tt&gt;-Djbo.dofailover=true -Djbo.passivationstore=file -Djbo.tmpdir=C:\work\wlssessions\ -Doracle.adf.model.bean.supports-passivation=true&lt;/tt&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Here&#39;s the reasoning behind these system properties:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;jbo.dofailover=true&lt;/tt&gt; enables the failover behaviour of ADF BC to write its state to XML after each request&lt;/li&gt;
&lt;li&gt;we force &lt;tt&gt;jbo.passivationstore&lt;/tt&gt; to &lt;tt&gt;file&lt;/tt&gt; to write the session state to the file system and not to the database. Looking at &lt;tt&gt;oracle.adf.model.bean.DCBeanDataControl#findApplicationPool&lt;/tt&gt; we discovered that writing to the database for a non-BC data control isn&#39;t supported anyhow which makes sense.&lt;/li&gt;
&lt;li&gt;when writing the state to the file system we also set &lt;tt&gt;jbo.tmpdir&lt;/tt&gt; to specify the directory where to save these files&lt;/li&gt;
&lt;li&gt;finally, we set &lt;tt&gt;oracle.adf.model.bean.supports-passivation=true&lt;/tt&gt; to enable ADF BC state passivation for non-BC data controls. This seems to be an experimental feature as there is no documentation about this parameter. This system property is not yet supported in 11.1.1.7 but it does exist in 12.1.3. This seems to be the missing link that enables state passivation for non-BC data controls&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
We found that for simple data controls this actually works. Having &lt;tt&gt;oracle.adf.model.bean.supports-passivation&lt;/tt&gt; to enable the &lt;tt&gt;InternalDCAM&lt;/tt&gt; to passivate its state in combination with having the &lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop-data-controls/data-controls-bean.htm#ADFDC751&quot; target=&quot;_blank&quot;&gt;data control itself save and restore its state&lt;/a&gt; makes this work on a failing cluster. This can easily be demonstrated with the tip at the beginning of this article to use a file based weblogic http session store without any in-memory caching. Unfortunately when having a data control with more than one level this will fail with an exception. For example, you could have a bean data control or &lt;a href=&quot;https://adfxmldc.atlassian.net/wiki/&quot; target=&quot;_blank&quot;&gt;XML Data Control&lt;/a&gt; with a &lt;tt&gt;findAllDepartments()&lt;/tt&gt; method. That method returns a collection of departments. Each department has a collection of employees and each of those employees has a collection of accounts. In such a scenario with nested collections the failover of the iterators in the &lt;tt&gt;InternalDCAM&lt;/tt&gt; will fail with missing parent key relations and throws &lt;tt&gt;ArrayIndexOutOfBoundsException&lt;/tt&gt;. Perhaps this is the reason why &lt;tt&gt;oracle.adf.model.bean.supports-passivation&lt;/tt&gt; is an undocumented feature. Let&#39;s hope Oracle will fully support this in a future release and it will also work with these more complex data controls. Until then, I guess you&#39;re out of luck for replicating your ADF application state in a cluster when using anything else than ADF Business Components.&lt;br /&gt;
&lt;br /&gt;
Without the &lt;tt&gt;oracle.adf.model.bean.supports-passivation&lt;/tt&gt; system property things get even worse. Since the &lt;tt&gt;InternalDCAM&lt;/tt&gt; is not replicating its state without this property, it will reset all iterators to the first row even though the underlying data control might have replicated its state. This means a user might haven been working on row 5 in a collection. When a failover occurs the server-side iterator resets to row 1, but the user still sees row 5 in his browser. Any changes made by the user are submitted to the server and applied to row 1 without any error message or warning, leading to data corruption.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;
Networking&lt;/h3&gt;
&lt;div&gt;
One final word about the networking architecture in front of your multi-node weblogic cluster. Since failover of a session to a different node in the cluster is relatively expensive we want to prevent this as much as possible and only move a session to a different node when the original node really fails. When the node stays up we should do our best to route each request for the same session to the same node. This is known as session stickiness. When you use an Oracle HTTP Server in front of your weblogic cluster this is handled automatically. Oracle HTTP server knows about the weblogic cluster architecture and will try to route each request. By the way, you might want to look in the &lt;a href=&quot;https://docs.oracle.com/cd/E21764_01/web.1111/e16435/plugin_params.htm#PLGWL473&quot; target=&quot;_blank&quot;&gt;mod_weblogic plugin parameters&lt;/a&gt; to fine tune the clustering behaviour and perhaps change some of the timeout settings.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
When not using an Oracle HTTP server, but for example a hardware load balancer that directly routes to the weblogic cluster you need to ensure session stickiness yourself. You need to learn your load balancer about the structure of a &lt;a href=&quot;http://www.bea-weblogic.com/weblogic-server-support-pattern-common-diagnostic-process-for-proxy-plug-in-problems.html&quot; target=&quot;_blank&quot;&gt;weblogic session cookie&lt;/a&gt;. The format of a session cookie is &lt;tt&gt;sessionid!primary_server_id!secondary_server_id&lt;/tt&gt;. The load balancer should be able to pick up the id of the primary server between the two exclamation points and use that id to route each request to that primary server. Only when that server fails it should use the id of the secondary server and route the request to that server as that server is the one that already has the replicated session in memory. If you would route to any other node in the cluster it would still work but it would add the delay of first getting the state from another node in the cluster. By the way, once a session has failed over to a different node the client will get a new session cookie with new server id&#39;s that can be used in routing subsequent requests.&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/1280056024055053032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2015/10/adf-session-replication-ha-cluster.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/1280056024055053032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/1280056024055053032'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2015/10/adf-session-replication-ha-cluster.html' title='ADF Session Replication on a Cluster for High Availability'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-7120007597793018337</id><published>2015-02-17T23:20:00.000+01:00</published><updated>2017-02-01T08:06:14.553+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="adf faces"/><category scheme="http://www.blogger.com/atom/ns#" term="components demo"/><category scheme="http://www.blogger.com/atom/ns#" term="Selenium"/><title type='text'>ADF Faces 12c Components Demo and Test Automation</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
You might have noticed that I am working on a &lt;a href=&quot;http://www.redheap.com/search/label/Selenium&quot; target=&quot;&quot;&gt;series of blog articles&lt;/a&gt; on using &lt;a href=&quot;http://www.seleniumhq.org/&quot; target=&quot;_blank&quot;&gt;Selenium&lt;/a&gt; to automate testing of Oracle ADF applications. This includes work on a &lt;a href=&quot;https://github.com/wvanderdeijl/adf-selenium&quot; target=&quot;_blank&quot;&gt;little framework&lt;/a&gt; to make this easier and a set of sample JUnit tests against the public&amp;nbsp;&lt;a href=&quot;http://jdevadf.oracle.com/adf-richclient-demo&quot; target=&quot;_blank&quot;&gt;Oracle ADF Faces 12c Components Demo&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Getting the Faces 12c Component Demo running with test automation had some challenges. I wanted to write them down here in case somebody wants to try the same. It starts by downloading the &lt;a href=&quot;http://www.oracle.com/technetwork/developer-tools/adf/downloads/index.html&quot; target=&quot;_blank&quot;&gt;Oracle ADF Faces Components Demo&lt;/a&gt; from OTN. This also includes &lt;a href=&quot;http://www.oracle.com/technetwork/developer-tools/adf/documentation/adf-faces-rc-demo-083799.html&quot; target=&quot;_blank&quot;&gt;instructions&lt;/a&gt; on how to run this application in your integrated weblogic server, but those instructions have some caveats and are for JDeveloper 11g, not version 12c. Please follow the instructions below as an alternative (I&#39;ve marked the differences with the normal Oracle instructions and included screenshots at the end).&lt;br /&gt;
&lt;br /&gt;
In the end this needed more work than I expected, so I also offer the fixed versions for download. If anyone from Oracle feels that this is a problem please contact me and I&#39;ll remove the download and you can follow the instructions below to create your own fixed version.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://drive.google.com/file/d/0B0EvDYuyTjZzYnlVSjFlYnhucFE/view?usp=sharing&quot; target=&quot;_blank&quot;&gt;JDeveloper 12.1.3 project&lt;/a&gt; if you want to make changes to it&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://drive.google.com/file/d/0B0EvDYuyTjZzM1A3X1FWXzltUjA/view?usp=sharing&amp;amp;authkey=CNbq-OQL&quot; target=&quot;_blank&quot;&gt;ADF 12.1.3 deployable WAR&lt;/a&gt; that you can just deploy on your integrated weblogic or any other weblogic server&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://drive.google.com/file/d/0B0EvDYuyTjZzeHByNW1hZVQtaE0/view?usp=sharing&amp;amp;authkey=CLbMpNIM&quot; target=&quot;_blank&quot;&gt;JDeveloper 12.2.1 project&lt;/a&gt; if you want to make changes to it&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://drive.google.com/file/d/0B0EvDYuyTjZzbFZpQ1FtTWpONzg/view?usp=sharing&amp;amp;authkey=CJzezMcM&quot; target=&quot;_blank&quot;&gt;ADF 12.2.1 deployable WAR&lt;/a&gt; that you can just deploy on your integrated weblogic or any other weblogic server&lt;/li&gt;
&lt;/ul&gt;
If you want to start from the downloads from Oracle and not use my fixed versions you would have to follow these steps:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://www.oracle.com/technetwork/developer-tools/adf/downloads/index.html&quot; target=&quot;_blank&quot;&gt;Download&lt;/a&gt; the ADF Faces 12c Components Demo WAR file, but don&#39;t unpack it.&lt;/li&gt;
&lt;li&gt;Start JDeveloper 12.1.3&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Instructions updated from 11g&lt;/i&gt;: Choose File &amp;gt; New &amp;gt; From Gallery from the menu to create a new application. Select General &amp;gt; Applications in the tree and select Custom Application as application type and press Ok.&lt;/li&gt;
&lt;li&gt;In the Create Application dialog type adffacesdemo as the application name, select a directory, leave the rest of the options alone and press Finish. This creates new application workspace and project.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Instructions updated from 11g:&amp;nbsp;&lt;/i&gt;The default created project is not needed and you may delete the project. Right click it and select Delete Project. In the subsequent dialog choose to not only delete the project form the application but also delete it from disk.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Instructions updated from 11g&lt;/i&gt;: In the now empty workspace choose File &amp;gt; New &amp;gt; From Gallery from the JDeveloper menu. In the list of items select Projects and on the right hand side Project from WAR and press Ok. In the next dialog provide a name for the project, e.g. adffacesdemo, and keep the directory information. On the second panel, use the file browser to select the downloaded ADF Faces demo WAR file and finish the wizard.&lt;/li&gt;
&lt;li&gt;Double click onto the project node to open the project properties and select the Run &amp;gt; Debug &amp;gt; Profile option. Press the Edit button and select the Tool Settings. In the Before Running section, uncheck the Make Project and Dependencies option and close the dialog pressing Ok.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Extra step added by me&lt;/i&gt;: Unfortunately some files are missing from the exploded WAR which will result in javascript errors and missing images.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Manually copy the META-INF directory from the src directory to the classes directory so you end up with classes/META-INF&lt;/li&gt;
&lt;li&gt;Copy the src/oracle/adfdemo/view/js directory (and all of its subdirectories) to classes/oracle/adfdemo/view/js&lt;/li&gt;
&lt;li&gt;Copy the two .properties files from src/oracle/adfdemo/view/resource to classes/oracle/adfdemo/view/resource&lt;/li&gt;
&lt;li&gt;Copy the&amp;nbsp;src/oracle/adfdemo/view/resource/fileExplorer directory and the .properties file it contains to classes/oracle/adfdemo/view/resource/fileExplorer&lt;/li&gt;
&lt;li&gt;Copy all xml file from src/oracle/adfdemo/view/components/rich/tageditor to&amp;nbsp;classes/oracle/adfdemo/view/components/rich/tageditor&lt;/li&gt;
&lt;li&gt;Copy the xml and csv file from src/oracle/adfdemo/view/feature/rich/diagram/data to classes/oracle/adfdemo/view/feature/rich/diagram/data&lt;/li&gt;
&lt;li&gt;Copy the src/oracle/adfdemo/view/feature/rich/dvt/data/election directory to classes/oracle/adfdemo/view/feature/rich/dvt/data/election&lt;/li&gt;
&lt;li&gt;Copy all xml files from src/oracle/adfdemo/view/feature/rich/hv to classes/oracle/adfdemo/view/feature/rich/hv&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;i&gt;Extra step added by me&lt;/i&gt;: To be able to use test automation on this ADF sample application, enable automation by opening public_html/WEB-INF/web.xml in JDeveloper and remove the comment markers around the existing &lt;a href=&quot;http://www.redheap.com/2015/02/configuring-adf-project-for-selenium.html&quot;&gt;oracle.adf.view.rich.automation.ENABLED&lt;/a&gt; context parameter.&lt;br /&gt;For test automation to work you also have to&amp;nbsp;copy JDEV_HOME/oracle_common/modules/oracle.adf.view_12.1.3/adf-richclient-automation-11.jar to the&amp;nbsp;&amp;nbsp;public_html/WEB-INF/lib directory of the project.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Extra step added by me&lt;/i&gt;: As a final step I prefer a simple URL when running the application. Double click the project to open the project properties. In the Java EE Application section change both the application name and context root to adf-richclient-demo&lt;/li&gt;
&lt;li&gt;Finally, expand the project and select index.jspx under the Web Content node. Choose Run from the right mouse context menu.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Screenshots of these steps are below for your reference:&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikDyaktAKGAfZma1Z27TojNmQk6P5tYER4TBiMwVeoeAaN9lmyONlRhxAGEs2rIa7J4Vf60k8hfKG7FU2in4MtNznXGqnx7ft2npE0huisovAtAkxojxJcMhUJABfuCTzLAHaXhmhSMN0/s1600/Snap14.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;285&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikDyaktAKGAfZma1Z27TojNmQk6P5tYER4TBiMwVeoeAaN9lmyONlRhxAGEs2rIa7J4Vf60k8hfKG7FU2in4MtNznXGqnx7ft2npE0huisovAtAkxojxJcMhUJABfuCTzLAHaXhmhSMN0/s1600/Snap14.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;New Gallery dialog to create Custom Application&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQVgUgopgLK2ZMfg0KEBen6y5vKR8BaAY1kGSSW2orrQR_5fLCwa9sz1WjVmGYWe6BPq3A_brOYpX3gSWSVF0sDK-uV4WFh4zkkaoJS49roZfUf2Wwvje0h5utsPMfJSl_8xqZUfPGH1U/s1600/Snap15.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;300&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQVgUgopgLK2ZMfg0KEBen6y5vKR8BaAY1kGSSW2orrQR_5fLCwa9sz1WjVmGYWe6BPq3A_brOYpX3gSWSVF0sDK-uV4WFh4zkkaoJS49roZfUf2Wwvje0h5utsPMfJSl_8xqZUfPGH1U/s1600/Snap15.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Create Custom Application dialog&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQdYzU837DL5WdH_ENTu0jZg2T9x0_TR8nrOgNBlKMJ8Tux-NdrHupxm6qu9mrcIrei3-hCdG-LyJIQAgAm1VuPV6ugvc5qAEkZxxeExxMvWhrEvZ9O_fsMGIzE_IVBaOuNnV5BgMnSDw/s1600/Snap16.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;173&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQdYzU837DL5WdH_ENTu0jZg2T9x0_TR8nrOgNBlKMJ8Tux-NdrHupxm6qu9mrcIrei3-hCdG-LyJIQAgAm1VuPV6ugvc5qAEkZxxeExxMvWhrEvZ9O_fsMGIzE_IVBaOuNnV5BgMnSDw/s1600/Snap16.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Delete the default project&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvI-weQJ5IOBHoVdnqpCBXu7Mu9TNPEgOxOYqEw7tVlQc7LpqHArwZxhTzAgb24ZATLW2fSMYKknpICbl1_s26ieOCuifs2JJCX0cvI57H6sBBiIMUnh7hc0Usj87HKJa_ZQkHPKGkqYY/s1600/Snap17.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;173&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvI-weQJ5IOBHoVdnqpCBXu7Mu9TNPEgOxOYqEw7tVlQc7LpqHArwZxhTzAgb24ZATLW2fSMYKknpICbl1_s26ieOCuifs2JJCX0cvI57H6sBBiIMUnh7hc0Usj87HKJa_ZQkHPKGkqYY/s1600/Snap17.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Delete the default project from disk&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiY-eTSYf6x7g_nfoEg6K3RAQqR0JkrV1KV5LQN3lIycmWK5snaySxsN5kBeyjPGqN_Enwr3DuUVQL42pSnNldIzxnYH48d3Viyl2uX0vw6wCqyD09kark8n7WGgdwCptXCvSmwCUrJV4/s1600/Snap18.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;285&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiY-eTSYf6x7g_nfoEg6K3RAQqR0JkrV1KV5LQN3lIycmWK5snaySxsN5kBeyjPGqN_Enwr3DuUVQL42pSnNldIzxnYH48d3Viyl2uX0vw6wCqyD09kark8n7WGgdwCptXCvSmwCUrJV4/s1600/Snap18.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Create new project from WAR&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqb7HAMURg5yDWLO8x21ucpwWEfb0BwwEZRAV1AdqPUmx90GQV1feav_-WeI-ahwGByzAWNL-dUHmelFA8sVyJgEcPXacfGKZRfKj5_LjyB3SLG5U8omFG3wdgkcT_WhOnAG8QHxYy3iM/s1600/Snap19.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;300&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqb7HAMURg5yDWLO8x21ucpwWEfb0BwwEZRAV1AdqPUmx90GQV1feav_-WeI-ahwGByzAWNL-dUHmelFA8sVyJgEcPXacfGKZRfKj5_LjyB3SLG5U8omFG3wdgkcT_WhOnAG8QHxYy3iM/s1600/Snap19.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Step 1 of importing WAR&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPN7PvNzF6U8KgxXGUe7qmcsdrutPzTP5KGv0IWGd8WKIuHKMWS0dDVNfxAFzTWuh4mKbWtmikOwb4pemoDeL3b-n9xOxRELs9T8tHPx6YBgRJh-z74MJN3HxBBZSBBqqlwMbYGOW80j4/s1600/Snap20.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;300&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPN7PvNzF6U8KgxXGUe7qmcsdrutPzTP5KGv0IWGd8WKIuHKMWS0dDVNfxAFzTWuh4mKbWtmikOwb4pemoDeL3b-n9xOxRELs9T8tHPx6YBgRJh-z74MJN3HxBBZSBBqqlwMbYGOW80j4/s1600/Snap20.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Step 2 of importing WAR&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiaZzw5ua1wU7zyS7vVzvVlGdfFRbu9Y1awnzIlSkctbEJ1Q64_72bez2mdNJ48I6ig3K3jIvupI-OcESUS6l3fd2Ewp2VwGnL4IS3WgG6KGV7QhHgiG6lgsFjuCMGmlj4Gfak-cgvyh8/s1600/Snap21.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;300&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiaZzw5ua1wU7zyS7vVzvVlGdfFRbu9Y1awnzIlSkctbEJ1Q64_72bez2mdNJ48I6ig3K3jIvupI-OcESUS6l3fd2Ewp2VwGnL4IS3WgG6KGV7QhHgiG6lgsFjuCMGmlj4Gfak-cgvyh8/s1600/Snap21.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Disable Make Project in Run Profile&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigutcFrIO3Pkp9uFDgkcheWW3i7fZMvVj0oljbOtd6stm12m2GAddfiK685vDDVc-UbLMI8C2Geu4MIIYrHln3XOtBnHiA-GfqIFlO2Z5qox1EwVmi4CH7_Mj6dOjTzMtYiWku_jgyuGo/s1600/Snap22.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;187&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigutcFrIO3Pkp9uFDgkcheWW3i7fZMvVj0oljbOtd6stm12m2GAddfiK685vDDVc-UbLMI8C2Geu4MIIYrHln3XOtBnHiA-GfqIFlO2Z5qox1EwVmi4CH7_Mj6dOjTzMtYiWku_jgyuGo/s1600/Snap22.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Uncomment/activate existing&amp;nbsp;oracle.adf.view.rich.automation.ENABLED&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhncZ6hpi8DWqntODlChsqJ53IhqHIkSrjzPsKHDEoVupajoktjTgqRiTD2E93n-nnFKEWBltmWicZwiJx2jhlnuqRghoh-8JGbC2npzpTzdRqJeKUQfG6EqUYa1Dg1F1Db290bQQ3G4uM/s1600/Snap23.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;287&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhncZ6hpi8DWqntODlChsqJ53IhqHIkSrjzPsKHDEoVupajoktjTgqRiTD2E93n-nnFKEWBltmWicZwiJx2jhlnuqRghoh-8JGbC2npzpTzdRqJeKUQfG6EqUYa1Dg1F1Db290bQQ3G4uM/s1600/Snap23.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Add&amp;nbsp;adf-richclient-automation-11.jar to public_html/WEB-INF/lib&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFpHFhi3vnT2KAPbabiSNQAT8Mq_OG3eUbeehGxisRAbHEGCTqzhsTWtPUu_mnMSfGEkzRtkFAtcBEYUz50NMr_GYwyu5K59U7S-T9Os2ZhVPL9K2n1CAc2iDbKMKmEMelVZnmCErJ9Qo/s1600/Snap24.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;285&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFpHFhi3vnT2KAPbabiSNQAT8Mq_OG3eUbeehGxisRAbHEGCTqzhsTWtPUu_mnMSfGEkzRtkFAtcBEYUz50NMr_GYwyu5K59U7S-T9Os2ZhVPL9K2n1CAc2iDbKMKmEMelVZnmCErJ9Qo/s1600/Snap24.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Setting application name and context root in project properties&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;div&gt;
This post is part of a&amp;nbsp;&lt;a href=&quot;http://www.redheap.com/search/label/Selenium&quot;&gt;series on how to get Selenium to work&lt;/a&gt;&amp;nbsp;with Oracle ADF.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/7120007597793018337/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2015/02/adf-faces-12c-components-demo-test-automation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/7120007597793018337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/7120007597793018337'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2015/02/adf-faces-12c-components-demo-test-automation.html' title='ADF Faces 12c Components Demo and Test Automation'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikDyaktAKGAfZma1Z27TojNmQk6P5tYER4TBiMwVeoeAaN9lmyONlRhxAGEs2rIa7J4Vf60k8hfKG7FU2in4MtNznXGqnx7ft2npE0huisovAtAkxojxJcMhUJABfuCTzLAHaXhmhSMN0/s72-c/Snap14.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-5049074012099215599</id><published>2015-02-15T16:05:00.001+01:00</published><updated>2015-02-15T16:05:06.357+01:00</updated><title type='text'>ADFLogger 12.1.3 ignoring message parameters and resource keys</title><content type='html'>In JDeveloper 12.1.3 Oracle made a switch to a new log formatter that has its shortcomings. It no longer knows how to replace resource bundle keys with their actual message and also fails to replace the &lt;code&gt;{0}&lt;/code&gt;, &lt;code&gt;{1}&lt;/code&gt;, ... placeholders with their actual values. You can end up with logging looking like this:&lt;br /&gt;
&lt;pre class=&quot;brush:plain&quot;&gt;&amp;lt;oracle.adf.view&amp;gt; &amp;lt;RichRenderKit&amp;gt; &amp;lt;isAutomationEnabled&amp;gt; &amp;lt;AUTOMATION_ENABLED_WITHOUT_AUTOMATION_JAR&amp;gt; 
&amp;lt;oracle.adf.common&amp;gt; &amp;lt;ADFConfigFactory&amp;gt; &amp;lt;findOrCreateADFConfig&amp;gt; &amp;lt;Resource {0} not found on the classpath.&amp;gt; 
&lt;/pre&gt;
&lt;br /&gt;
Notice the &lt;code&gt;AUTOMATION_ENABLED_WITHOUT_AUTOMATION_JAR&lt;/code&gt; that is not replaced with its actual message as well as the &lt;code&gt;Resource {0}...&lt;/code&gt; message which should clearly mention the missing resource.&lt;br /&gt;
&lt;br /&gt;
I don&#39;t know how this made it past basic QA, but this is now the default configuration for your Integrated WebLogic server in JDeveloper 12.1.3. Luckily there is an easy fix to revert to the 12.1.2 behaviour which is working fine.&lt;br /&gt;
&lt;br /&gt;
Either start your integrated weblogic server in JDeveloper and click the actions button the log window and select &lt;code&gt;Configure Oracle Diagnostics Logging&lt;/code&gt; or directly edit the &lt;code&gt;JDEV_USER_HOME/system12.1.3.0.41.140521.1008/DefaultDomain/config/fmwconfig/servers/DefaultServer/logging.xml&lt;/code&gt; file.&lt;br /&gt;
&lt;br /&gt;
Find the &lt;code&gt;log_handler&lt;/code&gt; declaration at the beginning of the file for the &lt;code&gt;console-handler&lt;/code&gt;. Change its &lt;code&gt;formatter&lt;/code&gt; attribute from &lt;code&gt;oracle.adf.share.logging.internal.diagnostic.ConsoleFormatter&lt;/code&gt; to &lt;code&gt;oracle.core.ojdl.weblogic.ConsoleFormatter&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
Restart your integrated weblogic server for the changes to take effect. You can now notice the resource keys and message parameters are correctly replaced:&lt;br /&gt;
&lt;pre class=&quot;brush:plain&quot;&gt;&amp;lt;Feb 15, 2015 3:59:01 PM CET&amp;gt; &amp;lt;Warning&amp;gt; &amp;lt;oracle.adfinternal.view.faces.renderkit.rich.RichRenderKit&amp;gt; &amp;lt;ADF_FACES-60118&amp;gt; &amp;lt;Your application is running with the automation enabled in your web.xml file but the automation jar is unavailable. Please ensure that the jar is in the classpath.&amp;gt; 
&amp;lt;Feb 15, 2015 3:59:01 PM CET&amp;gt; &amp;lt;Warning&amp;gt; &amp;lt;oracle.adf.share.config.ADFConfigFactory&amp;gt; &amp;lt;BEA-000000&amp;gt; &amp;lt;Resource META-INF/adf-config.xml not found on the classpath.&amp;gt; 
&lt;/pre&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/5049074012099215599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2015/02/adflogger-1213-message-parameters-resource-keys.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/5049074012099215599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/5049074012099215599'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2015/02/adflogger-1213-message-parameters-resource-keys.html' title='ADFLogger 12.1.3 ignoring message parameters and resource keys'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-2251951326236255912</id><published>2015-02-08T13:52:00.000+01:00</published><updated>2015-02-11T23:55:29.867+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="partialPageRendering"/><category scheme="http://www.blogger.com/atom/ns#" term="PPR"/><category scheme="http://www.blogger.com/atom/ns#" term="Selenium"/><category scheme="http://www.blogger.com/atom/ns#" term="Test"/><category scheme="http://www.blogger.com/atom/ns#" term="Testing"/><title type='text'>Waiting for Oracle ADF Partial Page Rendering in Selenium tests</title><content type='html'>One of the main reasons people fail to use Selenium (or any other tool) for automated web testing with Oracle ADF is timing issues. The test automation tool typically wants to execute its actions as quickly as possible. This can be a challenge in dynamic applications that load parts of the pages on demand or in response to user interactions. This is what ADF typically does with &lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop-faces/adf-faces-ppr.htm#BGBEGIDF&quot; target=&quot;_blank&quot;&gt;partial page rendering&lt;/a&gt; requests.&lt;br /&gt;
&lt;br /&gt;
For example, the test could &quot;click&quot; on a tab in a af:pannelTabbed component. The content of the new tab will be retrieved with a partial page rendering request. If the test automation tool would continue immediately after &quot;clicking&quot; the tab and try to interact with elements on the new tab it would be too early and fail. Most automated testing tools have features to wait for new page DOM elements to appear before interacting with them. But even this can be too soon. When the response to the partial page rendering request is processed by the web browser client it adds the new elements to the page and then binds all sorts of javascript events and other goodies to them. Most automated testing tools will not wait for this to complete and will still fail to interact with the new elements.&lt;br /&gt;
&lt;br /&gt;
One quick and dirty solution is to introduce sleep statements in your test and just wait a second or two for the request to complete. This will unnecessarily slow down your tests if the partial request is completed in less than your sleep time and will still break your test whenever the page load will take longer then normal and thus longer than your sleep time.&lt;br /&gt;
&lt;br /&gt;
A much better way is to actually tell Selenium (or your other testing tool of choice) when the partial page rendering request is fully completed and the browser is ready for its next command. ADF includes a javascript method that does just that;&amp;nbsp;&lt;code&gt;&lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/api-reference-javascript-faces/oracle/adf/view/js/base/AdfPage.html#isSynchronizedWithServer__&quot; target=&quot;_blank&quot;&gt;AdfPage.isSynchronizedWithServer&lt;/a&gt;&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
This has been available in older ADF versions as well. In version 12c Oracle even introduced &lt;code&gt;&lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/api-reference-javascript-faces/oracle/adfinternal/view/js/laf/dhtml/rich/AdfDhtmlPage.html#whyIsNotSynchronizedWithServer__&quot; target=&quot;_blank&quot;&gt;AdfDhtmlPage.whyIsNotSynchronizedWithServer&lt;/a&gt;&lt;/code&gt; which tells you why the client is not ready yet. Please not this is part of the Oracle internal AdfDhtmlPage class and therefor not part of the public javascript API which means it might change or disappear in future versions.&lt;br /&gt;
&lt;br /&gt;
Selenium WebDriver has the notion of &lt;a href=&quot;http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp#explicit-and-implicit-waits&quot; target=&quot;_blank&quot;&gt;explicit waits&lt;/a&gt; where you can instruct Selenium to wait for a certain condition. I figured it would be nice if we could just hook into that mechanism. As part of my effort to automate ADF testing I&#39;ve created a subclass of &lt;a href=&quot;http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/ui/ExpectedCondition.html&quot; target=&quot;_blank&quot;&gt;org.openqa.selenium.support.ui.ExpectedCondition&lt;/a&gt; called &lt;a href=&quot;https://github.com/wvanderdeijl/adf-selenium/blob/page-objects/FileExplorer/src/com/redheap/selenium/conditions/ClientSynchedWithServer.java&quot; target=&quot;_blank&quot;&gt;ClientSynchedWithServer&lt;/a&gt;:&lt;br /&gt;
&lt;pre class=&quot;brush:java;highlight:[5,6,7,8,9,10,16]&quot;&gt;public class ClientSynchedWithServer implements ExpectedCondition&amp;lt;Boolean&amp;gt; {
    // return false if AdfPage object and functions do not exist
    // if they do exist return true if page is fully loaded and ready or reason why this is not completed yet
    String js =
        &quot;return typeof AdfPage !== &#39;undefined&#39; &amp;amp;&amp;amp; &quot; + 
        &quot;typeof AdfPage.PAGE !== &#39;undefined&#39; &amp;amp;&amp;amp; &quot; +
        &quot;typeof AdfPage.PAGE.isSynchronizedWithServer === &#39;function&#39; &amp;amp;&amp;amp; &quot; +
        &quot;(AdfPage.PAGE.isSynchronizedWithServer() || &quot; +
        &quot;(typeof AdfPage.PAGE.whyIsNotSynchronizedWithServer === &#39;function&#39; &amp;amp;&amp;amp; &quot; +
        &quot;AdfPage.PAGE.whyIsNotSynchronizedWithServer()))&quot;;

    @Override
    public Boolean apply(WebDriver driver) {
        JavascriptExecutor jsDriver = (JavascriptExecutor) driver;
        Object result = jsDriver.executeScript(js);
        System.out.println(&quot;client ready: &quot; + result);
        return Boolean.TRUE.equals(result);
    }
}
&lt;/pre&gt;
&lt;br /&gt;
The javascript tries to be as careful as possible not to throw an exception when not on an ADF page by first checking if &lt;code&gt;AdfPage&lt;/code&gt;, &lt;code&gt;AdfPage.PAGE&lt;/code&gt; and &lt;code&gt;AdfPage.PAGE.isSynchronizedWithServer&lt;/code&gt; are available. If so, it will execute &lt;code&gt;AdfPage.PAGE.isSynchronizedWithServer()&lt;/code&gt; to see if the client is completely finished processing all events. If this is not the case it will check if the &lt;code&gt;whyIsNotSynchronizedWithServer&lt;/code&gt; function is available and will invoke it if it is. This would return the reason why the client is not finished yet. If the &lt;code&gt;whyIsNotSynchronizedWithServer&lt;/code&gt; function is not available it would just return the &lt;code&gt;false&lt;/code&gt; result from &lt;code&gt;isSynchronizedWithServer&lt;/code&gt;.&lt;br /&gt;
In the end the javascript function will only return &lt;code&gt;true&lt;/code&gt; if &lt;code&gt;isSynchronizedWithServer&lt;/code&gt; returned true, otherwise it might return the reason why the page is not finished or any other non-true value.&lt;br /&gt;
&lt;br /&gt;
The &lt;code&gt;apply&lt;/code&gt; method from this ExpectedCondition will invoke the javascript and would print the reason why the page is not finished yet. If you don&#39;t want any &lt;code&gt;System.out.println&lt;/code&gt; in your tests you could just remove this. The important part is that it checks if the javascript returned &lt;code&gt;true&lt;/code&gt;. If it did, the apply method will also return true and Selenium would know the condition has been met and it no longer needs to wait.&lt;br /&gt;
&lt;br /&gt;
Using this class to wait for PPR after interacting with the page is similar to any explicit wait in Selenium WebDriver:&lt;br /&gt;
&lt;pre class=&quot;brush:java;highlight:[9,13]&quot;&gt;public void test() throws Exception {
    FirefoxProfile profile = new FirefoxProfile();
    profile.setEnableNativeEvents(true);
    profile.setPreference(&quot;app.update.enabled&quot;, false);
    WebDriver driver = new FirefoxDriver(profile);
    System.out.println(&quot;load demo page...&quot;);
    driver.get(&quot;http://jdevadf.oracle.com/adf-richclient-demo&quot;);
    System.out.println(&quot;wait for completion...&quot;);
    new WebDriverWait(driver, 10).until(new ClientSynchedWithServer());
    System.out.println(&quot;click search button...&quot;);
    driver.findElement(By.id(&quot;tmplt:gTools:glryFind:doFind&quot;)).click();
    System.out.println(&quot;wait for completion...&quot;);
    new WebDriverWait(driver, 10).until(new ClientSynchedWithServer());
    driver.quit();
}
&lt;/pre&gt;
&lt;br /&gt;
This will setup a new Selenium session in lines 2 through 5. It will then navigate to the &lt;a href=&quot;http://jdevadf.oracle.com/adf-richclient-demo&quot; target=&quot;_blank&quot;&gt;Oracle Rich Client Demo site&lt;/a&gt;. This already includes quite some client side javascript processing, so we need to wait for this to complete in line 9. We then click on the search button and again wait for that to complete in line 13. Both waits use a timeout of 10 seconds. If the condition is not met within that timeout Selenium will throw an exception.&lt;br /&gt;
Without the new waits this script would fail as it would try to click the search button before the page has completely rendered and attached all of its javascript listeners. With the new waits you can see the results in the console and why the page wasn&#39;t ready yet in lines 3-5 and 9-10:&lt;br /&gt;
&lt;pre class=&quot;brush:plain;highlight:[3,4,5,9,10]&quot;&gt;.load demo page...
wait for completion...
client ready: WAITING_FOR_USER_INPUT_PHASE
client ready: WAITING_FOR_USER_INPUT_PHASE
client ready: Event queue is not empty
client ready: true
click search button...
wait for completion...
client ready: DTS is not ready
client ready: WAITING_FOR_USER_INPUT_PHASE
client ready: true

Time: 9.756

OK (1 test)&lt;/pre&gt;
&lt;br /&gt;
This post is part of a &lt;a href=&quot;http://www.redheap.com/search/label/Selenium&quot;&gt;series on how to get Selenium to work&lt;/a&gt; with Oracle ADF.&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/2251951326236255912/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2015/02/selenium-adf-partial-page-rendering.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/2251951326236255912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/2251951326236255912'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2015/02/selenium-adf-partial-page-rendering.html' title='Waiting for Oracle ADF Partial Page Rendering in Selenium tests'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-7899684632486206414</id><published>2015-02-08T12:44:00.000+01:00</published><updated>2015-02-13T15:39:25.697+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Selenium"/><category scheme="http://www.blogger.com/atom/ns#" term="Test"/><category scheme="http://www.blogger.com/atom/ns#" term="Testing"/><title type='text'>Configuring an Oracle ADF Project for Selenium testing</title><content type='html'>Running Selenium testing against an ADF application requires direct interaction with the HTML DOM, JavaScript and CSS. An ADF application is normally optimised for performance and scalability which means CSS classes and javascript are minified and obfuscated. This makes testing with Selenium very difficult and brittle.&lt;br /&gt;
&lt;br /&gt;
Fortunately you can configure quite a few settings in your project&#39;s web.xml file to make it more development friendly. I&#39;ve &lt;a href=&quot;http://www.redheap.com/2014/01/configuring-adf-faces-for-development.html&quot; target=&quot;_blank&quot;&gt;written about these before&lt;/a&gt; but some are even more important for automated testing. The &lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop-faces/adf-faces-configuration.htm#BHCHHCFF&quot; target=&quot;_blank&quot;&gt;ADF Faces documentation&lt;/a&gt; also states a number of configuration changes have to be made for automated testing.&lt;br /&gt;
&lt;br /&gt;
These are the settings to change when using automated testing:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop-faces/adf-faces-configuration.htm#BHCHHCFF&quot; target=&quot;_blank&quot;&gt;oracle.adf.view.rich.automation.ENABLED&lt;/a&gt;&lt;/code&gt;&amp;nbsp;should be set to &lt;code&gt;true&lt;/code&gt;&amp;nbsp;in web.xml. This ensures a javascript client component is created for each ADF component regardless the value of the&amp;nbsp;&lt;code&gt;clientComponent&lt;/code&gt; attribute on the JSF component. This makes interacting with the page from Selenium much easier. It also seems to enable some other client and server side features. Search for &lt;code&gt;isAutomationEnabled&lt;/code&gt; in the ADF source code to get a feeling for things that will change when enabling this. One of the things it enables is to find objects using scope IDs (also known as Sub IDs). This is explained in the &lt;a href=&quot;http://www.oracle.com/technetwork/oem/app-test/index-084446.html&quot; target=&quot;_blank&quot;&gt;Oracle Application Testing Suite&lt;/a&gt; Open Script User Guide.&lt;br /&gt;For this to work you also need to put&amp;nbsp;adf-richclient-automation-11.jar in your project classpath. The simplest way is to just put this JAR in the WEB-INF/lib folder of your project. The file itself can be found in JDEV_HOME/oracle_common/modules/oracle.adf.view_12.1.3/&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop-faces/adf-faces-configuration.htm#sthref510&quot; target=&quot;_blank&quot;&gt;org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION&lt;/a&gt;&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;&amp;nbsp;in web.xml which will disable the compression of CSS classes like &lt;code&gt;af_button&lt;/code&gt; to something like &lt;code&gt;x7k&lt;/code&gt;. Having readable and deterministic CSS class names makes it possible to use CSS selectors in your Selenium scripts.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop-faces/adf-faces-configuration.htm#BABGAACI&quot; target=&quot;_blank&quot;&gt;org.apache.myfaces.trinidad.DEBUG_JAVASCRIPT&lt;/a&gt;&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;&amp;nbsp;in web.xml o disable the minification of ADF&#39;s javascript files. This gives you human readable javascript which makes it easier to figure out how to interact with those scripts from Selenium. You should also get a copy of the ADF Source code from Oracle Support so you even have the versions with all the inline comments in place. But don&#39;t let this scare you. For simple testing scenarios you won&#39;t be needing javascript interactions. It&#39;s just when you want to go all the way and have very detailed interactions or tests with ADF components.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop-faces/adf-faces-configuration.htm#sthref514&quot; target=&quot;_blank&quot;&gt;javax.faces.PROJECT_STAGE&lt;/a&gt;&lt;/code&gt; to &lt;code&gt;Development&lt;/code&gt;&amp;nbsp;in web.xml as your application will otherwise fail to start since you have enabled a number of development-only features. You can revert this to&amp;nbsp;&lt;code&gt;Production&lt;/code&gt;&amp;nbsp;with &lt;a href=&quot;http://www.redheap.com/2014/01/configuring-adf-faces-for-development.html&quot; target=&quot;_blank&quot;&gt;deployment plans&lt;/a&gt; for other environments.&lt;/li&gt;
&lt;li&gt;The aforementioned Oracle Application Testing Suite documentation also advises to set&amp;nbsp;&lt;code&gt;&lt;a href=&quot;http://docs.oracle.com/middleware/1213/adf/develop-faces/adf-faces-configuration.htm#CEGGDAIF&quot; target=&quot;_blank&quot;&gt;animation-enabled&lt;/a&gt;&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; in &lt;code&gt;trinidad-config.xml&lt;/code&gt;. This is not only to speed up the running of the testing script as it won&#39;t have to wait for the animations but will also make sure tests don&#39;t fail as they want to interact with things like tree nodes before the expanding animation of a tree node is finished. In my own testscripts I also make sure to execute the javascript &lt;code&gt;AdfPage.PAGE.setAnimationEnabled(false)&lt;/code&gt; on each page for situations where we forgot to set this parameter. Unfortunately values in &lt;code&gt;trinidad-config.xml&lt;/code&gt; cannot be overridden with deployment plans, but there is a &lt;a href=&quot;http://www.redheap.com/2014/01/configuring-adf-faces-for-development.html&quot; target=&quot;_blank&quot;&gt;neat trick&lt;/a&gt; where you can refer to web.xml context param values from &lt;code&gt;trinidad-config.xml.&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;
You can revert these settings to the optimised values with deployment plans. No need to change this in the source code or build artefact each time. Just set the development optimised versions in your source files so local runs in JDeveloper use the correct values. Then &lt;a href=&quot;http://www.redheap.com/2014/01/configuring-adf-faces-for-development.html&quot; target=&quot;_blank&quot;&gt;use deployment plans&lt;/a&gt; to override these for production and other environments.&lt;br /&gt;
&lt;br /&gt;
This post is part of a &lt;a href=&quot;http://www.redheap.com/search/label/Selenium&quot;&gt;series on how to use Selenium&lt;/a&gt; automated tests with Oracle ADF.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/7899684632486206414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2015/02/configuring-adf-project-for-selenium.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/7899684632486206414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/7899684632486206414'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2015/02/configuring-adf-project-for-selenium.html' title='Configuring an Oracle ADF Project for Selenium testing'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-1626342363256618224</id><published>2015-02-08T09:55:00.000+01:00</published><updated>2015-02-17T20:42:05.795+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Selenium"/><category scheme="http://www.blogger.com/atom/ns#" term="Test"/><category scheme="http://www.blogger.com/atom/ns#" term="Testing"/><category scheme="http://www.blogger.com/atom/ns#" term="WebDriver"/><title type='text'>Testing Oracle ADF with Selenium WebDriver Page Objects</title><content type='html'>&lt;a href=&quot;http://docs.seleniumhq.org/&quot; target=&quot;_blank&quot;&gt;Selenium&lt;/a&gt; is an awesome (and free) tool to automate browser-based user interface testing. Selenium offers two ways of working; Selenium IDE; a firefox add-on for simple record-and-playback of interactions with your browser and Selenium WebDriver; a collection of language specific bindings to drive a browser -- the way it is meant to be driven. &lt;br /&gt;
&lt;br /&gt;
For testing ADF applications you&#39;ll need to use Selenium WebDriver as that sends native events to the browser it is controlling. This means it will fire actual mouse, keyboard, and other events, which is something the javascript-heavy ADF framework needs.&lt;br /&gt;
&lt;br /&gt;
I&#39;ve built an example on how to test the public&amp;nbsp;&lt;a href=&quot;http://jdevadf.oracle.com/adf-richclient-demo/faces/index.jspx&quot; target=&quot;_blank&quot;&gt;Oracle ADF Faces 12c Components Demo&lt;/a&gt;&amp;nbsp;for a real life demo using &lt;a href=&quot;http://junit.org/&quot; target=&quot;_blank&quot;&gt;JUnit&lt;/a&gt; and &lt;a href=&quot;http://docs.seleniumhq.org/projects/webdriver/&quot; target=&quot;_blank&quot;&gt;Selenium WebDriver&lt;/a&gt;. The &lt;a href=&quot;https://github.com/wvanderdeijl/adf-selenium&quot; target=&quot;_blank&quot;&gt;example project is at github&lt;/a&gt; and I&#39;ll explain the important parts in a number of blog posts. This first post will show how the JUnit test classes interact with the page objects. The nitty gritty details on how to work with ADF and Selenium will be covered in separate posts.&lt;br /&gt;
&lt;br /&gt;
My advice is to follow the &lt;a href=&quot;https://code.google.com/p/selenium/wiki/PageObjects&quot; target=&quot;_blank&quot;&gt;Page Objects Pattern&lt;/a&gt; proposed by the Selenium team. It creates a clear separation between Page Objects and Test Objects. Page Objects know about the HTML, the page components and how to interact with them while the Test Objects drive these page objects and contain the real test logic and assertions. An alternative approach would be the &lt;a href=&quot;https://code.google.com/p/selenium/wiki/BotStyleTests&quot; target=&quot;_blank&quot;&gt;Bot Style&lt;/a&gt; tests which combines page logic and Selenium interactions in a single class.&lt;br /&gt;
&lt;br /&gt;
In an ideal world making changes to the ADF page itself only involves updating the Page Objects while the Test Objects can remain the same. Unless you&#39;re actually changing functionality on the page that requires changes to the tests itself. But even then it helps you to separate these two objects. The Page Object is more &quot;developer oriented&quot;, while the Test Object is more &quot;tester oriented&quot;.&lt;br /&gt;
&lt;br /&gt;
Let&#39;s look at an example that drives the public Oracle ADF Faces Components Demo:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;@Test
public void testNavigationToFileExplorer() throws Exception {
    FileExplorer page = getPage().clickFileExplorerLink().clickTreeTableTab();
    page.getScreenshotAs(new ScreenshotFile(new File(&quot;explorer-tree-table.png&quot;)));
}&lt;/pre&gt;
&lt;br /&gt;
This is a JUnit test method in the &lt;code&gt;&lt;a href=&quot;https://github.com/wvanderdeijl/adf-selenium/blob/page-objects/FileExplorer/src/com/redheap/selenium/RichClientDemoTest.java&quot; target=&quot;_blank&quot;&gt;RichClientDemoTest&lt;/a&gt;&lt;/code&gt; test class. It starts in line 3 by navigation to the component demo homepage by invoking &lt;code&gt;getPage()&lt;/code&gt;. This method returns a &lt;code&gt;&lt;a href=&quot;https://github.com/wvanderdeijl/adf-selenium/blob/page-objects/FileExplorer/src/com/redheap/selenium/pages/RichClientDemo.java&quot; target=&quot;_blank&quot;&gt;RichClientDemo&lt;/a&gt;&lt;/code&gt; page object. This is one of the aforementioned page objects that allow interaction with the web page.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC5vQPStgYdnU9ejblsUMDAUyBtD-Wr7_lPWbvm6Y1AATjx2vZZVMqUuh6RTsVA9ISQsd4zKwEcIskRLjyTs_j0VqXVg3_waq4Alc8FBGlftODEa1zFUvF9XuxgKNweSVKkw3nnPmwj7A/s1600/Snap12.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC5vQPStgYdnU9ejblsUMDAUyBtD-Wr7_lPWbvm6Y1AATjx2vZZVMqUuh6RTsVA9ISQsd4zKwEcIskRLjyTs_j0VqXVg3_waq4Alc8FBGlftODEa1zFUvF9XuxgKNweSVKkw3nnPmwj7A/s1600/Snap12.png&quot; height=&quot;282&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;ADF 12c Rich Client demo page with File Explorer link highlighted&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Invoking the &lt;code&gt;clickFileExplorerLink()&lt;/code&gt; method on the &lt;code&gt;RichClientDemo&lt;/code&gt; page object will find the link on the page to navigate to the &lt;code&gt;&lt;a href=&quot;http://jdevadf.oracle.com/adf-richclient-demo/faces/fileExplorer/index.jspx&quot; target=&quot;_blank&quot;&gt;File Explorer&lt;/a&gt;&lt;/code&gt; demo and click that link to navigate to that page. Navigation methods on page objects will return other page objects. In this example we invoked a navigation method on &lt;code&gt;RichClientDemo&lt;/code&gt; which returns a &lt;code&gt;&lt;a href=&quot;https://github.com/wvanderdeijl/adf-selenium/blob/master/FileExplorer/src/com/redheap/selenium/pages/FileExplorer.java&quot; target=&quot;_blank&quot;&gt;FileExplorer&lt;/a&gt;&lt;/code&gt; page object.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoGKpUuNUwmiasDoaWsyuX9eHX10Rrv1oenFkjxRdTFayti9aCUnPFVoN5Mm5twRaD8FVAYdwQkoT5uesXTXtJP2DPe79cfMENldWQnlX-SyErT8RQVgpWmFw1cffgag6Si0DpZKtigFo/s1600/Snap13.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoGKpUuNUwmiasDoaWsyuX9eHX10Rrv1oenFkjxRdTFayti9aCUnPFVoN5Mm5twRaD8FVAYdwQkoT5uesXTXtJP2DPe79cfMENldWQnlX-SyErT8RQVgpWmFw1cffgag6Si0DpZKtigFo/s1600/Snap13.png&quot; height=&quot;300&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;File Explorer page with Tree Table tab highlighted&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Finally we invoke the &lt;code&gt;clickTreeTableTab()&lt;/code&gt; method to click on the &lt;code&gt;Tree Table&lt;/code&gt; tab in the right hand side af:pannelTabbed. Methods on Page Objects return the same page object instance or another when navigation occurs. In either case this means you can chain numerous of these methods on a single line when needed.&lt;br /&gt;
&lt;br /&gt;
The last line of the test method shows how you can take a screenshot of what the browser is showing at the time. This can be very helpful especially with failing test cases where it could be useful to have a screenshot of the failed state.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBtSWPqtUwG-Uzc4I7mgihmhtmkswcFootNWDnfYuwU5-NOboxjm9JCd1uOTk1gUQjI3ZJL3DnBMKh05tzlgz8zBJMW6Cnegc1vv-fMjeaA6W_EMolKQeqT4GNk9wiENm3-jo8iPHmRoA/s1600/explorer-tree-table.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBtSWPqtUwG-Uzc4I7mgihmhtmkswcFootNWDnfYuwU5-NOboxjm9JCd1uOTk1gUQjI3ZJL3DnBMKh05tzlgz8zBJMW6Cnegc1vv-fMjeaA6W_EMolKQeqT4GNk9wiENm3-jo8iPHmRoA/s1600/explorer-tree-table.png&quot; height=&quot;221&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Screenshot taken by Firefox ran by Selenium WebDriver&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
This example showed how to interact with page objects and it will fail if any of the required links or other elements are not available on the page. But it doesn&#39;t have any real test assertions yet. One final example shows how to assert that the number of expanded nodes in an af:tree should have increased when clicking one of the (collapsed) nodes in the tree:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;@Test
public void testExpandTagGuideNodeA() {
    RichClientDemo page = getPage();
    int expandedNodesBefore = page.getTagGuideTreeExpandedNodeCount();
    page.clickLayoutTreeNode();
    Assert.assertEquals(&quot;number of expanded node should increase&quot;, 
                        expandedNodesBefore + 1,
                        page.getTagGuideTreeExpandedNodeCount());
}
&lt;/pre&gt;
&lt;br /&gt;
Line 3 shows how we again first navigate to the rich client demo homepage as that is the starting point for all of our tests. Line 4 uses the &lt;code&gt;RichClientDemo&lt;/code&gt; page object to retrieve the number of expanded nodes in the &lt;code&gt;af:tree&lt;/code&gt; component. Notice how the knowledge on how to interact with the page to get this information is contained in the page objects and not exposed to the tester. Line 5 clicks the node in the tree labeled &lt;code&gt;Layout&lt;/code&gt;. Again notice the knowledge on how to locate and click this node is hidden from the tester class. Finally in line 6 we have a &lt;a href=&quot;http://junit.org/javadoc/latest/org/junit/Assert.html&quot; target=&quot;_blank&quot;&gt;JUnit assertion&lt;/a&gt; that the number of expanded nodes in the tree should have been increased by 1. If that is not the case this JUnit test will fail.&lt;br /&gt;
&lt;br /&gt;
By the way; a Page Object doesn&#39;t have to represent a full page. Especially with ADF regions it is conceivable that each region would have its own Page Object (or rather Page Fragment Object). For complex page fragments this could be split up even further to keep the code manageable. More on that in other blog posts. I&#39;ll explain the other bits and pieces of this demo in separate blog posts. If you want to look at the full demo just hop over to &lt;a href=&quot;https://github.com/wvanderdeijl/adf-selenium&quot; target=&quot;_blank&quot;&gt;github&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
This post is part of a&amp;nbsp;&lt;a href=&quot;http://www.redheap.com/search/label/Selenium&quot;&gt;series on how to get Selenium to work&lt;/a&gt;&amp;nbsp;with Oracle ADF.</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/1626342363256618224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2015/02/adf-selenium-webdriver-pageobjects.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/1626342363256618224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/1626342363256618224'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2015/02/adf-selenium-webdriver-pageobjects.html' title='Testing Oracle ADF with Selenium WebDriver Page Objects'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC5vQPStgYdnU9ejblsUMDAUyBtD-Wr7_lPWbvm6Y1AATjx2vZZVMqUuh6RTsVA9ISQsd4zKwEcIskRLjyTs_j0VqXVg3_waq4Alc8FBGlftODEa1zFUvF9XuxgKNweSVKkw3nnPmwj7A/s72-c/Snap12.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-7635512759386671461</id><published>2015-01-23T14:43:00.000+01:00</published><updated>2015-01-23T14:47:59.665+01:00</updated><title type='text'>showPopupBehavior align property examples</title><content type='html'>I always struggle to understand the official descriptions for the &lt;a href=&quot;https://docs.oracle.com/middleware/1213/adf/tag-reference-faces/tagdoc/af_showPopupBehavior.html&quot; target=&quot;_blank&quot;&gt;align attribute of the af:showPopupBehavior&lt;/a&gt; tag. A picture is worth a thousands words so I just created screenshots of all the possible values:&lt;br /&gt;
&lt;hr /&gt;
&lt;b&gt;afterStart&lt;/b&gt;: The popup appears underneath the element with the popup&#39;s upper-left corner aligned with the lower-left corner of the element. The left edges of the element and the popup are aligned&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifRLbU5QwAx55_kheHPErgu6KXNFpf9yyTJ2lgOGekKktRyzgm6KKK8ePbveNsmUI6ygUH8u-a3COdHNFFaMvf0UYxXeuWCVuJpgVmpmaMH2WuztR0EgDRzVGbGbGrEjDBsc5P7Pxu7aM/s1600/afterStart.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifRLbU5QwAx55_kheHPErgu6KXNFpf9yyTJ2lgOGekKktRyzgm6KKK8ePbveNsmUI6ygUH8u-a3COdHNFFaMvf0UYxXeuWCVuJpgVmpmaMH2WuztR0EgDRzVGbGbGrEjDBsc5P7Pxu7aM/s1600/afterStart.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;b&gt;afterEnd&lt;/b&gt;: The popup appears underneath the element with the popup&#39;s upper-right corner aligned with the lower-right corner of the element. The right edges of the element and the popup are aligned.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVtOPiZ2Bd6LrbLJE3bKcRDo3iT1DWB4RTqvvplxvIuioxXUbAg0LHcpsvygDAPrBppi-EYLzP05YjVmK2BZquI8FQLAEYLT2sEdgV5MhqslkHs8k3zNejV_XwVG_VOPHWgXr6jZRq1rA/s1600/afterEnd.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVtOPiZ2Bd6LrbLJE3bKcRDo3iT1DWB4RTqvvplxvIuioxXUbAg0LHcpsvygDAPrBppi-EYLzP05YjVmK2BZquI8FQLAEYLT2sEdgV5MhqslkHs8k3zNejV_XwVG_VOPHWgXr6jZRq1rA/s1600/afterEnd.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;b&gt;beforeStart&lt;/b&gt;: The popup appears above the element with the popup&#39;s lower-left corner aligned with the upper-left corner of the element. The left edges of the element and the popup are aligned.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0qB5qSfwEhE_c8ojQc9MWfDeHNnrOPmM7A2ki0AoOvUvpxSvVnya4Fnrg_gbPHxlJTnqJz39lWIH4lBVywZm4KcVmiXQwSAe48tODSuMD_uIJPmxjE0Spkyc0ptvbtwK8nnqd7lnfuG0/s1600/beforeStart.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0qB5qSfwEhE_c8ojQc9MWfDeHNnrOPmM7A2ki0AoOvUvpxSvVnya4Fnrg_gbPHxlJTnqJz39lWIH4lBVywZm4KcVmiXQwSAe48tODSuMD_uIJPmxjE0Spkyc0ptvbtwK8nnqd7lnfuG0/s1600/beforeStart.png&quot; /&gt;&lt;/a&gt;&amp;nbsp;&lt;/div&gt;
&lt;hr /&gt;
&lt;b&gt;beforeEnd&lt;/b&gt;: The popup appears above the element with the popup&#39;s lower-right corner aligned with the upper-right corner of the element. The right edges of the element and the popup are aligned.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5RKE9qZ-fBiFxNPR1kTJOFDvKXb0ANztq_bqbOVQq1fDSKpcODD-SadDb3hCsDm-OSnQ3QW9MmrEFo-wkjL5otj_ZglVi9eY6vwl988ala2-RxavLu2qwF4YOBUUJlXvGhnGPejXpEQo/s1600/beforeEnd.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5RKE9qZ-fBiFxNPR1kTJOFDvKXb0ANztq_bqbOVQq1fDSKpcODD-SadDb3hCsDm-OSnQ3QW9MmrEFo-wkjL5otj_ZglVi9eY6vwl988ala2-RxavLu2qwF4YOBUUJlXvGhnGPejXpEQo/s1600/beforeEnd.png&quot; /&gt;&lt;/a&gt;&amp;nbsp;&lt;/div&gt;
&lt;hr /&gt;
&lt;b&gt;endAfter&lt;/b&gt;: The popup appears to the right of the element with the popup&#39;s lower-left corner aligned with the lower-right corner of the element. The bottom edges of the element and the popup are aligned.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn6T7RaLHpEQoZGwFBcem-V0-Cex7N6Vyih8JE2F4PkauBlLGAKEowZO5bSzn9CWWkNiZ4dLCDxrUr1sskEAhkNqPLSdpTRB1WEDkNnc0VIkcJnHpbezjlG0CSLL203WulZycKMjVT5CI/s1600/endAfter.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn6T7RaLHpEQoZGwFBcem-V0-Cex7N6Vyih8JE2F4PkauBlLGAKEowZO5bSzn9CWWkNiZ4dLCDxrUr1sskEAhkNqPLSdpTRB1WEDkNnc0VIkcJnHpbezjlG0CSLL203WulZycKMjVT5CI/s1600/endAfter.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;b&gt;endBefore&lt;/b&gt;: The popup appears to the right of the element with the popup&#39;s upper-left corner aligned with the upper-right corner of the element. The top edges of the element and the popup are aligned.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkWh2B3fIDIlgEngYY0-tyFAiWigEJrwuXoT7QGYlPT2EFKdeijeHp2A7uEtKjUYBN6jgiJ9dhdVAVebY_nLhuIfiCgJlQQ8M3d4nun5tdL7sKsBjH3IWKo4plQOsVL2WCWroatPl8nds/s1600/endBefore.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkWh2B3fIDIlgEngYY0-tyFAiWigEJrwuXoT7QGYlPT2EFKdeijeHp2A7uEtKjUYBN6jgiJ9dhdVAVebY_nLhuIfiCgJlQQ8M3d4nun5tdL7sKsBjH3IWKo4plQOsVL2WCWroatPl8nds/s1600/endBefore.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;b&gt;startAfter&lt;/b&gt;: The popup appears to the left of the element with the popup&#39;s lower-right corner aligned with the lower-left corner of the element. The bottom edges of the element and the popup are aligned.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcWe7kEJPy0OBPp5Z_f4NhVupXojfiEcueOzUbF27gKUnwhmMyBngUdKd_hsRNBB92vPd63s9LH3Zd-3GbVJ5aGxYuMtNG2Q_WnygSUOgoa6Mn6ZTDgQewSc-yD85Id5xdQuqIg3IKwrI/s1600/startAfter.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcWe7kEJPy0OBPp5Z_f4NhVupXojfiEcueOzUbF27gKUnwhmMyBngUdKd_hsRNBB92vPd63s9LH3Zd-3GbVJ5aGxYuMtNG2Q_WnygSUOgoa6Mn6ZTDgQewSc-yD85Id5xdQuqIg3IKwrI/s1600/startAfter.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;b&gt;startBefore&lt;/b&gt;: The popup appears to the left of the element with the popup&#39;s upper-right corner aligned with the upper-left corner of the element. The top edges of the element and the popup are aligned.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSMo8M72GCXlHD1jwaCpsI6SnC-8CIGSLJXaCkIOxUMrTgec1Hr04Hmp9RFP1-3O0K4_wuVnYj4S1mDhqqbHE7L53vczHxeQMc5MImgsuqZXuBRSdoo1mJGq6MOUoZPy0HNlDdNltGgJo/s1600/startBefore.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSMo8M72GCXlHD1jwaCpsI6SnC-8CIGSLJXaCkIOxUMrTgec1Hr04Hmp9RFP1-3O0K4_wuVnYj4S1mDhqqbHE7L53vczHxeQMc5MImgsuqZXuBRSdoo1mJGq6MOUoZPy0HNlDdNltGgJo/s1600/startBefore.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/7635512759386671461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2015/01/showpopupbehavior-align-examples.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/7635512759386671461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/7635512759386671461'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2015/01/showpopupbehavior-align-examples.html' title='showPopupBehavior align property examples'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifRLbU5QwAx55_kheHPErgu6KXNFpf9yyTJ2lgOGekKktRyzgm6KKK8ePbveNsmUI6ygUH8u-a3COdHNFFaMvf0UYxXeuWCVuJpgVmpmaMH2WuztR0EgDRzVGbGbGrEjDBsc5P7Pxu7aM/s72-c/afterStart.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-8293608275748995025</id><published>2014-04-10T22:36:00.000+02:00</published><updated>2014-04-13T16:21:29.026+02:00</updated><title type='text'>Host a Soap Web Service on Google App Engine with JAX-WS</title><content type='html'>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 &lt;a href=&quot;http://cloud.google.com/AppEngine%E2%80%8E&quot; target=&quot;_blank&quot;&gt;Google App Engine&lt;/a&gt;&amp;nbsp;has two major benefits: it is free and is accessible for anyone on the internet 24x7.&lt;br /&gt;
&lt;br /&gt;
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&amp;nbsp;&lt;a href=&quot;https://redheap-jaxws.appspot.com/HelloWorldService.wsdl&quot;&gt;https://redheap-jaxws.appspot.com/HelloWorldService.wsdl&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJvsc-NqUgYhbOeFDfLGZnSolbqMMFKfyd2eUFF_wgV9OrEunjgUxpPiKAoBW9GvTgBm6fXnDsjuVMmxhb1r4FVHcoMS4EmgLJTZAXO8Ym5YIx6Q-6LwaUH4siHFCjzy1RwJw9zuqpubM/s1600/soapui.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJvsc-NqUgYhbOeFDfLGZnSolbqMMFKfyd2eUFF_wgV9OrEunjgUxpPiKAoBW9GvTgBm6fXnDsjuVMmxhb1r4FVHcoMS4EmgLJTZAXO8Ym5YIx6Q-6LwaUH4siHFCjzy1RwJw9zuqpubM/s1600/soapui.png&quot; height=&quot;259&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;SoapUI test invoking HelloWorld service on Google App Engine&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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&#39;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.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Navigate to the directory where you want to create a subdirectory for a project. No need to create the project directory yourself, just navigate to its parent. Then run&amp;nbsp;&lt;code&gt;mvn archetype:generate&lt;/code&gt;. Search for &lt;code&gt;com.google.appengine.archetypes:skeleton-archetype&lt;/code&gt;&amp;nbsp;and select the entry for &lt;code&gt;com.google.appengine.archetypes:appengine-skeleton-archetype&lt;/code&gt;. Finish the wizard by specifying a unique groupId and artifactId. The rest can be left at their defaults:&lt;br /&gt;
&lt;pre class=&quot;brush:plain;highlight:[24,25]&quot;&gt;C:\work\redheap\jdev12120&amp;gt;mvn archetype:generate
[INFO] Scanning for projects...
[INFO] 
[INFO] Using the builder org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder with a thread count of 1
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] &amp;gt;&amp;gt;&amp;gt; maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom &amp;gt;&amp;gt;&amp;gt;
[INFO] 
[INFO] &amp;lt;&amp;lt;&amp;lt; maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom &amp;lt;&amp;lt;&amp;lt;
[INFO] 
[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
..... [[snip long list]] .....
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 361: com.google.appengine.archetypes:skeleton-archetype
Choose archetype:
1: remote -&amp;gt; com.google.appengine.archetypes:appengine-skeleton-archetype (-)
2: remote -&amp;gt; com.google.appengine.archetypes:skeleton-archetype (-)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 1
Define value for property &#39;groupId&#39;: : com.redheap.samples
Define value for property &#39;artifactId&#39;: : AppEngineJaxWs
Define value for property &#39;version&#39;:  1.0-SNAPSHOT: : 
Define value for property &#39;package&#39;:  com.redheap.samples: : 
Confirm properties configuration:
groupId: com.redheap.samples
artifactId: AppEngineJaxWs
version: 1.0-SNAPSHOT
package: com.redheap.samples
 Y: : Y
&lt;/pre&gt;
&lt;br /&gt;
In JDeveloper 12c go to Tools &amp;gt; Preferences and change the location of maven to use a recent version you downloaded yourself. The maven version included with JDeveloper 12.1.2.0.0 is too old for Google App Engine as that requires maven to be at least version 3.1:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSYmZ-Ut-G12XiMEoSbD_EuBOqvAxt0biYpxMD3gkgHGY0cLXsOkt6U783DxBPBe8wRIJ-7alr1htLK0yLXOkEFkArqGHiVYmLa9CdeAq33VvZGEBASxZNl4qOCUOwrLaxF7OSJkO3o1k/s1600/jdevmaven.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSYmZ-Ut-G12XiMEoSbD_EuBOqvAxt0biYpxMD3gkgHGY0cLXsOkt6U783DxBPBe8wRIJ-7alr1htLK0yLXOkEFkArqGHiVYmLa9CdeAq33VvZGEBASxZNl4qOCUOwrLaxF7OSJkO3o1k/s1600/jdevmaven.png&quot; height=&quot;197&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Use at least version 3.1 of maven in JDeveloper 12c&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Next steps are for Oracle JDeveloper, but you can take similar steps from the command line or your favorite Java IDE. Create a new JDeveloper workspace from the maven pom files. JDeveloper will warn that the project already exists and it will be overwritten. Just click Yes even though this is a new project.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS2JxatVk2z5t790GB78JTuLpCiGShMYagSXrrvG-3bvQvvLEKals_ftBaB0XITx6yVMN8JY_0UxSqd-lnlzesnT1Jt-AUA5f7pM3YYj4ABufiIEc_NBNhWw7WANYBFSHCcPYVJCDTet8/s1600/maven1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS2JxatVk2z5t790GB78JTuLpCiGShMYagSXrrvG-3bvQvvLEKals_ftBaB0XITx6yVMN8JY_0UxSqd-lnlzesnT1Jt-AUA5f7pM3YYj4ABufiIEc_NBNhWw7WANYBFSHCcPYVJCDTet8/s1600/maven1.png&quot; height=&quot;223&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Start maven import wizard from New Gallery&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3OvIkOFqTyWWxSPIdDIDSe7Il8wc0HiU7KRr67TkWC-tpvuZ7bwNiwQTcKWKmIAY-LTGgTSEouUNTx3jv8LSTiUoRkUkaqL2DYhR0YGHpPVgimWgZGtJT4nR4MqdHNJK4s3ybtl951Bo/s1600/maven2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3OvIkOFqTyWWxSPIdDIDSe7Il8wc0HiU7KRr67TkWC-tpvuZ7bwNiwQTcKWKmIAY-LTGgTSEouUNTx3jv8LSTiUoRkUkaqL2DYhR0YGHpPVgimWgZGtJT4nR4MqdHNJK4s3ybtl951Bo/s1600/maven2.png&quot; height=&quot;182&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Import all pom&#39;s&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6TUBuKcdRXDuSOHiTPziNeBHuOGoVL7mydvhjMfnCDtUHyYe1rE8ZhKQsZKoVVC6y-kWEkUNd_XOlCyUYIBelk_FJF4rDdCta8jRLb32rV099BTjKgtxj0WpV_mR9APtlVMqhz6FoCRA/s1600/maven3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6TUBuKcdRXDuSOHiTPziNeBHuOGoVL7mydvhjMfnCDtUHyYe1rE8ZhKQsZKoVVC6y-kWEkUNd_XOlCyUYIBelk_FJF4rDdCta8jRLb32rV099BTjKgtxj0WpV_mR9APtlVMqhz6FoCRA/s1600/maven3.png&quot; height=&quot;195&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Point to parent directory of project as subdir is implied&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
Open the pom.xml at application level and update the &lt;code&gt;appengine.target.version&lt;/code&gt; property to the latest App Engine version. Currently this is 1.9.2 but you might want to check the latest Java SDK version at&amp;nbsp;&lt;a href=&quot;https://developers.google.com/appengine/downloads&quot; target=&quot;_blank&quot;&gt;https://developers.google.com/appengine/downloads&lt;/a&gt;.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK2lFAGjKFlV0WiHyMQ4NAERzGoA4Dk2OoKC_GBtdC8iDDYmBbBSACTwRcefL3r-aqxUOh6xPzkR0CSvg6k-Vu-k_H3V5PCfk9t7E1VsyKGgmtOYI80d1iy5XYrB_jHx2gM6WS7NppzqU/s1600/apppom.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK2lFAGjKFlV0WiHyMQ4NAERzGoA4Dk2OoKC_GBtdC8iDDYmBbBSACTwRcefL3r-aqxUOh6xPzkR0CSvg6k-Vu-k_H3V5PCfk9t7E1VsyKGgmtOYI80d1iy5XYrB_jHx2gM6WS7NppzqU/s1600/apppom.png&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Open the application level maven pom&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTZohnEbiNaW8M0gbEzBL-BZUqM2lDkVKVZE95oEYKNDSlCXCRotRHVP1gq-mfBXxXIKBeqlkhCouyZ96ZmtFL2-35dHHCz3hO_At1VwnqR6CPgRpcMzXWTUDBgwxYKRaPfuF5L2RbU-I/s1600/apppom2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTZohnEbiNaW8M0gbEzBL-BZUqM2lDkVKVZE95oEYKNDSlCXCRotRHVP1gq-mfBXxXIKBeqlkhCouyZ96ZmtFL2-35dHHCz3hO_At1VwnqR6CPgRpcMzXWTUDBgwxYKRaPfuF5L2RbU-I/s1600/apppom2.png&quot; height=&quot;223&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Update appengine.target.version&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Go to&amp;nbsp;&lt;a href=&quot;https://console.developers.google.com/&quot; target=&quot;_blank&quot;&gt;https://console.developers.google.com&lt;/a&gt; and create a new project. Use the same project name as you used when setting up the maven project, &lt;code&gt;AppEngineJaxWs&lt;/code&gt; in this example. The project ID has to be globally unique across all App Engine customers and will become the first part of your URL. For example, typing &lt;code&gt;redheap-jaxws&lt;/code&gt; will create &lt;code&gt;http://redheap-jaxws.appspot.com&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Open the project properties for the AppEngineJaxWs-ear project and add the &lt;code&gt;src/main/application&lt;/code&gt; directory to the Java Source Paths.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDXCEbL4ZNGwbMFD_S_3U9GzELt3OvksWTTqW_N03aQO-1v81p0SjPQPZO6bQyqGrki-FXWvGf9ajKhUdS5rL3QjbT9lTnYrt_zjFvKNQKJdBTF0iqgLFWsdwskQQ4rvmcyyP-WEWxLP4/s1600/earprops.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDXCEbL4ZNGwbMFD_S_3U9GzELt3OvksWTTqW_N03aQO-1v81p0SjPQPZO6bQyqGrki-FXWvGf9ajKhUdS5rL3QjbT9lTnYrt_zjFvKNQKJdBTF0iqgLFWsdwskQQ4rvmcyyP-WEWxLP4/s1600/earprops.png&quot; height=&quot;202&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Add src/main/application as source directory&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Then open the &lt;code&gt;application/META-INF/appengine-application.xml&lt;/code&gt; file and update the application name with the globally unique project ID (not the name) that was created in the Google developer console:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7EO35qHAsF_Vsv6b7u0_Tf60ulkK-kAtU50wVNZSGVfNq0wgb5D8XtZ7knmInXpiZTL4X7YHSoR3pqPun72aRNpscX4gz4VNmOwrIaLS49pZxlvk02iN3B-dDVXqiQQU2oXIY17QxGlg/s1600/earappname.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7EO35qHAsF_Vsv6b7u0_Tf60ulkK-kAtU50wVNZSGVfNq0wgb5D8XtZ7knmInXpiZTL4X7YHSoR3pqPun72aRNpscX4gz4VNmOwrIaLS49pZxlvk02iN3B-dDVXqiQQU2oXIY17QxGlg/s1600/earappname.png&quot; height=&quot;127&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Update application name with App Engine Project ID&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Next, create a Java class Person in the war project that we will be using as an argument to our webservice, just to demonstrate how to handle complex payloads:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.redheap.appengine;

public class Person {
    private String firstName;
    private String lastName;

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

    public String getFirstName() {
        return firstName;
    }

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

    public String getLastName() {
        return lastName;
    }
}
&lt;/pre&gt;
&lt;br /&gt;
Next create the HelloWorld class that we will be exposing as a JAX-WS service:&lt;br /&gt;
&lt;pre class=&quot;brush:java;highlight:5&quot;&gt;package com.redheap.appengine;

public class HelloWorld {
    public String sayHello(Person person) {
        return &quot;Hello &quot; + person.getFirstName() + &quot; &quot; + person.getLastName();
    }
}
&lt;/pre&gt;
&lt;br /&gt;
Right click the HelloWorld class in the application navigator and create a web service out of it. When running this for the first time it will ask if you want a WebLogic specific web service or JAX-WS Reference Implementation version. Be sure to check the RI one as we want to deploy to a non-weblogic environment. Other than that, accept all default values. If you are not using JDeveloper, you can also use the command line wsgen tool that ships with the JDK.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-sI5fKRClCudFeC-VxZ6aQK9MXxA0KX-wlUHuPJBRuI_ytqaxi2RtMfX4ItnSVAWeMnXJFxaCQ1cPRNYjijm6euGtswLgoOQFcQK2znUQFS6vemejhxaAWnBIYU_WGYAhAbKA_l5UeuM/s1600/jaxws1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-sI5fKRClCudFeC-VxZ6aQK9MXxA0KX-wlUHuPJBRuI_ytqaxi2RtMfX4ItnSVAWeMnXJFxaCQ1cPRNYjijm6euGtswLgoOQFcQK2znUQFS6vemejhxaAWnBIYU_WGYAhAbKA_l5UeuM/s1600/jaxws1.png&quot; height=&quot;320&quot; width=&quot;209&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHFWcpe76hl6MJxaCzjifI7vufhccNLVmQhPZ22PIjHihi22KvGqrBTv2fdNeM_hs4eWo1pXrBDAj7Erd1rzCo3X7HEwu__yxC239pKioI0JjjENxWhaguGNnBclpRmomljLtaDqGXHxM/s1600/jaxws2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHFWcpe76hl6MJxaCzjifI7vufhccNLVmQhPZ22PIjHihi22KvGqrBTv2fdNeM_hs4eWo1pXrBDAj7Erd1rzCo3X7HEwu__yxC239pKioI0JjjENxWhaguGNnBclpRmomljLtaDqGXHxM/s1600/jaxws2.png&quot; height=&quot;240&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
This will have added a number of annotations to the HelloWorld class. Change the @WebParam annotation for more meaningful argument name than &lt;code&gt;arg0&lt;/code&gt;&amp;nbsp;as this name will end up in the XSD for the web service.&lt;br /&gt;
&lt;pre class=&quot;brush:java;highlight:[1,3,4]&quot;&gt;@WebService
public class HelloWorld {
    @WebMethod
    public String sayHello(@WebParam(name = &quot;person&quot;) Person person) {
        return &quot;Hello &quot; + person.getFirstName() + &quot; &quot; + person.getLastName();
    }
}&lt;/pre&gt;
&lt;br /&gt;
Now right click HelloWorld again and generate a WSDL file.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdyD_jgoJWyPSJ6pSRVRJGwSKf-cDbhNQqwZqB-azmz6b289qAGpHE-bJa6zqX1R6pWjWibesyOufQkiBue5D9U5NJeq1vq8oHz92Xp69NBKJTHoiYLUKqc8mWtz37li85HGFR0T-9PFw/s1600/jaxws-wsdl.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdyD_jgoJWyPSJ6pSRVRJGwSKf-cDbhNQqwZqB-azmz6b289qAGpHE-bJa6zqX1R6pWjWibesyOufQkiBue5D9U5NJeq1vq8oHz92Xp69NBKJTHoiYLUKqc8mWtz37li85HGFR0T-9PFw/s1600/jaxws-wsdl.png&quot; height=&quot;320&quot; width=&quot;246&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Right click the generated wsdl file and use the Move option from the Refactor menu to relocate it to webapp directory itself (two levels up) so the file is no longer in the WEB-INF folder and accessible through the web. Repeat the same steps for the xsd file so it will also be available on the web.&lt;br /&gt;
&lt;br /&gt;
Open the generated WSDL file and update the &lt;code&gt;soap:address&lt;/code&gt; at the end of the file to the URL at your appengine instance. For example, mine is &lt;code&gt;https://redheap-jaxws.appspot.com/HelloWorldService&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Open the generated XSD file and add &lt;code&gt;elementFormDefault=&quot;qualified&quot;&lt;/code&gt; to the root element to ensure we will be using namespaces in the web service requests and responses.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjp8OQ9sglqSDpGbwHpmXCGv-vFd9wXqSix8sqtRWVzUag6NRYsZXMuqiEnr4EQqX0zkfnTNrkDSF-MH-dBUEXBgPRApMlJ2-axYsX24A8aAvaHuoZ5RihyphenhyphenGxDc07te5DOg6sqV2qRuES8/s1600/xsdqualified.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjp8OQ9sglqSDpGbwHpmXCGv-vFd9wXqSix8sqtRWVzUag6NRYsZXMuqiEnr4EQqX0zkfnTNrkDSF-MH-dBUEXBgPRApMlJ2-axYsX24A8aAvaHuoZ5RihyphenhyphenGxDc07te5DOg6sqV2qRuES8/s1600/xsdqualified.png&quot; height=&quot;221&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Use namespace qualified elements&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Now right click the XSD file and create a JAXB Content Model. Be sure to select the correct source directory for the JAXB classes in the wizard as you don&#39;t want them to end up in your test directory since those are not included in a deployment.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiosLa_zj3_b4dE7DpM6P97qrb-3TAg3MTkBvZkPR1MUqRkTfU6tg6q09AMjpcJogmPzYD9qDhS_bWaS4che-tQzYx-eRq3d8vd4RecocrjNYB5n4G0D6yc7wDdjY88sHcIwhhAdtvcbWI/s1600/jaxbgen.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiosLa_zj3_b4dE7DpM6P97qrb-3TAg3MTkBvZkPR1MUqRkTfU6tg6q09AMjpcJogmPzYD9qDhS_bWaS4che-tQzYx-eRq3d8vd4RecocrjNYB5n4G0D6yc7wDdjY88sHcIwhhAdtvcbWI/s1600/jaxbgen.png&quot; height=&quot;256&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjybtUD0ptpCXzxFTrXNqPURp0cL-jowYMWTXVQI9yOrrhykQFcDt9X7IQ-WMhhImPZyxoJ3o4fzEcMK1qiulWvnmttcAx7UbDWbj6fIWswsJMm-klQ39WETvG95cijiNLbkIlpQYqbC0k/s1600/jaxbgen2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjybtUD0ptpCXzxFTrXNqPURp0cL-jowYMWTXVQI9yOrrhykQFcDt9X7IQ-WMhhImPZyxoJ3o4fzEcMK1qiulWvnmttcAx7UbDWbj6fIWswsJMm-klQ39WETvG95cijiNLbkIlpQYqbC0k/s1600/jaxbgen2.png&quot; height=&quot;259&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Google App Engine doesn&#39;t include the com.sun.xml.ws.* classes that are normally used by a JAX-WS service. So we need to create our own servlet that handles the requests and invokes the HelloWorld class. This is where the magic happens. Most of the code in this class is generic for any webservice. We implemented everything in a single class for this example, but in a real application you want to refactor the generic code to a super class that can be reused for each web service.&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class HelloWorldServlet extends HttpServlet {

    public static final String NS = &quot;http://appengine.redheap.com/&quot;;
    public static final QName QNAME_SAY_HELLO = new QName(NS, &quot;sayHello&quot;);
    public static final QName QNAME_OTHER = new QName(NS, &quot;otherOperation&quot;);

    private final HelloWorld serviceImpl = new HelloWorld();

    private static final MessageFactory messageFactory;

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
                                                                                           IOException {
        try {
            MimeHeaders headers = getHeaders(request);
            InputStream in = request.getInputStream();
            SOAPMessage soapReq = messageFactory.createMessage(headers, in);
            SOAPMessage soapResp = handleSOAPRequest(soapReq);
            response.setStatus(HttpServletResponse.SC_OK);
            response.setContentType(&quot;text/xml;charset=\&quot;UTF-8\&quot;&quot;);
            OutputStream out = response.getOutputStream();
            soapResp.writeTo(out);
            out.flush();
        } catch (SOAPException e) {
            throw new IOException(&quot;exception while creating SOAP message&quot;, e);
        }
    }

    public MimeHeaders getHeaders(HttpServletRequest request) {
        MimeHeaders retval = new MimeHeaders();
        Enumeration&lt;String&gt; headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            String value = request.getHeader(name);
            StringTokenizer values = new StringTokenizer(value, &quot;,&quot;);
            while (values.hasMoreTokens()) {
                retval.addHeader(name, values.nextToken().trim());
            }
        }
        return retval;
    }

    protected SOAPMessage handleSOAPRequest(SOAPMessage request) throws SOAPException {
        Iterator iter = request.getSOAPBody().getChildElements();
        Object respPojo = null;
        while (iter.hasNext()) {
            // find first Element child
            Object child = iter.next();
            if (child instanceof SOAPElement) {
                respPojo = handleSOAPRequestElement((SOAPElement) child);
                break;
            }
        }
        SOAPMessage soapResp = messageFactory.createMessage();
        SOAPBody respBody = soapResp.getSOAPBody();
        if (respPojo != null) {
            JAXB.marshal(respPojo, new SAAJResult(respBody));
        } else {
            SOAPFault fault = respBody.addFault();
            fault.setFaultString(&quot;Unknown SOAP request&quot;);
        }
        return soapResp;
    }

    protected Object handleSOAPRequestElement(SOAPElement reqElem) {
        QName reqName = reqElem.getElementQName();
        if (QNAME_SAY_HELLO.equals(reqName)) {
            return handleSayHello(JAXB.unmarshal(new DOMSource(reqElem), SayHello.class));
        } else if (QNAME_OTHER.equals(reqName)) {
            //
        }
        return null;
    }

    protected SayHelloResponse handleSayHello(SayHello request) {
        SayHelloResponse response = new SayHelloResponse();
        response.setReturn(serviceImpl.sayHello(request.getPerson()));
        return response;
    }

    static {
        try {
            messageFactory = MessageFactory.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
&lt;/string&gt;&lt;/pre&gt;
&lt;br /&gt;
Remove all entries from web.xml that were created by the web service wizard in JDeveloper and register our own servlet. The &lt;code&gt;url-pattern&lt;/code&gt; has to match the endpoint you configured in the &lt;code&gt;soap:address&lt;/code&gt; in the WSDL file.&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;web-app version=&quot;2.5&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns=&quot;http://java.sun.com/xml/ns/javaee&quot; xsi:schemalocation=&quot;http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;&amp;gt;
    &amp;lt;servlet&amp;gt;
        &amp;lt;servlet-name&amp;gt;HelloWorldServlet&amp;lt;/servlet-name&amp;gt;
        &amp;lt;servlet-class&amp;gt;com.redheap.appengine.HelloWorldServlet&amp;lt;/servlet-class&amp;gt;
    &amp;lt;/servlet&amp;gt;
    &amp;lt;servlet-mapping&amp;gt;
        &amp;lt;servlet-name&amp;gt;HelloWorldServlet&amp;lt;/servlet-name&amp;gt;
        &amp;lt;url-pattern&amp;gt;/HelloWorldService&amp;lt;/url-pattern&amp;gt;
    &amp;lt;/servlet-mapping&amp;gt;
&amp;lt;/web-app&amp;gt;&lt;/pre&gt;
&lt;br /&gt;
Finally all we need to do is add some maven goals to JDeveloper so we can select them from the build menu. To do this, go to the Tools menu and select Preferences. Then go to the Maven &amp;gt; Phases/Goals and add a goal to the list of Selected Phases/Goals:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwBGm8qvqsd0IjB6uGX9BAMRslEblR4t_9z7n9FBX_gy9dDkCwMR431aPMvuFSaeV10_91R9jpO7SXzIQ1GApZtEWBOORJhWPizZsSCqLs-6d_5UWBHOlp9QE835cR7ETrCLRG0v0IQ70/s1600/mvnphases.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwBGm8qvqsd0IjB6uGX9BAMRslEblR4t_9z7n9FBX_gy9dDkCwMR431aPMvuFSaeV10_91R9jpO7SXzIQ1GApZtEWBOORJhWPizZsSCqLs-6d_5UWBHOlp9QE835cR7ETrCLRG0v0IQ70/s1600/mvnphases.png&quot; height=&quot;228&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Add a goal to Maven preferences&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Add two goals: &lt;code&gt;com.google.appengine:appengine-maven-plugin:devserver&lt;/code&gt; and &lt;code&gt;com.google.appengine:appengine-maven-plugin:update&lt;/code&gt;. The first one is to start a local AppEngine server for testing and the second one is to deploy your application to the real Google App Engine.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0L8OBU88szAULXBlhsSXNvaLkdSkCSm4snIJolCCJE2NdFMrnPp4SjXBSEDiFqtPOHxiy5YB7SSgvyRlggzhS2E1dkGVgfGVjbSTMszctylL8p1t6WSaHfjFiY3K3NFYZjU1N5Swn7rk/s1600/mvndevserver.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0L8OBU88szAULXBlhsSXNvaLkdSkCSm4snIJolCCJE2NdFMrnPp4SjXBSEDiFqtPOHxiy5YB7SSgvyRlggzhS2E1dkGVgfGVjbSTMszctylL8p1t6WSaHfjFiY3K3NFYZjU1N5Swn7rk/s1600/mvndevserver.png&quot; height=&quot;320&quot; width=&quot;307&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Add Maven goals&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
If everything is well, you can now run your application:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Right-click the &lt;code&gt;pom.xml&lt;/code&gt; in the Application Resources &amp;gt; Build Files and run maven phase &lt;code&gt;install&lt;/code&gt; from the &lt;code&gt;Run Maven Goal Profile &quot;Default&quot;&lt;/code&gt; popup menu. This should compile and build your project&lt;/li&gt;
&lt;li&gt;Right-click the &lt;code&gt;pom.xml&lt;/code&gt; in the AppEngineJaxWs-ear project and run the &lt;code&gt;appengine:devserver&lt;/code&gt; phase from the same popup menu. This should launch the local AppEngine server and you should be able to download the WSDL at &lt;a href=&quot;http://localhost:8080/HelloWorldService.wsdl&quot; target=&quot;_blank&quot;&gt;http://localhost:8080/HelloWorldService.wsdl&lt;/a&gt; and invoke the local webservice at&amp;nbsp;&lt;a href=&quot;http://localhost:8080/HelloWorldService&quot; target=&quot;_blank&quot;&gt;http://localhost:8080/HelloWorldService&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Once this is fine, you can run the &lt;code&gt;appengine:update&lt;/code&gt; phase from the AppEngineJaxWs-ear project. This installs the project at your Google AppEngine server. Be sure to run this from the command line the first time and not from JDeveloper. The reason is it will launch a web browser to authenticate yourself and you have to enter a code from the web browser into the maven build. This cannot be done when building from JDeveloper as it doesn&#39;t allow you to enter information.&lt;/li&gt;
&lt;/ol&gt;
You&#39;re done. Enjoy your Google AppEngine JAX-WS Soap WebService. You can also give my instance a try. The WSDL is available at&amp;nbsp;&lt;a href=&quot;https://redheap-jaxws.appspot.com/HelloWorldService.wsdl&quot; target=&quot;_blank&quot;&gt;https://redheap-jaxws.appspot.com/HelloWorldService.wsdl&lt;/a&gt;. Give it a try in SoapUI.&lt;br /&gt;
&lt;br /&gt;
As always you can&amp;nbsp;&lt;a href=&quot;https://java.net/projects/redheap/downloads/directory/jdev12120/AppEngineJaxWs&quot; target=&quot;_blank&quot;&gt;download the full sample&lt;/a&gt;&amp;nbsp;application or&amp;nbsp;&lt;a href=&quot;https://java.net/projects/redheap/sources/svn/show/jdev12120/AppEngineJaxWs&quot; target=&quot;_blank&quot;&gt;browse the subversion repository&lt;/a&gt;&amp;nbsp;to look at the source code. If you want to have a quick look at the solution start with the&amp;nbsp;&lt;a href=&quot;https://java.net/projects/redheap/sources/svn/content/jdev12120/AppEngineJaxWs/AppEngineJaxWs-war/src/main/java/com/redheap/appengine/HelloWorldServlet.java&quot; target=&quot;_blank&quot;&gt;com.redheap.appengine.HelloWorldServlet&lt;/a&gt;&amp;nbsp;servlet that does most of the important work.</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/8293608275748995025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2014/04/host-soap-web-service-on-google-app-engine.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/8293608275748995025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/8293608275748995025'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2014/04/host-soap-web-service-on-google-app-engine.html' title='Host a Soap Web Service on Google App Engine with JAX-WS'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJvsc-NqUgYhbOeFDfLGZnSolbqMMFKfyd2eUFF_wgV9OrEunjgUxpPiKAoBW9GvTgBm6fXnDsjuVMmxhb1r4FVHcoMS4EmgLJTZAXO8Ym5YIx6Q-6LwaUH4siHFCjzy1RwJw9zuqpubM/s72-c/soapui.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-91638456534683345</id><published>2014-03-31T17:45:00.001+02:00</published><updated>2015-01-24T13:28:11.637+01:00</updated><title type='text'>Managed Bean changes should mark their ADF Scope dirty in a HA cluster</title><content type='html'>We&#39;re starting development on a new ADF application and the plan is to run this in a high-available weblogic cluster. The &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/web.1111/b31974/web_getstarted.htm#CHDJDDGJ&quot; target=&quot;_blank&quot;&gt;documentation&lt;/a&gt; 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:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;Map viewScope = ADFContext.getCurrent().getViewScope();
ControllerContext.getInstance().markScopeDirty(viewScope);
&lt;/pre&gt;
&lt;br /&gt;
That&#39;s not too difficult but it&#39;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!&lt;br /&gt;
&lt;br /&gt;
Full source code is at the end of this posting, but I&#39;ll explain the vital parts first. We&#39;ve create a JSF PhaseListener that listens to each JSF phase transition:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public PhaseId getPhaseId() {
    return PhaseId.ANY_PHASE;
}
&lt;/pre&gt;
&lt;br /&gt;
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&lt;br /&gt;
&lt;br /&gt;
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&#39;re in trouble when the digests changed and the developer has not invoked &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/apirefs.1111/e10651/oracle/adf/controller/ControllerContext.html#markScopeDirty(java.util.Map)&quot; target=&quot;_blank&quot;&gt;ControllerContext.markScopeDirty&lt;/a&gt;. 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&#39;t actually abort JSF processing as that would also cancel any other PhaseListeners. We don&#39;t want to make things worse.&lt;br /&gt;
&lt;br /&gt;
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&#39;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&#39;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.&lt;br /&gt;
&lt;br /&gt;
The demo workspace includes a singe page application to demonstrate the&amp;nbsp;DirtyScopePhaseListener. Simply run that page and press the button marked &quot;change viewState without marking dirty&quot;. This will log an error in the console that neatly explains the internal state of&amp;nbsp;myViewScopeBean in the ADF viewScope was changed:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTpYRl_9c5L8hdJ7QklE87tuOkdV_GI3vSikQWQ_W9a0CulnNN_6w7KG2jvKbCQ2f2ZTto9EAJq6Y4-cd7VErY3_wmuwegzP2t4rlSsvzYOGL8RMDT4FQIhmPwjdL4xiIzKKxg5jur55k/s1600/Snap11.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTpYRl_9c5L8hdJ7QklE87tuOkdV_GI3vSikQWQ_W9a0CulnNN_6w7KG2jvKbCQ2f2ZTto9EAJq6Y4-cd7VErY3_wmuwegzP2t4rlSsvzYOGL8RMDT4FQIhmPwjdL4xiIzKKxg5jur55k/s1600/Snap11.png&quot; height=&quot;360&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Hopefully this JSF PhaseListener can be a valuable tool for anyone building a ADF application intended to run on a session-replicating cluster.&lt;br /&gt;
&lt;br /&gt;
As always you can &lt;a href=&quot;https://java.net/projects/redheap/downloads/directory/jdev11117/ClusteredDirtyScope&quot; target=&quot;_blank&quot;&gt;download the full sample&lt;/a&gt; application or &lt;a href=&quot;https://java.net/projects/redheap/sources/svn/show/jdev11117/ClusteredDirtyScope&quot; target=&quot;_blank&quot;&gt;browse the subversion repository&lt;/a&gt; to look at the source code. If you want to have a quick look at the solution start with the &lt;a href=&quot;https://java.net/projects/redheap/sources/svn/content/jdev11117/ClusteredDirtyScope/ClusteredDirtyScope/src/com/redheap/dirtyscope/DirtyScopePhaseListener.java&quot; target=&quot;_blank&quot;&gt;com.redheap.dirtyscope.DirtyScopePhaseListener&lt;/a&gt; phase listener and the &lt;a href=&quot;https://java.net/projects/redheap/sources/svn/content/jdev11117/ClusteredDirtyScope/ClusteredDirtyScope/src/com/redheap/dirtyscope/ADFScopeChecker.java&quot; target=&quot;_blank&quot;&gt;com.redheap.dirtyscope.ADFScopeChecker&lt;/a&gt; class that does all the digest calculating and checking.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update&lt;/b&gt;: The sample code is broken. It only looks at the pageFlowScope and viewScope of the unbounded taskflow and does not consider any state in bounded taskflows and viewScopes running in regions. I am working on an &lt;a href=&quot;https://github.com/wvanderdeijl/adfc-dirty-scopes&quot; target=&quot;_blank&quot;&gt;improved version&lt;/a&gt; and will post a new blog entry once that is finished.</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/91638456534683345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2014/03/managed-bean-changes-should-mark-their.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/91638456534683345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/91638456534683345'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2014/03/managed-bean-changes-should-mark-their.html' title='Managed Bean changes should mark their ADF Scope dirty in a HA cluster'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTpYRl_9c5L8hdJ7QklE87tuOkdV_GI3vSikQWQ_W9a0CulnNN_6w7KG2jvKbCQ2f2ZTto9EAJq6Y4-cd7VErY3_wmuwegzP2t4rlSsvzYOGL8RMDT4FQIhmPwjdL4xiIzKKxg5jur55k/s72-c/Snap11.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-7747464200767928061</id><published>2014-02-24T23:45:00.002+01:00</published><updated>2014-02-24T23:45:32.572+01:00</updated><title type='text'>ADFLogger JAX-WS SoapHandler to log request, reponse and faults</title><content type='html'>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.&lt;br /&gt;
&lt;br /&gt;
Let&#39;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:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhICq_6FTqTW_fB-h0aBXi1NMmHf0oibI6z6aFKE0fF-fKIDmkybOmXY4T5nElBnv9CWXZmvFd3gSQ7cr-rG073IuiFA2bl_IZ6KvoGaHwcZCfnj4cKHwCIkLAIsYDLZ6ab_faA4XuKwEw/s1600/soaplog.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhICq_6FTqTW_fB-h0aBXi1NMmHf0oibI6z6aFKE0fF-fKIDmkybOmXY4T5nElBnv9CWXZmvFd3gSQ7cr-rG073IuiFA2bl_IZ6KvoGaHwcZCfnj4cKHwCIkLAIsYDLZ6ab_faA4XuKwEw/s1600/soaplog.png&quot; height=&quot;306&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;SOAP request and response logged when receiving SOAP fault&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
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 &lt;a href=&quot;http://www.redheap.com/2013/01/instrumentation-performance-diagnostics-with-adflogger.html&quot;&gt;performance analysis with the Log Analyzer&lt;/a&gt;. This breaks down your entire request and our LoggingSoapHandler times the milliseconds it took to invoke the web service.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcYYmicm9qYJg2DE6ImsUkdAC4QScdJYdkfugggkCSM5RJqg7KtkL9Kq4Iw8X4w20gD1PXG3wj4WXnriUsHJYU5EIcceQk6jRxteSCkjZe8LofvnLyD8XFEqqQBqyyR5LgJ1oeySkWK7g/s1600/soaplog-analyzer.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcYYmicm9qYJg2DE6ImsUkdAC4QScdJYdkfugggkCSM5RJqg7KtkL9Kq4Iw8X4w20gD1PXG3wj4WXnriUsHJYU5EIcceQk6jRxteSCkjZe8LofvnLyD8XFEqqQBqyyR5LgJ1oeySkWK7g/s1600/soaplog-analyzer.png&quot; height=&quot;297&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Log Analyzer showing this web service call took 5 msecs&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
This magic is performed by a &lt;a href=&quot;http://docs.oracle.com/javase/7/docs/api/javax/xml/ws/handler/soap/SOAPHandler.html&quot; target=&quot;_blank&quot;&gt;JAX-WS SoapHandler&lt;/a&gt;. 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.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguDvH-WAb1SY7cgsfB9Uy27s2XHetQjbFKi98dzAyyM4-c33B9WCd0qxqQGcKw8R16U5PFdRzZ6MV31j7GHB77MGLtWP5Gxey7S_fZ-xNcI3v0Prel4I0xzocs5pzJ6OkGl0dptPl4em0/s1600/soaplog-wsproxy.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguDvH-WAb1SY7cgsfB9Uy27s2XHetQjbFKi98dzAyyM4-c33B9WCd0qxqQGcKw8R16U5PFdRzZ6MV31j7GHB77MGLtWP5Gxey7S_fZ-xNcI3v0Prel4I0xzocs5pzJ6OkGl0dptPl4em0/s1600/soaplog-wsproxy.png&quot; height=&quot;300&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Add LoggingSoapHandler as a Handler on the JAX-WS Proxy&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
You can get the &lt;a href=&quot;https://java.net/projects/redheap/sources/svn/content/jdev11117/LoggingSoapHandler/LoggingSoapHandler/src/com/redheap/soaplog/LoggingSoapHandler.java&quot; target=&quot;_blank&quot;&gt; full source code for the com.redheap.soaplog.LoggingSoapHandler class&lt;/a&gt;&amp;nbsp;so you can add it to your own project or library. The embedded documentation is rather elaborate but I&#39;ll also explain the most important bits here.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;JAX-WS will invoke the &lt;code&gt;handleMessage&lt;/code&gt; method when sending or receiving a message. We check if this is an outbound message (aka request) or an inbound message (aka response):&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;    public boolean handleMessage(final SOAPMessageContext context) {
        if (Boolean.TRUE.equals(context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY))) {
            handleRequest(context);
        } else {
            handleResponse(context);
        }
        return true; // return true to continue processing other handlers
    }
&lt;/pre&gt;
&lt;br /&gt;
When the log levels are set to verbose, the &lt;code&gt;handleRequest&lt;/code&gt; method will log the fact that a web service is being invoked including the end point URL and it will log the actual request payload. Regardless the log level it will also invoke ADFLogger#begin to start a performance timer so the time spent invoking the web service will show up in the log analyzer. Finally, it also adds the request payload as well as a timestamp to the &lt;code&gt;SOAPMessageContext&lt;/code&gt;. More on this later.&lt;br /&gt;
&lt;br /&gt;
The &lt;code&gt;handleResponse&lt;/code&gt; method will stop the performance timer by invoking ADFLogger#end. When the log levels are set to verbose, it will log the response payload and get the starting timestamp from the &lt;code&gt;SOAPMessageContext&lt;/code&gt; (which was put there by &lt;code&gt;handleRequest&lt;/code&gt;) and calculate the time spent and log this to the normal ADFLogger.&lt;br /&gt;
&lt;br /&gt;
When an error occurs, such as receiving a soap fault from the web service, the JAX-WS proxy will not invoke the &lt;code&gt;handleMessage&lt;/code&gt; method but it will invoke &lt;code&gt;handleFault&lt;/code&gt;. Similar to &lt;code&gt;handleResponse&lt;/code&gt; we stop the timer and when being verbose log the time spent on invoking the web service. But the really nice thing it does is log the fault response payload as well as the original request payload at warning level. This is why &lt;code&gt;handleMessage&lt;/code&gt; put the request itself in the &lt;code&gt;SOAPMessageContext&lt;/code&gt;, so &lt;code&gt;handleFault&lt;/code&gt; can get the request there. It is a method for sharing state between the different methods of the (stateless) handler. The result can be seen in the first screenshot of this post.&lt;br /&gt;
&lt;br /&gt;
We also made sure each service and service operation uses a distinct ADFLogger. In this example we are invoking the &lt;code&gt;divideTen&lt;/code&gt; operation on the &lt;code&gt;MyTestService&lt;/code&gt; web service which means we are using the &lt;code&gt;com.redheap.soaplog.LoggingSoapHandler.&lt;b&gt;&lt;i&gt;MyTestService.divideTen&lt;/i&gt;&lt;/b&gt;&lt;/code&gt; logger. Since log levels work like a hierarchy this allows you to set the default log level for all LoggingSoapHandlers at &lt;code&gt;com.redheap.soaplog.LoggingSoapHandler&lt;/code&gt;, or you can override this for all operations of a specific service at &lt;code&gt;com.redheap.soaplog.LoggingSoapHandler.&lt;b&gt;&lt;i&gt;SERVICENAME&lt;/i&gt;&lt;/b&gt;&lt;/code&gt; or use the full name of the logger to set it for a specific operation. This can prove to be very valuable in a production environment where you can enable very specific logging at runtime without overwhelming your log files.
&lt;br /&gt;
&lt;br /&gt;
As always you can &lt;a href=&quot;https://java.net/projects/redheap/downloads/directory/jdev11117/LoggingSoapHandler&quot; target=&quot;_blank&quot;&gt;download the full sample&lt;/a&gt; application or &lt;a href=&quot;https://java.net/projects/redheap/sources/svn/show/jdev11117/LoggingSoapHandler&quot; target=&quot;_blank&quot;&gt;browse the subversion repository&lt;/a&gt; to look at the source code. All you really need is the single &lt;a href=&quot;https://java.net/projects/redheap/sources/svn/content/jdev11117/LoggingSoapHandler/LoggingSoapHandler/src/com/redheap/soaplog/LoggingSoapHandler.java&quot; target=&quot;_blank&quot;&gt;com.redheap.soaplog.LoggingSoapHandler&lt;/a&gt; class, but the workspace also includes a very simple JSF page to invoking a (local) web service that divides 10 by the given input. This was used to create the screenshots and entering 0 as an input will give a nice divide by zero soap fault for testing.&lt;br /&gt;
&lt;br /&gt;
The workspace also includes the &lt;code&gt;com.redheap.soaplog.Tester&lt;/code&gt; class to demonstrate the logger from a plain java program. You can simply run that class, but be sure to first run the &lt;code&gt;com.redheap.soaplog.test.MyTestService&lt;/code&gt; service to ensure it is deployed to your local weblogic. Switch between the two run profiles in the project properties to set the verbosity of the logger when running the &lt;code&gt;Tester&lt;/code&gt;.</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/7747464200767928061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2014/02/adflogger-jax-ws-soaphandler.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/7747464200767928061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/7747464200767928061'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2014/02/adflogger-jax-ws-soaphandler.html' title='ADFLogger JAX-WS SoapHandler to log request, reponse and faults'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhICq_6FTqTW_fB-h0aBXi1NMmHf0oibI6z6aFKE0fF-fKIDmkybOmXY4T5nElBnv9CWXZmvFd3gSQ7cr-rG073IuiFA2bl_IZ6KvoGaHwcZCfnj4cKHwCIkLAIsYDLZ6ab_faA4XuKwEw/s72-c/soaplog.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-6504656967987188268</id><published>2014-01-03T11:25:00.000+01:00</published><updated>2015-02-08T11:53:39.671+01:00</updated><title type='text'>Configuring ADF Faces for development</title><content type='html'>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.&lt;br /&gt;
&lt;br /&gt;
More background information on all ADF Faces configuration parameters can be found in the &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/web.1111/b31973/ap_config.htm#BABFIGBA&quot; target=&quot;_blank&quot;&gt;appendix of the Web User Interface Developer&#39;s Guide&lt;/a&gt;. The ones we want to change during development are:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;org.apache.myfaces.trinidad.CHECK_FILE_MODIFICATION&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; 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.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;org.apache.myfaces.trinidad.resource.DEBUG&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; to enable resource debugging and prevent the client from caching resources (eg javascript libraries, images, CSS, etc)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; to disable CSS content compression and use human-readable CSS class names for skinning&lt;/li&gt;
&lt;li&gt;&lt;code&gt;org.apache.myfaces.trinidad.DEBUG_JAVASCRIPT&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; to non-obfuscated javascript&lt;/li&gt;
&lt;li&gt;&lt;code&gt;oracle.adf.view.rich.LOGGER_LEVEL&lt;/code&gt; to &lt;code&gt;FINE&lt;/code&gt; to enable client side javascript logging. Other allowed values are SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, and ALL&lt;/li&gt;
&lt;li&gt;&lt;code&gt;oracle.adf.view.rich.ASSERT_ENABLED&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; to enable client-side javascript assertions&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;All you have to do is copy and paste the context parameters below and add them to your &lt;code&gt;WEB-INF/web.xml&lt;/code&gt; file:&lt;br /&gt;
&lt;div&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;  &amp;lt;context-param&amp;gt;
    &amp;lt;description&amp;gt;If this parameter is true, there will be an automatic check
                 of the modification date of your JSPs, and saved state will
                 be discarded when JSP&#39;s change. It will also automatically
                 check if your skinning css files have changed without you
                 having to restart the server.&amp;lt;/description&amp;gt;
    &amp;lt;param-name&amp;gt;org.apache.myfaces.trinidad.CHECK_FILE_MODIFICATION&amp;lt;/param-name&amp;gt;
    &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;
  &amp;lt;/context-param&amp;gt;
  &amp;lt;context-param&amp;gt;
    &amp;lt;description&amp;gt;Set to true to have ADF Faces set HTTP response headers to
                 let the browser know that resource (such as javascript
                 files, images, and CSS) should not be cached&amp;lt;/description&amp;gt;
    &amp;lt;param-name&amp;gt;org.apache.myfaces.trinidad.resource.DEBUG&amp;lt;/param-name&amp;gt;
    &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;
  &amp;lt;/context-param&amp;gt;
  &amp;lt;context-param&amp;gt;
    &amp;lt;description&amp;gt;Set to true to disable compression of CSS class names for
                 skinning keys and have more human readable class
                 names&amp;lt;/description&amp;gt;
    &amp;lt;param-name&amp;gt;org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION&amp;lt;/param-name&amp;gt;
    &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;
  &amp;lt;/context-param&amp;gt;
  &amp;lt;context-param&amp;gt;
    &amp;lt;description&amp;gt;Set to true to disable obfuscation and compaction of ADF
                 javascript that also removes comments and
                 whitespace.&amp;lt;/description&amp;gt;
    &amp;lt;param-name&amp;gt;org.apache.myfaces.trinidad.DEBUG_JAVASCRIPT&amp;lt;/param-name&amp;gt;
    &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;
  &amp;lt;/context-param&amp;gt;
  &amp;lt;context-param&amp;gt;
    &amp;lt;description&amp;gt;Set the level of client side javascipt logging. Default is
                 OFF, other allowed values are SEVERE,WARNING,INFO,CONFIG,
                 FINE,FINER,FINEST, and ALL&amp;lt;/description&amp;gt;
    &amp;lt;param-name&amp;gt;oracle.adf.view.rich.LOGGER_LEVEL&amp;lt;/param-name&amp;gt;
    &amp;lt;param-value&amp;gt;FINER&amp;lt;/param-value&amp;gt;
  &amp;lt;/context-param&amp;gt;
  &amp;lt;context-param&amp;gt;
    &amp;lt;description&amp;gt;Set to true to enable assertions in client side 
                 javascript. This is frequently used to assert valid
                 argument types to JS methods&amp;lt;/description&amp;gt;
    &amp;lt;param-name&amp;gt;oracle.adf.view.rich.ASSERT_ENABLED&amp;lt;/param-name&amp;gt;
    &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;
  &amp;lt;/context-param&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Most of these parameter have a performance impact&lt;/b&gt; and should not be enabled on production environments, or user acceptance and performance testing environments. This can be achieved using deployment plans. These can make changes to deployment descriptors during deployment and the &lt;code&gt;WEB-INF/web.xml&lt;/code&gt; file is one of these deployment descriptors. Simple save the file below as &lt;code&gt;plan-nodev.xml&lt;/code&gt; and use it during deployment to override these settings. You do need to change the &lt;code&gt;application-name&lt;/code&gt; and &lt;code&gt;module-name&lt;/code&gt; elements to match your application.&lt;br /&gt;
&lt;br /&gt;
If you read the deployment plan you can see it defines two variables: &lt;code&gt;developMode&lt;/code&gt; and &lt;code&gt;adfJavascriptLoggerLevel&lt;/code&gt; that are used in the overrides to make changes to the &lt;code&gt;WEB-INF/web.xml&lt;/code&gt; file. I opted to use a single &lt;code&gt;developMode&lt;/code&gt; variable to change all booleans to &lt;code&gt;false&lt;/code&gt;. You could also create individual variables for each parameter and change the override to use these separate variables. That would give you individual control over each parameter. Without further ado here is the deployment plan:&lt;br /&gt;
&lt;pre class=&quot;brush:xml;highlight:[5,17]&quot;&gt;&amp;lt;?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39;?&amp;gt;
&amp;lt;deployment-plan xmlns=&quot;http://xmlns.oracle.com/weblogic/deployment-plan&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
                 xsi:schemaLocation=&quot;http://xmlns.oracle.com/weblogic/deployment-plan http://xmlns.oracle.com/weblogic/deployment-plan/1.0/deployment-plan.xsd&quot;
                 global-variables=&quot;false&quot;&amp;gt;
  &amp;lt;application-name&amp;gt;DeploySample.ear&amp;lt;/application-name&amp;gt;
  &amp;lt;variable-definition&amp;gt;
    &amp;lt;variable&amp;gt;
      &amp;lt;name&amp;gt;developMode&amp;lt;/name&amp;gt;
      &amp;lt;value&amp;gt;false&amp;lt;/value&amp;gt;
    &amp;lt;/variable&amp;gt;
    &amp;lt;variable&amp;gt;
      &amp;lt;name&amp;gt;adfJavascriptLoggerLevel&amp;lt;/name&amp;gt;
      &amp;lt;value&amp;gt;NONE&amp;lt;/value&amp;gt;
    &amp;lt;/variable&amp;gt;
  &amp;lt;/variable-definition&amp;gt;
  &amp;lt;module-override&amp;gt;
    &amp;lt;module-name&amp;gt;DeploySample.war&amp;lt;/module-name&amp;gt;
    &amp;lt;module-type&amp;gt;war&amp;lt;/module-type&amp;gt;
    &amp;lt;module-descriptor external=&quot;false&quot;&amp;gt;
      &amp;lt;root-element&amp;gt;web-app&amp;lt;/root-element&amp;gt;
      &amp;lt;uri&amp;gt;WEB-INF/web.xml&amp;lt;/uri&amp;gt;
      &amp;lt;variable-assignment&amp;gt;
        &amp;lt;name&amp;gt;developMode&amp;lt;/name&amp;gt;
        &amp;lt;xpath&amp;gt;/web-app/context-param/[param-name=&quot;org.apache.myfaces.trinidad.DEBUG_JAVASCRIPT&quot;]/param-value&amp;lt;/xpath&amp;gt;
        &amp;lt;operation&amp;gt;replace&amp;lt;/operation&amp;gt;
      &amp;lt;/variable-assignment&amp;gt;
      &amp;lt;variable-assignment&amp;gt;
        &amp;lt;name&amp;gt;developMode&amp;lt;/name&amp;gt;
        &amp;lt;xpath&amp;gt;/web-app/context-param/[param-name=&quot;org.apache.myfaces.trinidad.resource.DEBUG&quot;]/param-value&amp;lt;/xpath&amp;gt;
        &amp;lt;operation&amp;gt;replace&amp;lt;/operation&amp;gt;
      &amp;lt;/variable-assignment&amp;gt;
      &amp;lt;variable-assignment&amp;gt;
        &amp;lt;name&amp;gt;developMode&amp;lt;/name&amp;gt;
        &amp;lt;xpath&amp;gt;/web-app/context-param/[param-name=&quot;oracle.adf.view.rich.ASSERT_ENABLED&quot;]/param-value&amp;lt;/xpath&amp;gt;
        &amp;lt;operation&amp;gt;replace&amp;lt;/operation&amp;gt;
      &amp;lt;/variable-assignment&amp;gt;
      &amp;lt;variable-assignment&amp;gt;
        &amp;lt;name&amp;gt;developMode&amp;lt;/name&amp;gt;
        &amp;lt;xpath&amp;gt;/web-app/context-param/[param-name=&quot;org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION&quot;]/param-value&amp;lt;/xpath&amp;gt;
        &amp;lt;operation&amp;gt;replace&amp;lt;/operation&amp;gt;
      &amp;lt;/variable-assignment&amp;gt;
      &amp;lt;variable-assignment&amp;gt;
        &amp;lt;name&amp;gt;adfJavascriptLoggerLevel&amp;lt;/name&amp;gt;
        &amp;lt;xpath&amp;gt;/web-app/context-param/[param-name=&quot;oracle.adf.view.rich.LOGGER_LEVEL&quot;]/param-value&amp;lt;/xpath&amp;gt;
        &amp;lt;operation&amp;gt;replace&amp;lt;/operation&amp;gt;
      &amp;lt;/variable-assignment&amp;gt;
    &amp;lt;/module-descriptor&amp;gt;
  &amp;lt;/module-override&amp;gt;
&amp;lt;/deployment-plan&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
In the intro I also promised to change a parameter in the &lt;code&gt;WEB-INF/trinidad-config.xml&lt;/code&gt; file. You can set &lt;code&gt;debug-output&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; to get better human readable HTML. It will be properly indented and even have HTML comments before each component to show its full ID. This makes it much easier to look at the generated HTML or PPR responses. The problem with the &lt;code&gt;WEB-INF/trinidad-config.xml&lt;/code&gt; file is that it is not an official JEE deployment descriptor so you cannot override its value in a deployment plan. But we most definitely don&#39;t want this debug mode in a production environment. Fortunately you can use EL expressions in this file and you can use those to refer to context parameters from the web.xml file. I have opted to simply look at the &lt;code&gt;org.apache.myfaces.trinidad.DEBUG_JAVASCRIPT&lt;/code&gt; parameter so we enable javascript debugging and HTML debug output with the same parameter. You could also create a separate context parameter to control this behavior. Here is the&amp;nbsp;&lt;code&gt;WEB-INF/trinidad-config.xml&lt;/code&gt;&amp;nbsp;file with EL expression:&lt;br /&gt;
&lt;pre class=&quot;brush:xml;highlight:4&quot;&gt;&amp;lt;trinidad-config xmlns=&quot;http://myfaces.apache.org/trinidad/config&quot;&amp;gt;
  &amp;lt;skin-family&amp;gt;skyros&amp;lt;/skin-family&amp;gt;
  &amp;lt;skin-version&amp;gt;v1&amp;lt;/skin-version&amp;gt;
  &amp;lt;debug-output&amp;gt;#{initParam[&#39;org.apache.myfaces.trinidad.DEBUG_JAVASCRIPT&#39;]}&amp;lt;/debug-output&amp;gt;
&amp;lt;/trinidad-config&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
If, for whatever reason, the initParam expression doesn&#39;t work you can also try to use &lt;code&gt;#{facesContext.externalContext.initParameterMap[&#39;org.apache.myfaces.trinidad.DEBUG_JAVASCRIPT&#39;]}&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
I hope this helps you to setup your project for development while also having a proper production deployment without the need to change your sources or repackage your application.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/6504656967987188268/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2014/01/configuring-adf-faces-for-development.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/6504656967987188268'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/6504656967987188268'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2014/01/configuring-adf-faces-for-development.html' title='Configuring ADF Faces for development'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-4734394841092456691</id><published>2013-11-19T15:16:00.000+01:00</published><updated>2013-11-19T17:19:14.769+01:00</updated><title type='text'>JDeveloper Extension To Suppress Warnings</title><content type='html'>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 &lt;code&gt;@SuppressWarnings&lt;/code&gt; annotation for Java code. JDeveloper 12c can even use this annotation to suppress any warning, not only the ones supported by the java compiler.&lt;br /&gt;
&lt;br /&gt;
However, much of an ADF (or SOA) application is XML files, not java. JDeveloper 12c doesn&#39;t offer a way to suppress warnings in these files. Luckily the auditing framework is highly pluggable and after some inspection how the&amp;nbsp;&lt;code&gt;@SuppressWarning&lt;/code&gt; annotation is implemented in the auditing framework, I could create something similar for XML files.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7wxPVecW528Z68iLkmQILmgaUbWT-lPam81ffyWJ4fQ_1KOi5_tUO_sM0ptyp4sxCcyWFu7EFjtXZf8k0J8eRViZkErt0I5nPfJmsXn0XNenkPZzpZEq1FrsT47gTbBqzT3lBwrwYeVs/s1600/Snap39.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;201&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7wxPVecW528Z68iLkmQILmgaUbWT-lPam81ffyWJ4fQ_1KOi5_tUO_sM0ptyp4sxCcyWFu7EFjtXZf8k0J8eRViZkErt0I5nPfJmsXn0XNenkPZzpZEq1FrsT47gTbBqzT3lBwrwYeVs/s400/Snap39.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Suppressing a warning in a JSF file&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
The screenshot above shows how the extension works. See the warning for the &lt;code&gt;value&lt;/code&gt; property of the &lt;code&gt;af:outputText&lt;/code&gt; 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 &lt;code&gt;@SuppressWarnings&lt;/code&gt; annotation in java.&lt;br /&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwGrUlf0BL5KrUhtBGaubER0EJxW0WUkQu5d7Xk5Tu9MJpElIQEG1SzoiFF7GohEi1TeD5oys5NCcjgkLVumvjaMyEhFtpNGWYm6Tolnl3DX97xezYYhuO1bg6iY1VaTDTucH5PgioFNI/s1600/Snap40.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;202&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwGrUlf0BL5KrUhtBGaubER0EJxW0WUkQu5d7Xk5Tu9MJpElIQEG1SzoiFF7GohEi1TeD5oys5NCcjgkLVumvjaMyEhFtpNGWYm6Tolnl3DX97xezYYhuO1bg6iY1VaTDTucH5PgioFNI/s400/Snap40.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Suppressed warning in a JSF file&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
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.&lt;br /&gt;
&lt;br /&gt;
I have plans on building a &lt;a href=&quot;http://www.sonarqube.org/&quot; target=&quot;_blank&quot;&gt;SonarQube&lt;/a&gt; extension to run &lt;a href=&quot;https://blogs.oracle.com/jdevextensions/entry/running_an_audit_from_the&quot; target=&quot;_blank&quot;&gt;ojaudit&lt;/a&gt; (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.&lt;br /&gt;
&lt;br /&gt;
The extension is already live, so simply start JDeveloper 12c and use the Help &amp;gt; Check for Updates feature. Be sure to check &quot;Open Source and Partner Extensions&quot;. You should be able to find the &quot;Suppress Audit Warnings&quot; extension. Please leave a comment below if you have any questions or suggestions for a future version.&lt;br /&gt;
&lt;br /&gt;
If you want to see how a custom suppression scheme is built you can &lt;a href=&quot;https://java.net/projects/redheap/downloads/directory/jdev12120/SuppressWarningsSrc&quot; target=&quot;_blank&quot;&gt;download the full workspace&lt;/a&gt;&amp;nbsp;or simply&amp;nbsp;&lt;a href=&quot;https://java.net/projects/redheap/sources/svn/show/jdev12120/SuppressWarnings&quot; target=&quot;_blank&quot;&gt;browse the subversion repository&lt;/a&gt; to look at the source code.</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/4734394841092456691/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/11/jdeveloper-extension-to-suppress.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/4734394841092456691'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/4734394841092456691'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/11/jdeveloper-extension-to-suppress.html' title='JDeveloper Extension To Suppress Warnings'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7wxPVecW528Z68iLkmQILmgaUbWT-lPam81ffyWJ4fQ_1KOi5_tUO_sM0ptyp4sxCcyWFu7EFjtXZf8k0J8eRViZkErt0I5nPfJmsXn0XNenkPZzpZEq1FrsT47gTbBqzT3lBwrwYeVs/s72-c/Snap39.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-1797148706218544244</id><published>2013-11-13T22:28:00.001+01:00</published><updated>2014-01-10T11:09:09.356+01:00</updated><title type='text'>Overriding Entity doDML or prepareForDml Causes Locking Issues</title><content type='html'>It is not uncommon for people to override the &lt;code&gt;doDML&lt;/code&gt; or &lt;code&gt;prepareForDml&lt;/code&gt; method in an &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/apirefs.1111/e10653/oracle/jbo/server/EntityImpl.html&quot; target=&quot;_blank&quot;&gt;ADF BC Entity&lt;/a&gt; to do some additional work just before posting changes to the database. The official documentation even describes this extension point as being an &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/web.1111/b31974/appendix_formstriggers.htm#sm0354&quot; target=&quot;_blank&quot;&gt;equivalent to the Oracle Forms Post Processing triggers&lt;/a&gt;.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update Nov 14:&lt;/b&gt; &lt;i&gt;The issue doesn&#39;t reproduce in ADF 12.1.2.0. Inspecting of the source code seems to indicate (unpublished) bug&amp;nbsp;11896369 is to blame. Currently working with Oracle support to further investigate and ask for fix backport to 11.1.1.7&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;b&gt;Update Jan 2: &lt;/b&gt;&lt;i&gt;Oracle development acknowledged this behavior is caused by bug&amp;nbsp;&lt;/i&gt;&lt;i&gt;11896369 and a backport request has been filed to bring the fix to 11.1.1.7.&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;b&gt;Update Jan 10:&lt;/b&gt;&amp;nbsp;&lt;i&gt;Patch 11896369 is now available for download.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Let&#39;s start with an simplified example of an entity mutation another one. Below is the &lt;code&gt;doDML&lt;/code&gt; 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.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java;highlight:6&quot;&gt;@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);
}
&lt;/pre&gt;
&lt;br /&gt;
What we also need is a entity level validation on Employee that will be violated by this change. For demonstration purposes I&#39;ve setup a range validation for CommissionPct to be between 0.00 and 0.50:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF672okU5wcK-ZO1R_GxINORxnVvGZECsvUOn5RlvwjRqXh91tdXEk0F_9XirWHbHB14-RnyrlQ_-ZtzjJDjUw-uHjZBOVncnHVuH3ueQ_5OCek6pkbNvIAwoos76fGcvwZfoTySzhJqk/s1600/Snap29.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF672okU5wcK-ZO1R_GxINORxnVvGZECsvUOn5RlvwjRqXh91tdXEk0F_9XirWHbHB14-RnyrlQ_-ZtzjJDjUw-uHjZBOVncnHVuH3ueQ_5OCek6pkbNvIAwoos76fGcvwZfoTySzhJqk/s320/Snap29.png&quot; height=&quot;310&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Entity-level Validation Rule&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Now let&#39;s build a very simple ADF page to change a department and try to save the changes to the database. Here is what happens:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdsl-AWl8tWzj0bSd25n9V5ck1812nX3d89TwKbhkEtMKWx40QDHBBp9vLrzvRmlON5Ez_vB_e57qv6MP2UdRfUuQhflUqEhXp38_9ZEOdOAMbpEWqd2a8rFrbWBOGo0O6DOEHEGVLXXM/s1600/Snap30.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdsl-AWl8tWzj0bSd25n9V5ck1812nX3d89TwKbhkEtMKWx40QDHBBp9vLrzvRmlON5Ez_vB_e57qv6MP2UdRfUuQhflUqEhXp38_9ZEOdOAMbpEWqd2a8rFrbWBOGo0O6DOEHEGVLXXM/s320/Snap30.png&quot; height=&quot;146&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Validation Error in ADF Application&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Everything appears to be okay. The user is confronted with the validation error as expected. But now let&#39;s try to update the same record from a different database session:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5jMEjVv4Nxgy4llx_duPn2dJT4o7diWbq1CHsx8xpmRF3qY9Dn_u9X-94N5CgDLqVAxRhzi-AhJVQq7AwCeiG4sweDJGZFDTe4CQ7JbMRewCRU0OC-Is_RVGEKse6GCgO_SQhN3OtEGE/s1600/Snap31.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5jMEjVv4Nxgy4llx_duPn2dJT4o7diWbq1CHsx8xpmRF3qY9Dn_u9X-94N5CgDLqVAxRhzi-AhJVQq7AwCeiG4sweDJGZFDTe4CQ7JbMRewCRU0OC-Is_RVGEKse6GCgO_SQhN3OtEGE/s320/Snap31.png&quot; height=&quot;199&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Database record locked after validation exception&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;This shows the database record is still locked. This is strange as this ADF BC application is set to its default of pessimistic locking. This means it should only lock the record while doing the DML and not keep the lock across requests. Further investigation points to the &lt;code&gt;commitInternal&lt;/code&gt; method in the &lt;code&gt;oracle.jbo.server.DBTransactionImpl&lt;/code&gt; class. I&#39;ve simplified its code in pseudo-code below:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;try {
  while (hasObjectsToPost()) {
    while (hasObjectsToValidate()) {
      JboException jboEx = null;
      try {
        validateAllObjects();
      } catch (JboException e) {
        jboEx = e;  // remember exception
        break; // abort hasObjectsToValidate loop
      }
    }
    if (jboEx != null) throw jboEx;
    setSavepoint();
    passivateStateForUndo();
    try {
      postChanges();
    } catch (RuntimeException r) {
      rollbackToSavepoint();
      throw r; // abort hasObjectsToPost
    }
  }
  try {
    doCommit();
  } catch (RuntimeException r) {
    rollbackToSavepoint();
    activateStateForUndo();
  }
} finally {
  clearSavePoint();
}&lt;/pre&gt;
&lt;br /&gt;
Let&#39;s ignore the loops for now. In line 6 all objects with pending changes are validated. In our example this is only the Department as that is the only entity the user changes from the user interface. This Department has no validation issues, so no exception is caught in lines 7-9 and no exception is re-thrown in line 12.&lt;br /&gt;
&lt;br /&gt;
So the process continues at line 13 to set a database savepoint and then continues posting the real changes (performing DML) in line 16. This is where the &lt;code&gt;prepareForDml&lt;/code&gt; and &lt;code&gt;doDML&lt;/code&gt; on all changes entities is invoked. This is where &lt;code&gt;DepartmentImpl&lt;/code&gt; is performing its SQL UPDATE statement. This is also where our &lt;code&gt;DepartmentImpl&lt;/code&gt; makes changes to an &lt;code&gt;EmployeeImpl&lt;/code&gt; entity. This does not throw any exception since &lt;code&gt;EmployeeImpl&lt;/code&gt; has an entity-level validation which is not validated directly when changing an attribute but is postponed until the entity is saved to the database. So we never get to the exception handling in line 18 that might have performed a rollback.&lt;br /&gt;
&lt;br /&gt;
We have now finished the first try of validation and posting changes but we have changed entities left. This means the loop at line 2 is going for another iteration. In line 6 we are again validating all entities with pending changes. In this second iteration, that is only the &lt;code&gt;EmployeeImpl&lt;/code&gt;. This time the entity-level validations occur and an exception is thrown. We end up in the exception handling in line 7-9 where we keep the validation exception and abort the validation loop. The validation exception is then re-thrown in line 12. This immediately jumps to line 29 where the database savepoint is cleared, but we never rollback to that savepoint as the exception handling around &lt;code&gt;postChanges&lt;/code&gt; and &lt;code&gt;doCommit&lt;/code&gt; would have done. This means the already changed row in the Departments table is still changed (and thus locked).&lt;br /&gt;
&lt;br /&gt;
I think this is a bug in ADF and a service request has been filed with Oracle Support. As long as this is not fixed, you can implement a workaround. Whenever you manipulate other objects from the &lt;code&gt;prepareForDml&lt;/code&gt; or &lt;code&gt;doDML&lt;/code&gt; be sure to force validation yourself. This would not only abort the DML on the entity itself but it also means the &lt;code&gt;postChanges&lt;/code&gt; in line 16 of our &lt;code&gt;DBTransactionImpl::commitInternal&lt;/code&gt; pseudo-code would throw an exception and a rollback of any changes posted by other entities occurs. To implement this you only need a simple change to the code in DepartmentImpl (see line 10):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java;highlight:10&quot;&gt;@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);
    }
    firstEmployee.validate();
    super.doDML(i, transactionEvent);
}
&lt;/pre&gt;
&lt;br /&gt;
As always you can &lt;a href=&quot;https://java.net/projects/redheap/downloads/directory/jdev11117/PendingChanges&quot; target=&quot;_blank&quot;&gt;download the full sample&lt;/a&gt; application or &lt;a href=&quot;https://java.net/projects/redheap/sources/svn/show/jdev11117/PendingChanges&quot; target=&quot;_blank&quot;&gt;browse the subversion repository&lt;/a&gt; to look at the source code.</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/1797148706218544244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/11/locking-issues-by-doDML-prepareForDml.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/1797148706218544244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/1797148706218544244'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/11/locking-issues-by-doDML-prepareForDml.html' title='Overriding Entity doDML or prepareForDml Causes Locking Issues'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF672okU5wcK-ZO1R_GxINORxnVvGZECsvUOn5RlvwjRqXh91tdXEk0F_9XirWHbHB14-RnyrlQ_-ZtzjJDjUw-uHjZBOVncnHVuH3ueQ_5OCek6pkbNvIAwoos76fGcvwZfoTySzhJqk/s72-c/Snap29.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-2063715016961968326</id><published>2013-11-08T22:53:00.002+01:00</published><updated>2013-11-08T23:03:28.313+01:00</updated><title type='text'>Vodafone Content Tampering Making Sites Very Slow On Wi-Fi</title><content type='html'>I&#39;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.&lt;br /&gt;
&lt;br /&gt;
I noticed my browser is trying to download &lt;tt&gt;http://1.2.3.50/jsi/flash.php?file=gordon.js&amp;amp;max-age=3600&lt;/tt&gt; which never succeeds on Wi-Fi. A &lt;a href=&quot;http://networktools.nl/whois/1.2.3.50&quot; target=&quot;_blank&quot;&gt;whois search&lt;/a&gt; seems to indicate the entire 1.2.3.0/24 address block is invalid and shouldn&#39;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.&lt;br /&gt;
&lt;br /&gt;
But why is my client requesting this bizarre URL? It is actually part of &lt;tt&gt;http://googleads.g.doubleclick.net/pagead/blank.html&lt;/tt&gt; 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:&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;html&amp;gt;&amp;lt;script src=&quot;http://1.2.3.50/jsi/flash.php?file=gordon.js&amp;amp;max-age=3600&quot; language=&quot;javascript&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;body style=&quot;background-color: transparent&quot;&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
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 &lt;tt&gt;blank.html&lt;/tt&gt; from my Wi-Fi connection I get a trully blank page:&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;html&amp;gt;&amp;lt;body style=&quot;background-color: transparent&quot;&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
You don&#39;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 &lt;tt&gt;blank.html&lt;/tt&gt; telling your browser it is okay to cache the page for 24 hours. So your device will simply use the cached (tampered) version of &lt;tt&gt;blank.html&lt;/tt&gt; it retrieved through Vodafone&#39;s network. But now you are on Wi-Fi and your device can&#39;t load the file from 1.2.3.50 and the site is dead slow.&lt;br /&gt;
&lt;br /&gt;
Okay, this is bad, but let&#39;s hope the problem clears after 24 hours. After all your browser is only allowed to cache the tampered &lt;tt&gt;blank.html&lt;/tt&gt; page for 24 hours. Unfortunately the problem doesn&#39;t disappear after 24 hours. This is caused by Google sending an &lt;a href=&quot;http://en.wikipedia.org/wiki/HTTP_ETag&quot; target=&quot;_blank&quot;&gt;ETag&lt;/a&gt; response header with &lt;tt&gt;blank.html&lt;/tt&gt; 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&#39;t so your browser is caching this altered version under Google&#39;s original ETag. So even when the cache expires after 24 hours and your browser is asking for a fresh copy of &lt;tt&gt;blank.html&lt;/tt&gt; it will include the ETag with this request. Whether you are on Wi-Fi or 3G, Google will always respond that &lt;tt&gt;blank.html&lt;/tt&gt; hasn&#39;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 &lt;tt&gt;blank.html&lt;/tt&gt; until you clear your browser cache.&lt;br /&gt;
&lt;br /&gt;
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&#39;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! &lt;a href=&quot;http://forum.vodafone.nl/t5/Vodafone-Red-Abonnementen/How-to-disable-Bytemobile-transparent-proxying/td-p/29426&quot; target=&quot;_blank&quot;&gt;Vodafone support is acknowledging&lt;/a&gt; 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.&lt;br /&gt;
&lt;br /&gt;
Hopefully this rant can help others understand what is going on when they see this failed downloads from the &lt;tt&gt;1.2.3.50&lt;/tt&gt; or &lt;tt&gt;1.2.3.4&lt;/tt&gt; IP address.</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/2063715016961968326/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/11/vodafone-content-tampering-making-sites.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/2063715016961968326'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/2063715016961968326'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/11/vodafone-content-tampering-making-sites.html' title='Vodafone Content Tampering Making Sites Very Slow On Wi-Fi'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-8251495206767025109</id><published>2013-11-07T16:31:00.000+01:00</published><updated>2013-11-07T16:31:28.841+01:00</updated><title type='text'>Decimal Comma with Numeric Keypad as ADF Client Behavior</title><content type='html'>According to &lt;a href=&quot;http://en.wikipedia.org/wiki/Decimal_mark#Hindu.E2.80.93Arabic_numeral_system&quot; target=&quot;_blank&quot;&gt;wikipedia&lt;/a&gt; 24% of the world&#39;s population uses a comma as decimal separator, including The Netherlands where I live. This means entering numeric information with the numeric keypad on the keyboard can be challenging. You can only use it to type a decimal point (.) while we need a decimal comma (,). To make things ADF simply ignores the decimal point in our locale. When a user enters &lt;tt&gt;1.23&lt;/tt&gt; it is converted to &lt;tt&gt;123&lt;/tt&gt; and wrong information is entered into the system.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiokbBF2PZEYpSWwqbsTcvEJdvi4YjkL5fWdOYF-QbtyIHyzZl9dWpvj9DpxrkYs07Z43nnptIfzXwSyXzORBbu0hK2ofXxEE7y0ADotOmdvSXrMCwY5K9-1PvjlAJOz8VUn3KNUdcMd6g/s1600/333px-Numpad.svg.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiokbBF2PZEYpSWwqbsTcvEJdvi4YjkL5fWdOYF-QbtyIHyzZl9dWpvj9DpxrkYs07Z43nnptIfzXwSyXzORBbu0hK2ofXxEE7y0ADotOmdvSXrMCwY5K9-1PvjlAJOz8VUn3KNUdcMd6g/s200/333px-Numpad.svg.png&quot; width=&quot;162&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Numeric keypad decimal point&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
We came up with a solution based on a custom ADF Behavior tag. I&#39;ve recently posted how to create your own ADF (client side) behavior. The first post was a &lt;a href=&quot;http://www.redheap.com/2013/02/custom-adf-faces-client-behavior-jsp-tag.html&quot; target=&quot;_blank&quot;&gt;simple version without properties&lt;/a&gt;, while the second post &lt;a href=&quot;http://www.redheap.com/2013/03/adf-faces-client-behavior-with-parameters.html&quot; target=&quot;_blank&quot;&gt;expanded this example with properties&lt;/a&gt;. Now it is time for the sequel showing how you can handle key presses in an input item and replace any decimal point keystroke with a decimal separator (possibly comma) keystroke. The user can simply use the decimal point on the numeric keypad and when using a European locale it will simply type a comma.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Read these previous posts to learn how to create custom ADF behavior tags. This post will only focus on the parts that are specific for this solution: the BehaviorTag class, the javascript implementation and a sample page. Let&#39;s start with the&amp;nbsp;DecimalCommaBehaviorTag class. This represents the redheap:decimalCommaBehavior JSP tag and constructs the client side snippet of javascript:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.redheap.decimalcomma;

import java.text.DecimalFormatSymbols;
import java.util.Locale;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.myfaces.trinidad.context.RequestContext;

/**
 * Implementation of redheap:decimalCommaBehavior JSP tag.
 * @author Wilfred van der Deijl, www.redheap.com
 */
public class DecimalCommaBehaviorTag 
  extends oracle.adfinternal.view.faces.taglib.behaviors.BehaviorTag {

    /**
     * Returns the snippet of javascript code that needs to be executed
     * on the client to construct the client behavior object.
     * @param component JSF component this behavior tag is attached to
     * @return snippet of javascript that instantiates an object
     */
    @Override
    protected String getBehavior(UIComponent component) {
      return &quot;new RedHeapDecimalCommaBehavior(&#39;&quot; +
          StringEscapeUtils.escapeJavaScript(getDecimalSeparator()) + 
          &quot;&#39;)&quot;;
    }

    /**
     * Returns the name of a JavaScript library feature that provides
     * the client-side implementation of this listener/behavior.
     * This feature will be added to the set of features required for
     * this page/request, ensuring that corresponding JavaScript
     * library partition is available.
     * @return a javascript library feature name
     */
    @Override
    protected String getFeatureDependency() {
      return &quot;RedHeapDecimalCommaBehavior&quot;;
    }

    protected String getDecimalSeparator() {
      DecimalFormatSymbols dfs = new DecimalFormatSymbols(getLocale());
      return String.valueOf(dfs.getDecimalSeparator());
    }

    protected Locale getLocale() {
      Locale locale =
          RequestContext.getCurrentInstance().getFormattingLocale();
      return locale != null ? locale :
            FacesContext.getCurrentInstance().getViewRoot().getLocale();
    }

}
&lt;/pre&gt;
Line 25-27 returns the javascript script to instantiate the client-side implementation object. This gets the decimal separator character as argument to the constructor. This decimal separator character is determined in the &lt;tt&gt;getDecimalSeparator()&lt;/tt&gt; methods which uses &lt;tt&gt;getLocale()&lt;/tt&gt; to determine the locale for the current request/page.&lt;br /&gt;
&lt;br /&gt;
Next is the most important part of this solution: the client-side javascript implementation:&lt;br /&gt;
&lt;pre class=&quot;brush:javascript&quot;&gt;/**
 * javascript constructor that invokes the Init function
 */
function RedHeapDecimalCommaBehavior(decimalSeparator) {
  this.Init(decimalSeparator);
}

// register as a subclass of AdfClientBehavior
AdfObject.createSubclass(RedHeapDecimalCommaBehavior,
                         AdfClientBehavior);

/**
 * initialize this behavior
 * @override
 */
RedHeapDecimalCommaBehavior.prototype.Init = function(decimalSeparator) {
  // be sure to invoke initialization by superclass
  RedHeapDecimalCommaBehavior.superclass.Init.call(this);
  this._decimalSeparator = decimalSeparator;
}

/**
 * as part of the AdfClientBehavior behavior contract, initialize is
 * called when the component is created to give the behavior a chance
 * to register event listeners.
 * @param {AdfUIComponent} component
 */
RedHeapDecimalCommaBehavior.prototype.initialize =
function(component) {
  AdfAssert.assertPrototype(component, AdfUIComponent);
  component.addEventListener(AdfUIInputEvent.KEY_PRESS_EVENT_TYPE,
                             this._handleKeyPress, this);
}

/**
 * handle invoking a command component with this behavior.
 * @param {AdfUIInputEvent} event
 */
RedHeapDecimalCommaBehavior.prototype._handleKeyPress =
function(event) {
  AdfAssert.assertPrototype(event, AdfUIInputEvent);
  if (event.getKeyCode() == &#39;.&#39;.charCodeAt(0)) {
    // this looks like the &#39;.&#39; is pressed and we might want to replace it
    if (event.getNativeEvent &amp;amp;&amp;amp; event.getNativeEvent().charCode==0) {
      // Firefox wrongfully raises this keyPress event on the DELETE
      // button as well. Look at the native event to distinguish and
      // abort. Also see &quot;Special keys&quot; at 
      // http://www.quirksmode.org/dom/events/keys.html
      return;
    }
    if (&#39;.&#39; == this._decimalSeparator) {
      // no need to do anything if decimal-separator of current locale
      // uses decimal dot
      return;
    }
    // replace keystroke of dot on numeric keypad with decimal separator
    // of current locale
    var source = event.getSource();
    AdfLogger.LOGGER.logMessage(AdfLogger.FINE, 
                                &quot;replacing . keystroke with &quot; +
                                this._decimalSeparator + &quot; for &quot; +
                                source.getClientId());
    var input = AdfDhtmlEditableValuePeer.GetContentNode(source);
    if (input) {
      event.cancel(); // cancel normal event to suppress &#39;.&#39; character
      if (typeof(input.selectionStart) !== &#39;undefined&#39;) {
        // gecko, webkit or IE9+ support selection properties
        AdfLogger.LOGGER.logMessage(AdfLogger.FINE, 
          &quot;using selection properties for modern browsers&quot;);
        // determine future caret position before we start messing with
        // selection and content
        var newPos = input.selectionStart + this._decimalSeparator.length;
        // inject decimal separator while keeping text before and after
        // selection (thus removing selection)
        var oldtext = input.value;
        input.value = oldtext.substring(0, input.selectionStart) + 
                      this._decimalSeparator +
                      oldtext.substring(input.selectionEnd, 
                                        oldtext.length);
        // set caret position after the decimal separator
        input.selectionStart = newPos;
        input.selectionEnd = newPos;
      } else if (document.selection &amp;amp;&amp;amp; document.selection.createRange) {
        AdfLogger.LOGGER.logMessage(AdfLogger.FINE, 
          &quot;using document.selection for older IE versions&quot;);
        var sel = document.selection.createRange();
        // replace current selection with decimal-sep or insert at caret
        sel.text = this._decimalSeparator; 
        // collapse selection so caret is after decimal-separator
        sel.setEndPoint(&quot;StartToEnd&quot;, sel); 
        sel.select();
      }
    }
  }
}&lt;/pre&gt;
&lt;br /&gt;
The code should be well documented so reading a couple of times should make clear what it does. Basically we are canceling the key-press event for &quot;.&quot; and injecting the decimal separator in the value of the current item at the cursor position or replacing any existing selected text within this item.&lt;br /&gt;
&lt;br /&gt;
Finally the sample page:&lt;br /&gt;
&lt;pre class=&quot;brush:xml;highlight:[14,15,16]&quot;&gt;&amp;lt;?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39;?&amp;gt;
&amp;lt;jsp:root xmlns:jsp=&quot;http://java.sun.com/JSP/Page&quot; version=&quot;2.1&quot;
          xmlns:f=&quot;http://java.sun.com/jsf/core&quot;
          xmlns:h=&quot;http://java.sun.com/jsf/html&quot;
          xmlns:af=&quot;http://xmlns.oracle.com/adf/faces/rich&quot;
          xmlns:redheap=&quot;http://redheap.com/taglib&quot;&amp;gt;
  &amp;lt;jsp:directive.page contentType=&quot;text/html;charset=UTF-8&quot;/&amp;gt;
  &amp;lt;f:view&amp;gt;
    &amp;lt;af:document id=&quot;d1&quot;&amp;gt;
      &amp;lt;af:form id=&quot;f1&quot;&amp;gt;
        &amp;lt;af:panelFormLayout&amp;gt;
          &amp;lt;af:inputText label=&quot;Browser locale (should use comma decimal separator)&quot;
                        value=&quot;#{facesContext.viewRoot.locale}&quot; readOnly=&quot;true&quot;/&amp;gt;
          &amp;lt;af:inputText label=&quot;Try typing point on decimal keyboard&quot; id=&quot;it1&quot;&amp;gt;
            &amp;lt;redheap:decimalCommaBehvior/&amp;gt;
          &amp;lt;/af:inputText&amp;gt;
        &amp;lt;/af:panelFormLayout&amp;gt;
      &amp;lt;/af:form&amp;gt;
    &amp;lt;/af:document&amp;gt;
  &amp;lt;/f:view&amp;gt;
&amp;lt;/jsp:root&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
As always you can &lt;a href=&quot;https://java.net/projects/redheap/downloads/directory/jdev11117/DecimalCommaBehavior&quot; target=&quot;_blank&quot;&gt;download the full sample&lt;/a&gt; application or &lt;a href=&quot;https://java.net/projects/redheap/sources/svn/show/jdev11117/DecimalCommaBehavior&quot; target=&quot;_blank&quot;&gt;browse the subversion repository&lt;/a&gt; to look at the source code.</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/8251495206767025109/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/11/decimal-comma-with-numeric-keypad-as.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/8251495206767025109'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/8251495206767025109'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/11/decimal-comma-with-numeric-keypad-as.html' title='Decimal Comma with Numeric Keypad as ADF Client Behavior'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiokbBF2PZEYpSWwqbsTcvEJdvi4YjkL5fWdOYF-QbtyIHyzZl9dWpvj9DpxrkYs07Z43nnptIfzXwSyXzORBbu0hK2ofXxEE7y0ADotOmdvSXrMCwY5K9-1PvjlAJOz8VUn3KNUdcMd6g/s72-c/333px-Numpad.svg.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-7373957373558109656</id><published>2013-10-14T10:34:00.000+02:00</published><updated>2014-01-02T14:35:02.945+01:00</updated><title type='text'>Check for postChanges without commit or rollback in ADF BC</title><content type='html'>It is not uncommon for an ADF application to invoke &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/apirefs.1111/e10653/oracle/jbo/server/DBTransactionImpl.html#postChanges()&quot; target=&quot;_blank&quot;&gt;DBTransactionImpl::postChanges()&lt;/a&gt; to perform database DML without invoking commit (or rollback). This is typically done in environments where we also want to invoke PL/SQL logic in the database that already needs to see these pending changes.&lt;br /&gt;
&lt;br /&gt;
The developer should make sure a commit or rollback is executed in the same JSF request. If this is not done, the database session has pending changes and as we know there is no guarantee a subsequent request by the same user will get the same Application Module and JDBC Connection. It is considered bad practice to have these pending changes survive a single request and today we had a situation where this accidentally happened with all sorts of nasty side-effects. One of the things that happens is that the pending changes also could mean long-lived database locks. We added some code to our ADF BC base classes to detect this and throw an exception so we at least know what is going on and to alert a developer he/she is implementing this bad practice.&lt;br /&gt;
&lt;br /&gt;
First thing we need is to configure our application module to use a custom database transaction class. This is described in the &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/web.1111/b31974/bcadvgen.htm#CHEJCIHJ&quot; target=&quot;_blank&quot;&gt;ADF documentation&lt;/a&gt;. First we need to create our own &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/apirefs.1111/e10653/oracle/jbo/server/DatabaseTransactionFactory.html&quot; target=&quot;_blank&quot;&gt;DatabaseTransactionFactory&lt;/a&gt; so we can use our own subclass of &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/apirefs.1111/e10653/oracle/jbo/server/DBTransactionImpl2.html&quot; target=&quot;_blank&quot;&gt;DBTransactionImpl2&lt;/a&gt;:
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;import oracle.jbo.server.DBTransactionImpl2;
import oracle.jbo.server.DatabaseTransactionFactory;

public class MyDatabaseTransactionFactory
  extends DatabaseTransactionFactory
{
  @Override
  public DBTransactionImpl2 create()
  {
    return new MyDBTransactionImpl2();
  }
}&lt;/pre&gt;
&lt;br /&gt;
Then we need to make sure this factory class is used instead of the default by setting the TransactionFactory property of the ADF Application Module configuration to the full class name of our own transaction factory:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB0Bmjmi2IQWVghrMZBNijPa6Da7s2gEvuFnouBgidzxtIp6MqwBBNzegtuvkh5fk38K5kAmaVVf3zjl-1B3a4OBkWf_my8j2zEjfkoLWskBvJLltB-YiyTVY4LX9t169g_KpLpa6qRho/s1600/bc_adv_configeditor.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB0Bmjmi2IQWVghrMZBNijPa6Da7s2gEvuFnouBgidzxtIp6MqwBBNzegtuvkh5fk38K5kAmaVVf3zjl-1B3a4OBkWf_my8j2zEjfkoLWskBvJLltB-YiyTVY4LX9t169g_KpLpa6qRho/s320/bc_adv_configeditor.png&quot; width=&quot;295&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Set TransactionFactory property of AM Configuration&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Next, we can create our own subclass of DBTransactionImpl2 that keeps track of pending postChanges. It sets a flag when postChanges is executed and clears this flag when performing a commit or rollback. We are going to check this flag later on when releasing an Application Module at the end of a request:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;import oracle.jbo.server.DBTransactionImpl2;
import oracle.jbo.server.TransactionEvent;

public class MyDBTransactionImpl2
  extends DBTransactionImpl2
{
  private boolean postedChanges = false;

  @Override
  protected void postChanges(TransactionEvent te)
  {
    super.postChanges(te);
    setPostedChanges(true);
  }

  @Override
  protected void doCommit()
  {
    setPostedChanges(false);
    super.doCommit();
  }

  @Override
  protected void doRollback()
  {
    setPostedChanges(false);
    super.doRollback();
  }

  private void setPostedChanges(boolean postedChanges)
  {
    this.postedChanges = postedChanges;
  }

  public boolean isPostedChanges()
  {
    return postedChanges;
  }

}&lt;/pre&gt;
&lt;br /&gt;
Final step is to check for pending postChanges at the end of each request. We can do this from our Application Module. This would typically be code you add to your own ADF BC base classes:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;import oracle.jbo.ApplicationPoolSvcMsgContext;
import oracle.jbo.JboException;
import oracle.jbo.server.ApplicationModuleImpl;
import oracle.jbo.server.DBTransaction;

public class MyBaseAppModuleImpl
  extends ApplicationModuleImpl
{
  /**
   * This is invoked by the Application Module Pool whenever an 
   * application module is being used, released, removed or recycled
   * from the pool.
   */
  @Override
  public ApplicationPoolSvcMsgContext doPoolMessage(ApplicationPoolSvcMsgContext ctx)
  {
    if (ctx.getMessageType() == 
        ApplicationPoolSvcMsgContext.MESSAGE_TYPE_RELEASING)
    {
      DBTransaction txn = getDBTransaction();
      if (txn instanceof MyDBTransactionImpl2 &amp;amp;&amp;amp; 
          ((MyDBTransactionImpl2) txn).isPostedChanges())
      {
        // throwing exception will mark AM as dead and close tainted
        // DBTransaction and JDBC connection
        throw new JboException(&quot;Application Module released to the pool with pending posted changes&quot;);
      }
    }
    return super.doPoolMessage(ctx);
  }

}
&lt;/pre&gt;
&lt;br /&gt;
&lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/apirefs.1111/e10653/oracle/jbo/ApplicationModule.html#doPoolMessage(oracle.jbo.ApplicationPoolSvcMsgContext)&quot; target=&quot;_blank&quot;&gt;ApplicationModule::doPoolMessage&lt;/a&gt; is invoked whenever the pool uses, releases, removes or recycles an application module instance. This can be seen by inspecting &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/apirefs.1111/e10653/oracle/jbo/ApplicationPoolSvcMsgContext.html#getMessageType()&quot; target=&quot;_blank&quot;&gt;ApplicationPoolSvcMsgContext::getMessageType()&lt;/a&gt;&amp;nbsp;and comparing to any of the MESSAGE_* constants in ApplicationPoolSvcMsgContext. We check for uncommitted postChanges whenever the application module instance is released to the pool (aka at the end of each request). If these exist we simply throw a JboException. This will not be visible to the end-user as the JSF response has already been completed by then. It will show up in the log for administrators and developers. Because we are throwing an exception during pool management the AM instance will be destroyed together with its JDBC connection. This is actually good as we don&#39;t want the AM instance with pending changes, and potential database locks, to linger around.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update 2 jan:&lt;/b&gt; &lt;i&gt;We changed the code to no longer throw an exception thus destroying the applicationModuke, but only log a warning message. &lt;a href=&quot;http://www.redheap.com/2013/11/locking-issues-by-doDML-prepareForDml.html&quot;&gt;Due to an ADF bug&lt;/a&gt; we have quite a few AM instances with posted changes at the end of their request. When they get destroyed all ViewObjects loose their where clause and other (or all) records are fetched on the next page request. So until that bug is we fixed we reverted to only logging a warning.&lt;/i&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/7373957373558109656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/10/check-for-postchanges-without-commit-or.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/7373957373558109656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/7373957373558109656'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/10/check-for-postchanges-without-commit-or.html' title='Check for postChanges without commit or rollback in ADF BC'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB0Bmjmi2IQWVghrMZBNijPa6Da7s2gEvuFnouBgidzxtIp6MqwBBNzegtuvkh5fk38K5kAmaVVf3zjl-1B3a4OBkWf_my8j2zEjfkoLWskBvJLltB-YiyTVY4LX9t169g_KpLpa6qRho/s72-c/bc_adv_configeditor.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-9209193354018561089</id><published>2013-08-22T10:35:00.000+02:00</published><updated>2013-08-22T10:35:10.445+02:00</updated><title type='text'>JDeveloper installer very small on Mac OS X</title><content type='html'>I have previously installed JDeveloper 11 on my MacBook Pro running Mac OS X Mountain Lion (10.8). Basically you download the generic installer from Oracle and run:&lt;br /&gt;
&lt;pre class=&quot;brush:plain&quot;&gt;java -jar&amp;nbsp;jdevstudio11124install.jar&lt;/pre&gt;
&lt;br /&gt;
Today I tried it again and the installer does start but with a very small screen only showing the exit button:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKrBYaMmk_gvt9X3SQHx6VSzaBxMlQ6lQgC3pKs0y8qbq5X-0JFwIAiQUc0tii-MtD4niYSS47Bhh2cRae-w6XITklNbJVVx_jm1NRerrDAdt7CPaWcCmMkWJPAZXEtR0Tl3MdVVLKQXs/s1600/Screen+Shot+2013-08-21+at+20.48.29+.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKrBYaMmk_gvt9X3SQHx6VSzaBxMlQ6lQgC3pKs0y8qbq5X-0JFwIAiQUc0tii-MtD4niYSS47Bhh2cRae-w6XITklNbJVVx_jm1NRerrDAdt7CPaWcCmMkWJPAZXEtR0Tl3MdVVLKQXs/s1600/Screen+Shot+2013-08-21+at+20.48.29+.png&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;JDeveloper Installer with only Exit button&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
As it turns out this is caused by a recent install of JDeveloper 12c on the same machine. That had forced me to install JDK version 7 which is now the default java runtime environment on my machine. Apparently the JDeveloper version 11 installer doesn&#39;t like java version 7, at least on Mac OS X.&lt;br /&gt;
&lt;br /&gt;
The solution is rather simple. Run the following commands in a terminal window to start the JDeveloper 11 installer:&lt;br /&gt;
&lt;pre class=&quot;brush:plain;highlight:[1,3,7]&quot;&gt;wMac:~ wilfred$ /usr/libexec/java_home -v 1.6
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
wMac:~ wilfred$ /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java -version
java version &quot;1.6.0_51&quot;
Java(TM) SE Runtime Environment (build 1.6.0_51-b11-457-11M4509)
Java HotSpot(TM) 64-Bit Server VM (build 20.51-b01-457, mixed mode)
wMac:~ wilfred$ /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java -jar jdevstudio11124install.jar 
Extracting scripts to /var/folders/vl/qsk0dkgn39b2_4sdngwvcf840000gn/T/
Executing MacOS-specific pre-installation scripts
You may be prompted to enter your Mac OS X password in order to create required directories and symbolic links
Extracting 0%....................................................................................................100%
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Line 1 runs java_home to get you the full path to the java version 6 home directory. Line 3 uses this path and adds &quot;/bin/java -version&quot; to run java from that directory to check its exact version. Make sure it is in fact a 1.6.0_xx version. Then finally line 7 uses java from that directory to run the installer. This time it just starts fine:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF5gNAJGEtQv3wpCWnPukswM2_Pq99EvAaqOzl8NYN8hL7gbzB1zA2o3I2Lx4xnoGgn34yWkvanOVZ7eNH4z79K0W9Y9LzAFfU88jaEczvqa_ds0cIIpfrF0qsLEgGOfJh2crDxmMRnFA/s1600/Screen+Shot+2013-08-22+at+10.33.37+.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;242&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF5gNAJGEtQv3wpCWnPukswM2_Pq99EvAaqOzl8NYN8hL7gbzB1zA2o3I2Lx4xnoGgn34yWkvanOVZ7eNH4z79K0W9Y9LzAFfU88jaEczvqa_ds0cIIpfrF0qsLEgGOfJh2crDxmMRnFA/s320/Screen+Shot+2013-08-22+at+10.33.37+.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;JDeveloper 11 installer runs fine with JDK 6&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/9209193354018561089/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/08/jdeveloper-installer-very-small-on-mac.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/9209193354018561089'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/9209193354018561089'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/08/jdeveloper-installer-very-small-on-mac.html' title='JDeveloper installer very small on Mac OS X'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKrBYaMmk_gvt9X3SQHx6VSzaBxMlQ6lQgC3pKs0y8qbq5X-0JFwIAiQUc0tii-MtD4niYSS47Bhh2cRae-w6XITklNbJVVx_jm1NRerrDAdt7CPaWcCmMkWJPAZXEtR0Tl3MdVVLKQXs/s72-c/Screen+Shot+2013-08-21+at+20.48.29+.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-6730424645851506483</id><published>2013-06-17T17:37:00.000+02:00</published><updated>2014-06-18T09:04:05.746+02:00</updated><title type='text'>Credential Store Framework</title><content type='html'>Sometimes you have the need for credentials (username/password) in your ADF, or other Fusion Middleware, application. I&#39;ve seen numerous solutions with property files, web.xml context parameters, deployment plans, etc. Most of these run into problems with SysOps or anyone else worried with security. You don&#39;t want these credentials scattered around in plain text files and you don&#39;t want developers to know the passwords for each environment. This is better left to configuration by a sys-admin after deployment.&lt;br /&gt;
&lt;br /&gt;
Not everybody seems to know Oracle Fusion Middleware, more specifically Oracle Platform Security Services (OPSS), provides a great solution with the &lt;b&gt;Credentials Store Framework&lt;/b&gt;. This is a set of APIs that applications can use to create, read, update, and manage credentials securely.&lt;br /&gt;
&lt;br /&gt;
A credential store is a repository of security data (credentials) that can hold user name and password combinations, tickets, or public key certificates.&amp;nbsp;A credential store can be file-, LDAP- (Oracle Internet Directory), or DB-(Oracle RDBMS)based. A file-based credential store, also referred to as wallet-based and represented by the file &lt;tt&gt;cwallet.sso&lt;/tt&gt;, is the out-of-the-box credential store.&lt;br /&gt;
&lt;br /&gt;
The Credentials Store Framework also limits which application (or components thereof) are allowed to retrieve or modify credentials. This allows for a very secure setup where only trusted libraries that go through extensive auditing are allowed to retrieve credentials.&lt;br /&gt;
&lt;br /&gt;
This post describes the basic steps to get started with the Credentials Store Framework, but more information can be found in the official documentation (Fusion Middleware Application Security Guide):&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/core.1111/e10043/devcsf.htm#BABEADIA&quot; target=&quot;_blank&quot;&gt;Chapter 24 -&amp;nbsp;Developing with the Credential Store Framework&lt;/a&gt; on how to use the CSF API from your Java application whether it is deployed to a WebLogic server or running as a standalone Java application.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/core.1111/e10043/cfgauthr.htm#CHDHGAJG&quot; target=&quot;_blank&quot;&gt;Chapter&amp;nbsp;8 -&amp;nbsp;Configuring the OPSS Security Store&lt;/a&gt; especially if you want to change the default file-based credential store to a database- or LDAP-store which Oracle advices for production usage.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/core.1111/e10043/csfadmin.htm#CACDJHGE&quot; target=&quot;_blank&quot;&gt;Chapter 10 -&amp;nbsp;Managing the Credential Store&lt;/a&gt; on enabling encryption for LDAP- and file-based stores which are clear-text by default and on how to create, update, and delete credentials through Fusion Middleware Control or WLST scripts&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
The Credential Store is a collection of maps, each with its own name. Each of these maps can store and retrieve credentials or certificates based on a unique key. It&#39;s common practice to name each map specific for an application so we can grant as little privileges as possible to this map (and keys).&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Step 1 - Add Credentials to a Credential Store&lt;/h2&gt;
&lt;div&gt;
The first step in this example is to add credentials to a credential store. You can use WLST or Fusion Middleware Control. When using the embedded weblogic server that comes with JDeveloper you will have to use WLST scripting as it doesn&#39;t have Fusion Middleware Control. I&#39;ll explain both approaches below.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Creating credentials with WLST&lt;/h3&gt;
&lt;div&gt;
Ensure the (integrated) WebLogic server is running and start WLST with &lt;tt&gt;ORACLE_HOME/oracle_common/common/bin/wlst&lt;/tt&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Connect to the WebLogic Server from WLST with the correct credentials and t3 URL, for example:&lt;/div&gt;
&lt;div&gt;
&lt;tt&gt;connect(&#39;weblogic&#39;, &#39;weblogic1&#39;, &#39;t3://localhost:7101&#39;)&lt;/tt&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
create a credential with &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/core.1111/e10043/csfadmin.htm#CACHACFJ&quot; target=&quot;_blank&quot;&gt;createCred&lt;/a&gt;:&lt;/div&gt;
&lt;div&gt;
&lt;tt&gt;createCred(map=&quot;mapName&quot;, key=&quot;keyName&quot;, user=&quot;secretUsername&quot;, password=&quot;secretPassword&quot;, desc=&quot;Description&quot;)&lt;/tt&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I advice to keep the name of the map equal to the &lt;tt&gt;adfAppUID&lt;/tt&gt; as defined in the &lt;tt&gt;META-INF/adf-config.xml&lt;/tt&gt; file of your application:&lt;br /&gt;
&lt;pre class=&quot;brush:xml;highlight:[6,7]&quot;&gt;&amp;lt;adf-config xmlns=&quot;http://xmlns.oracle.com/adf/config&quot;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; xmlns:config=&quot;http://xmlns.oracle.com/bc4j/configuration&quot;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; xmlns:adf=&quot;http://xmlns.oracle.com/adf/config/properties&quot;&amp;gt;
&amp;nbsp; ....
&amp;nbsp; &amp;lt;adf:adf-properties-child xmlns=&quot;http://xmlns.oracle.com/adf/config/properties&quot;&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;adf-property name=&quot;adfAppUID&quot;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; value=&quot;ApplicationName.com.redheap.sample&quot;/&amp;gt;
&amp;nbsp; &amp;lt;/adf:adf-properties-child&amp;gt;
&amp;lt;/adf-config&amp;gt;&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
An example would be:&lt;/div&gt;
&lt;div&gt;
&lt;tt&gt;createCred(map=&quot;ApplicationName.com.redheap.sample&quot;, key=&quot;workflowRMI&quot;, user=&quot;weblogic&quot;, password=&quot;forYourEyesOnly&quot;, desc=&quot;Account for RMI calls to Human Workflow Service&quot;)&lt;/tt&gt;&lt;br /&gt;
&lt;br /&gt;
You can use &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/core.1111/e10043/csfadmin.htm#CACCGBJE&quot; target=&quot;_blank&quot;&gt;updateCred&lt;/a&gt;&amp;nbsp;and &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/core.1111/e10043/csfadmin.htm#CACGIGDB&quot; target=&quot;_blank&quot;&gt;deleteCred&lt;/a&gt; for other operations.&lt;br /&gt;
&lt;br /&gt;
As a final step you can check if your newly create credential is available in the store:&lt;br /&gt;
&lt;tt&gt;listCred(map=&quot;mapName&quot;, key=&quot;keyName&quot;)&lt;/tt&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Creating credentials with Fusion Middleware Control&lt;/h3&gt;
&lt;div&gt;
An alternative to WLST scripting is to use the Fusion Middleware Control web interface. The steps are similar although you have to create the map itself first and then create a key within that map. Keep in mind that the credential store is for the entire weblogic domain and not for a specific server or cluster. The credential store can be managed through &lt;tt&gt;Domain &amp;gt; Security &amp;gt; Credentials&lt;/tt&gt;. For more details see&amp;nbsp;&lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/core.1111/e10043/csfadmin.htm#CACDGFEH&quot; target=&quot;_blank&quot;&gt;Managing Credentials with Fusion Middleware Control&lt;/a&gt;&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzZtEbFCqkLh-ncgG_FJssjjskfxjqOMU6jpcSrhpYBh8V6wAStTcHzgvmy8s_MO3CXjMlpypo2lOr_I8Kl3y5verwGB4kU4FYXiEEWatX8otVHAxkEw8xx684-Zfb0zgYBCsMn3zqgiI/s1600/emsyscreds.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzZtEbFCqkLh-ncgG_FJssjjskfxjqOMU6jpcSrhpYBh8V6wAStTcHzgvmy8s_MO3CXjMlpypo2lOr_I8Kl3y5verwGB4kU4FYXiEEWatX8otVHAxkEw8xx684-Zfb0zgYBCsMn3zqgiI/s400/emsyscreds.gif&quot; height=&quot;200&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Editing credentials using Fusion Middleware Control&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h2&gt;
Step 2 -&amp;nbsp;Authorising&amp;nbsp;an a application to retrieve credentials&lt;/h2&gt;
&lt;div&gt;
Credentials from the Credential Store cannot simply be retrieved by any application. A system administrator first has to grant privileges through system policies.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Integrated WebLogic Server in JDeveloper&lt;/h3&gt;
&lt;div&gt;
When developing with a local JDeveloper and WebLogic installation it is easiest to use relaxed security and to give all applications read-access to all credentials. This removes the need to grant permissions to each (test) application over and over again. For a very relaxed policy shutdown your Integrated WebLogic server and edit its &lt;tt&gt;system-jazn-data.xml&lt;/tt&gt; file. On windows this is typically located at &lt;tt&gt;%APPDATA%\JDeveloper\system11.x.x.x.x.x.x\DefaultDomain\config\fmwconfig\system-jazn-data.xml&lt;/tt&gt;. Add the following grant as a child of &lt;tt&gt;jazn-data/system-policy/jazn-policy&lt;/tt&gt; (be very sure to check the location as there is also a admin-policy under system-policy and that&#39;s &lt;b&gt;not&lt;/b&gt; the one you want):&lt;/div&gt;
&lt;pre class=&quot;brush:xml;highlight:[4,10]&quot;&gt;&amp;lt;grant&amp;gt;
  &amp;lt;grantee&amp;gt;
    &amp;lt;codesource&amp;gt;
      &amp;lt;url&amp;gt;file:/-&amp;lt;/url&amp;gt;
    &amp;lt;/codesource&amp;gt;
  &amp;lt;/grantee&amp;gt;
  &amp;lt;permissions&amp;gt;
    &amp;lt;permission&amp;gt;
      &amp;lt;class&amp;gt;oracle.security.jps.service.credstore.CredentialAccessPermission&amp;lt;/class&amp;gt;
      &amp;lt;name&amp;gt;context=SYSTEM,mapName=*,keyName=*&amp;lt;/name&amp;gt;
      &amp;lt;actions&amp;gt;read&amp;lt;/actions&amp;gt;
    &amp;lt;/permission&amp;gt;
  &amp;lt;/permissions&amp;gt;
&amp;lt;/grant&amp;gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
Managed WebLogic Server&lt;/h3&gt;
&lt;div&gt;
With a properly managed server you don&#39;t want to grant every application access to all credentials. Here you want to limit the grants as much as possible. You can add a grant directly in the config file or through Fusion Middleware Control.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Manually granting directly in jazn-data.xml&lt;/h4&gt;
&lt;div&gt;
You can add the necessary grant as a child of &lt;tt&gt;jazn-data/system-policy/jazn-policy&lt;/tt&gt; in &lt;tt&gt;DOMAIN_HOME/config/fmwconfig/jazn-data.xml&lt;/tt&gt; (again be very sure to check the location as there is also a admin-policy under system-policy and that&#39;s &lt;b&gt;not&lt;/b&gt; the one you want):&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;brush:xml;highlight:[4,10]&quot;&gt;&amp;lt;grant&amp;gt;
 &amp;lt;grantee&amp;gt;
  &amp;lt;codesource&amp;gt;
   &amp;lt;url&amp;gt;file:${oracle.deployed.app.dir}/ApplicationName${oracle.deployed.app.ext}&amp;lt;/url&amp;gt;
  &amp;lt;/codesource&amp;gt;
 &amp;lt;/grantee&amp;gt;
 &amp;lt;permissions&amp;gt;
  &amp;lt;permission&amp;gt;
   &amp;lt;class&amp;gt;oracle.security.jps.service.credstore.CredentialAccessPermission&amp;lt;/class&amp;gt;
   &amp;lt;name&amp;gt;context=SYSTEM,mapName=CredentialMapName,keyName=CredentialKeyName&amp;lt;/name&amp;gt;
   &amp;lt;actions&amp;gt;read&amp;lt;/actions&amp;gt;
  &amp;lt;/permission&amp;gt;
 &amp;lt;/permissions&amp;gt;
&amp;lt;/grant&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Replace &lt;tt&gt;ApplicationName&lt;/tt&gt; with the name of the deployed application. This is the same as the directory that is created in &lt;tt&gt;.../user_projects/domains/DomainName/servers/ServerName/tmp/_WL_USER&lt;/tt&gt;. Also replace &lt;tt&gt;CredentialMapName&lt;/tt&gt; and &lt;tt&gt;CredentialKeyName&lt;/tt&gt; with the names of the credential map and key to identify which credential can be read by the application.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Adding using Fusion Middleware Control&lt;/h4&gt;
&lt;div&gt;
A less error prone method is to use Fusion Middleware Control to add the grant. Navigate to &lt;tt&gt;Domain &amp;gt; Security &amp;gt; System Policies&lt;/tt&gt; in Fusion Middleware Control. Then press &lt;tt&gt;Create...&lt;/tt&gt; and use the following properties:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Grant to: &lt;tt&gt;codebase&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Codebase: &lt;tt&gt;file:${oracle.deployed.app.dir}/ApplicationName${oracle.deployed.app.ext}&lt;/tt&gt; (replace &lt;tt&gt;ApplicationName&lt;/tt&gt; with the name of the application, see manual granting for more details)&lt;/li&gt;
&lt;li&gt;Press the &lt;tt&gt;Add&lt;/tt&gt; button for permissions&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Check &lt;tt&gt;Select here to enter details for a new permission&lt;/tt&gt;. This is a tiny checkbox at the bottom of the popup to start creating a new permission.&lt;/li&gt;
&lt;li&gt;Permission Class: &lt;tt&gt;oracle.security.jps.service.credstore.CredentialAccessPermission&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Resource Name: &lt;tt&gt;context=SYSTEM,mapName=CredentialMapName,keyName=CredentialKeyName&lt;/tt&gt; (replace &lt;tt&gt;CredentialMapName&lt;/tt&gt; and &lt;tt&gt;CredentialKeyName&lt;/tt&gt; with the name of the map and key used when creating the credentials)&lt;/li&gt;
&lt;li&gt;Permission Actions (if available): read&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;b&gt;WARNING:&lt;/b&gt; After making these changes all Managed Servers &lt;b&gt;AND&lt;/b&gt; the Admin Server have to restarted to activate these changes.&lt;br /&gt;
&lt;br /&gt;
TIP: More information on the syntax of the codebase URL, and the use of wildcards, can be found in &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/core.1111/e10043/apsysjaz.htm#BABBIJFE&quot; target=&quot;_blank&quot;&gt;Appendix B -&amp;nbsp;File-Based Identity and Policy Store Reference&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h2&gt;
Step 3 - Retrieving Credentials in Application&lt;/h2&gt;
&lt;div&gt;
In Java we need to use the &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/security/AccessController.html&quot; target=&quot;_blank&quot;&gt;AccessController&lt;/a&gt; to execute the code to retrieve credentials from the store with elevated privileges. The code itself will use &lt;a href=&quot;http://docs.oracle.com/cd/E28280_01/apirefs.1111/e14650/oracle/security/jps/service/credstore/CredentialStore.html&quot;&gt;oracle.security.jps.service.credstore.CredentialStore&lt;/a&gt; to retrieve the credentials. See the simplified example below for a factory class that can create a Connection object with credentials form the credential store. Most connection objects won&#39;t expose the credentials used for that connection to their user. This means you can package this factory class in a separate library and only allow that library access to the credential store. That way you only have to audit/review this single library and not all other application code for places where the credentials might leak out.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;brush:java;highlight:[64,65,66]&quot;&gt;import java.security.AccessController;

import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;

import oracle.adf.share.ADFContext;

import oracle.security.jps.JpsException;
import oracle.security.jps.service.JpsServiceLocator;
import oracle.security.jps.service.ServiceLocator;
import oracle.security.jps.service.credstore.PasswordCredential;
import oracle.security.jps.service.credstore.CredentialStore;

public final class ConnectionFactory {

    /**
     * Retrieves credentials from the Credential Store where the current
     * application UID is used as the name of the credential map.
     * This method must be called through AccessController.doPrivileged
     * @param key name of the key in the credential map to retrieve
     * @return PasswordCredential if exists, null otherwise
     * @throws JpsException
     */
    private PasswordCredential _readCredentials(String key) throws JpsException {
        ServiceLocator locator = JpsServiceLocator.getServiceLocator();
        CredentialStore store = locator.lookup(CredentialStore.class);
        // always use application UID as name for the credential map to ensure
        // each application uses its own map and credentials aren&#39;t shared
        String map = ADFContext.getCurrent().getADFApplicationUID();
        return (PasswordCredential)store.getCredential(map, key);
    }

    /**
     * Retrieves credentials from the Credential Store by invoking
     * {@link #_readCredentials} as a privileged action.
     * @param key name of the key in the credential map to retrieve
     * @return PasswordCredential if exists, null otherwise
     * @throws JpsException
     */
    private PasswordCredential readCredentials(final String key) {
        PasswordCredential credentials;
        PrivilegedExceptionAction&amp;lt;PasswordCredential&amp;gt; action =
            new PrivilegedExceptionAction&amp;lt;PasswordCredential&amp;gt;() {
            public PasswordCredential run() throws JpsException {
                return _readCredentials(key);
            }
        };
        try {
            credentials = AccessController.doPrivileged(action);
        } catch (PrivilegedActionException e) {
            throw new RuntimeException(e);
        }
        return credentials;
    }

    /**
     * Factory method to create connection with credentials from Credential
     * Store.
     * @return new connection
     */
    public Connection createWorkflowConnection() {
        // use fixed key so the user of this factory is not allowed to
        // create a connection based on any arbitrary credential
        PasswordCredential cred = readCredentials(&quot;workflowRMI&quot;);
        // TODO: create and return connection with information from
        //       cred.getName() and cred.getPassword();
        return null;
    }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;div&gt;
If the &lt;tt&gt;oracle.security.jps.*&lt;/tt&gt; classes are not available to your project be sure to include the &lt;tt&gt;JRF Client&lt;/tt&gt; or &lt;tt&gt;JRF Runtime&lt;/tt&gt; library in your project settings.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;TIP:&lt;/b&gt; If you miss the necessary system policy grant your application won&#39;t be allowed to retrieve the credentials. The raised &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/security/PrivilegedActionException.html&quot;&gt;AccessControlException&lt;/a&gt; is normally not shown to the end user or logged to your console. Add &lt;tt&gt;-Djps.auth.debug=true&lt;/tt&gt; to your application startup parameters (and restart weblogic) to display these errors in your console. If you also want to see which codebase is used to retrieve the credentials, you can also add &lt;tt&gt;-Djps.auth.debug.verbose=true&lt;/tt&gt; but be warned that this also logs every successful access so your console will quickly fill up. This way we found out that the codebase for one of our sample applications running on Windows was &lt;tt&gt;file:/C:/Users/xxx/AppData/Roaming/JDeveloper/system11.x.x.x.x.xx.x/DefaultDomain/servers/DefaultServer/tmp/_WL_user/ApplicationName/36wlms/war/WEB-INF/lib/credentials-1.0.jar&lt;/tt&gt;. Together with the previous information on wildcards in the codebase URL this can help you fine tune the system policies.&lt;br /&gt;
&lt;br /&gt;
Keep in mind that declarative ADF Connections (the ones you can edit in the JDeveloper IDE) &lt;a href=&quot;http://biemond.blogspot.nl/2012/02/changing-your-adf-connections-in.html&quot;&gt;can be changed through Fusion Middleware Control or WLST&lt;/a&gt; as described by &lt;a href=&quot;https://plus.google.com/113701679510703185415&quot;&gt;Edwin Biemond&lt;/a&gt;&amp;nbsp;from AMIS. The Oracle Credential Store Framework is more for situations where you are programmatically creating connections to backend systems or other situations where you need credentials. If you have any remaining questions just post them below and I&#39;ll try to answer them.&amp;nbsp;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/6730424645851506483/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/06/secure-credentials-in-adf-application.html#comment-form' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/6730424645851506483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/6730424645851506483'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/06/secure-credentials-in-adf-application.html' title='Credential Store Framework'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzZtEbFCqkLh-ncgG_FJssjjskfxjqOMU6jpcSrhpYBh8V6wAStTcHzgvmy8s_MO3CXjMlpypo2lOr_I8Kl3y5verwGB4kU4FYXiEEWatX8otVHAxkEw8xx684-Zfb0zgYBCsMn3zqgiI/s72-c/emsyscreds.gif" height="72" width="72"/><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-1629751778550998446</id><published>2013-05-08T10:47:00.000+02:00</published><updated>2014-12-19T10:16:21.187+01:00</updated><title type='text'>Customizing JDeveloper Preferences</title><content type='html'>I like to tweak some of the preferences in the Tools menu of JDeveloper. I thought I would document them here for my own reference and in case anyone else is interested. I&#39;ll try to list all the settings I typically change from their default. These are ordered and grouped by their panels in the preferences dialog so you should be able to locate them easily.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Environment&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Line Terminator to &quot;Line Feed (Unix/Mac)&quot; especially if you are in a mixed environment with windows and linux/mac developers as it prevents a lot of problems if everyone creates the files in the same way.&lt;/li&gt;
&lt;li&gt;Encoding to &quot;UTF-8&quot;. I have no idea why the default is platform dependent (MacRoman or some obscure windows code page). I like all developers in the team to use the same encoding. This is also used as encoding in XML files you create. Changing it afterwards can be a lot more work as existing files might need recoding&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Environment &amp;gt; Log&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Maximum Log Lines to something like 50000. The default of 3000 can be too small if you crank up the logging levels in a development session.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;ADF Business Components&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Look at all these settings carefully (and read below). Lots of these settings are used when creating new ADF BC objects so be careful to set these up before you start developing as it can safe a lot of rework later&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;ADF Business Components &amp;gt; Base Classes&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;You can set the default base classes for any ADF BC object you will create in JDeveloper. It is wise to create company wide extension classes for these and configure JDeveloper to use your company extended classes instead of the JDeveloper base ones. You could even &amp;nbsp;create a layer of extension classes for your project (extending from company classes) and setup the per-project settings to use these application level extension classes&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;ADF Business Components &amp;gt; Packages&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;A lot of developers like to group their ADF BC objects per type in separate sub packages. For instance put all view objects in a subpackage .views or .queries. In stead of remembering to set these sub packages each time you are creating ADF BC objects simply set the defaults here.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;ADF Business Components &amp;gt; View Objects&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;You could set the default fetching tuning parameters for new view objects here. But in reality they need consideration for each view object you create. One trick we used in the past is to set a ridiculous default value here and then check for that ridiculous value in your extended ADF ViewObject classes. If the developer left the ridiculous initial value simply throw an exception telling the developer to set reasonable values.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Audit&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;The JDeveloper Audit framework is&amp;nbsp;under-appreciated. I would advise to tweak the Code Assist Rules that you see while developing. Go over the rules that are disabled by default and see if you want to enable them. My guess is you can enable most of them, especially to warn developers about missing or incorrect javadoc. Also be sure to check the &quot;Audit During Compile&quot; with perhaps a slightly less restrictive set to prevent your developers from violating certain rules. The next step would be to monitor these quality issues from your continuous build server&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Code Editor&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;I like to enable &quot;Reformat Code Block When Pasting&quot;. That is mainly since I tend to keep most of my code auto-formatted so reformatting when pasting someone else&#39;s code seems like a good idea.&lt;/li&gt;
&lt;li&gt;One other thing I like to enable is &quot;Show Total Number of Lines in the Status Bar&quot; just to remind to keep the files small and simple.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Code Editor &amp;gt; Code Templates&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;You can add your own code templates here. We&#39;ve added a bunch to easily use ADFLogger in your Java source code. More on that in a future post.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Code Editor &amp;gt; Display&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Enable Text Anti-Aliasing because it just looks better :-)&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Code Editor &amp;gt; Line Gutter&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Enable &quot;Show Line Numbers&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Code Editor &amp;gt; Save Actions&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;These are actions that JDeveloper should perform on each file you save. I typically add &quot;Organize Imports&quot;, &quot;Trim Trailing Whitespace&quot; and &quot;Clear All Highlighting&quot;. I&#39;ve tried using Reformat as well which is great for Java sources which should always be formatted by a tool for consistency. But JDeveloper will then also reformat all XML files including JSF pages. In those files it is much more common to perform manual formatting and I don&#39;t like the always-auto-format of these save actions.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Compiler&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Enable &quot;Clean Project Before Project Rebuild&quot;. If you are rebuilding your entire project I see no reason why you don&#39;t want to start with a clean project first. Otherwise you might run the risk of keeping compiled&amp;nbsp;artifacts&amp;nbsp;for source objects you have already removed.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;CSS Editor&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;If you do anything with ADF skinning be sure to set the CSS level to Level 3 (and on JDev 11gR1) enable the ADF Faces Extensions checkbox&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Debugger&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Check &quot;Show Action Buttons&quot; to get the debugger buttons (step, continue, etc) also in the log window of JDeveloper.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Debugger &amp;gt; Beakpoints&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Set the scope for new breakpoints to Global. Especially if you are building on a large system with multiple workspaces. With the default setting your debugger will not stop if you set a breakpoint in one workspace and run the application from another workspace. My workflow is to keep the number of breakpoints limited and I frequently clean them. I would like the confidence that a breakpoint is always used.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Debugger &amp;gt; Data&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;I personally don&#39;t like the new Tree View in the 11gR2/12c debugger where you drill down into objects and have to traverse back up. I prefer the old-style Table View so I change the default view here.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Debugger &amp;gt; Smart Data&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;I like to increase the &quot;Number of Lines to Analyze&quot; to something like 5 to show a bit more information in this debugger panel.&lt;/li&gt;
&lt;li&gt;I personally don&#39;t like the new&amp;nbsp;Tree View in the 11gR2/12c debugger&amp;nbsp;where you drill down into objects and have to traverse back up. I prefer the old-style Table View so I change the default view here.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Debugger &amp;gt; Watches&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;I personally don&#39;t like the new&amp;nbsp;Tree View in the 11gR2/12c debugger&amp;nbsp;where you drill down into objects and have to traverse back up. I prefer the old-style Table View so I change the default view here.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;File Types&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;I like to change the default editor panel used for certain files. I don&#39;t like JSF files to open in design WYSIWYG mode as&amp;nbsp;initializing&amp;nbsp;that editor can be slow. I prefer these to start in source view and I can always switch to the design tab if needed. You can set this in the Default Editors tab of these preferences. I like to set this to &quot;Source&quot; for &quot;ADF Fragment File&quot;, &quot;HTML Source&quot;, &quot;HTML Template&quot;, &quot;JSFF Label&quot;, &quot;JSP Segment&quot;, &quot;JSP Source&quot;, &quot;XHTML/Facelets Source&quot; and &quot;XHTML Source&quot; (not all of these exist in every version of JDeveloper)&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;News (JDev 12c only)&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Add&amp;nbsp;http://feeds.feedburner.com/RedHeap to the list of News Feeds to get Red Heap posts in JDeveloper :-)&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Run &amp;gt; WebLogic&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;On 11gR2 only enable FastSwap deployment to you can make more changes to a deployed application without doing a full redeploy. Unfortunately this feature is not available on 11gR1.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Web Browser and Proxy&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;If your&amp;nbsp;organisation&amp;nbsp;uses a web proxy be sure to fill in these details so JDeveloper can access the internet for things like checking for updates. You can also set you default web browser here in case that is different from the default browser of your operating system. I like to use Google Chrome as my development browser and sometimes you cannot change the default web browser of your operating system due to administrator restrictions.&lt;/li&gt;
&lt;li&gt;When using Chrome as your browser be sure to start it in incognito mode. This ensures you start with a clean browser each time you start your application. In JDeveloper 11g you can simply add &lt;code&gt;--incognito&lt;/code&gt; to the command line of chrome while JDeveloper 12c allows you to specify &lt;code&gt;--incognito ${URL}&lt;/code&gt; as command line parameters.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
Some other things I would like to chance with a default JDeveloper installation:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Select Tools &amp;gt; External Tools and let JDeveloper create the default external tools when running on Microsoft Windows. This gives you a convenient right-click on all your objects to start a windows explorer in that specific source directory. Something I frequently use, for example to get access to TortoiseSVN on that file. On Mac I like to setup this to run a terminal from the selected directory.&lt;/li&gt;
&lt;li&gt;Change the memory options in JDEV_HOME/ide/bin/ide.conf. On a 32-bit JVM I like to set both -Xmx and -Xms to 1200M. On a 64-bit JVM you could even go a bit higher, like 1500M or 2000M.&lt;/li&gt;
&lt;li&gt;When running with non-English regional settings on your operating system, edit JDEV_USER_HOME/system11.x.x.x.x.x.x/DefaultDomain/bin/setDomainEnv.cmd, search for the lines where EXTRA_JAVA_PROPERTIES are set and add a line&lt;br /&gt;&lt;tt&gt;set EXTRA_JAVA_PROPERTIES=-Duser.language=en -Duser.country=US %EXTRA_JAVA_PROPERTIES%&lt;/tt&gt;&lt;br /&gt;This enforces WebLogic to use en_US as locale so error messages in the JDeveloper Log window are English and not the language from your operating system. This makes googling for these error messages much easier ;-)&lt;/li&gt;
&lt;li&gt;While you&#39;re already editing&amp;nbsp;JDEV_USER_HOME/system11.x.x.x.x.x.x/DefaultDomain/bin/setDomainEnv.cmd you might just as well increase the memory for WebLogic. Search for the lines where&amp;nbsp;XMS_SUN_64BIT,&amp;nbsp;XMS_SUN_32BIT,&amp;nbsp;XMX_SUN_64BIT and&amp;nbsp;XMX_SUN_32BIT are set. My advice is to change all four to 1024 but you might want to tweak this for your situation.&lt;br /&gt;When using JDeveloper 12.1.2 you can set memory arguments in&amp;nbsp;JDEV_USER_HOME/system12.1.2.x.x.x.x/DefaultDomain/bin/setStartupEnv.cmd in the section for&amp;nbsp;AdminServerStartupGroup.&lt;/li&gt;
&lt;/ul&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/1629751778550998446/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/05/customizing-jdeveloper-preferences.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/1629751778550998446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/1629751778550998446'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/05/customizing-jdeveloper-preferences.html' title='Customizing JDeveloper Preferences'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-6329189471693933011</id><published>2013-03-15T22:35:00.002+01:00</published><updated>2013-03-16T12:47:22.116+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ClientBehavior"/><category scheme="http://www.blogger.com/atom/ns#" term="EL expression"/><category scheme="http://www.blogger.com/atom/ns#" term="iterator"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="JSP"/><category scheme="http://www.blogger.com/atom/ns#" term="JSPX"/><category scheme="http://www.blogger.com/atom/ns#" term="org.apache.commons.lang"/><category scheme="http://www.blogger.com/atom/ns#" term="ShowAlertBehavior"/><category scheme="http://www.blogger.com/atom/ns#" term="StringEscapeUtils"/><category scheme="http://www.blogger.com/atom/ns#" term="TLD"/><category scheme="http://www.blogger.com/atom/ns#" term="ValueExpression"/><title type='text'>ADF Faces Client Behavior with Attributes</title><content type='html'>Last month I posted about the basics of &lt;a href=&quot;http://www.redheap.com/2013/02/custom-adf-faces-client-behavior-jsp-tag.html&quot; target=&quot;_blank&quot;&gt;creating custom ClientBehavior in ADF Faces&lt;/a&gt;. Now it is time to take the next step and enhance that example with ways to set attributes on the JSP client-behavior tag, pass these on to the client-side javascript implementation and use them in the actual functionality.&lt;br /&gt;
&lt;br /&gt;
We&#39;ll take the (simplified) example of the &lt;a href=&quot;http://www.redheap.com/2013/02/custom-adf-faces-client-behavior-jsp-tag.html&quot; target=&quot;_blank&quot;&gt;previous post&lt;/a&gt; that could show a javascript alert and adopt it to get the message from an attribute which we specify in the JSF page using the component. We&#39;ll also make sure we can use an EL expression to specify this values (this is the tricky part). We will be able to do something like:&lt;br /&gt;
&lt;pre class=&quot;brush:java;highlight:3&quot;&gt;&amp;lt;af:forEach begin=&quot;1&quot; end=&quot;5&quot; varStatus=&quot;vs&quot;&amp;gt;
&amp;nbsp; &amp;lt;af:commandButton text=&quot;click to see message #{vs.index}&quot; id=&quot;cb&quot;&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;redheap:showAlertBehavior message=&quot;This is message #{vs.index}&quot;/&amp;gt;
&amp;nbsp; &amp;lt;/af:commandButton&amp;gt;
&amp;lt;/af:forEach&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;
Add Attribute to Tag Library Descriptor&lt;/h2&gt;
The Tag Library Descriptor (TLD) describes the JSP tag itself and which attributes it supports. This is used when parsing the JSP/JSF files and also by JDeveloper for things like code completion and the property palette. Add the attribute to the tag in the TLD file:&lt;br /&gt;
&lt;pre class=&quot;brush:xml;highlight:[6,7,8,9,10,11]&quot;&gt;&amp;lt;tag&amp;gt;
&amp;nbsp; &amp;lt;description&amp;gt;Describe your component here&amp;lt;/description&amp;gt;
&amp;nbsp; &amp;lt;name&amp;gt;showAlertBehavior&amp;lt;/name&amp;gt;
&amp;nbsp; &amp;lt;tag-class&amp;gt;com.redheap.clientbehavior.ShowAlertBehaviorTag&amp;lt;/tag-class&amp;gt;
&amp;nbsp; &amp;lt;body-content&amp;gt;JSP&amp;lt;/body-content&amp;gt;
&amp;nbsp; &amp;lt;attribute&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;description&amp;gt;Message text to show in JS alert&amp;lt;/description&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;name&amp;gt;message&amp;lt;/name&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;required&amp;gt;true&amp;lt;/required&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;deferred-value/&amp;gt;
&amp;nbsp; &amp;lt;/attribute&amp;gt;
&amp;lt;/tag&amp;gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;h2&gt;
Adding Attributes to the JSP Tag Handler&lt;/h2&gt;
Next part is the Java code. The JSP Tag Handler class is the Java implementation of the tag in the JSPX/JSF document. This is the &lt;tt&gt;com.redheap.clientbehavior.ShowAlertBehaviorTag&lt;/tt&gt; class from our previous example. First thing to add is a member variable and a setter method:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;&amp;nbsp; &amp;nbsp; private ValueExpression message;

&amp;nbsp; &amp;nbsp; /**
&amp;nbsp; &amp;nbsp; &amp;nbsp;* Set the message to show in the javascript alert.
&amp;nbsp; &amp;nbsp; &amp;nbsp;* @param message message to show in the alert
&amp;nbsp; &amp;nbsp; &amp;nbsp;*/
&amp;nbsp; &amp;nbsp; public void setMessage(ValueExpression message) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; this.message = message;
&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
Evaluating EL Expression Attributes&lt;/h3&gt;
In our previous sample without attributes we implemented the &lt;tt&gt;getBehavior&lt;/tt&gt; method to return a snippet of javascript to instantiate a javascript object that implements the client side behavior. This time we have to pass &amp;nbsp;the message text to this client side implementation. Complicating factor is that this message text can come from an EL expression and we have to evaluate this EL expression with the correct context. Let&#39;s take the example from the introduction:&lt;br /&gt;
&lt;pre class=&quot;brush:java;highlight:3&quot;&gt;&amp;lt;af:forEach begin=&quot;1&quot; end=&quot;5&quot; varStatus=&quot;vs&quot;&amp;gt;
&amp;nbsp; &amp;lt;af:commandButton text=&quot;click to see message #{vs.index}&quot; id=&quot;cb&quot;&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;redheap:showAlertBehavior message=&quot;This is message #{vs.index}&quot;/&amp;gt;
&amp;nbsp; &amp;lt;/af:commandButton&amp;gt;
&amp;lt;/af:forEach&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
In this example we not only have to evaluate the &lt;tt&gt;#{vs.index}&lt;/tt&gt; expression but we also have to do it at the correct time. We cannot do it when the tag handler is created but we have to wait until it is actually asked to create the javascript snippet as we need the correct ELContext to resolve &lt;tt&gt;vs.index&lt;/tt&gt; to the actual row we are currently handling. The trick is to implement &lt;tt&gt;getBehaviorExpression&lt;/tt&gt; instead of &lt;tt&gt;getBehavior&lt;/tt&gt;. This can return a &lt;tt&gt;javax.el.ValueExpression&lt;/tt&gt; that is evaluated at the correct time with the correct ELContext:&lt;br /&gt;
&lt;pre class=&quot;brush:java;highlight:[3,8]&quot;&gt;    @Override
    protected String getBehavior(UIComponent component) {
        return null;
    }

    @Override
    protected ValueExpression getBehaviorExpression(UIComponent component) {
        return new ShowAlertValueExpression(message);
    }&lt;/pre&gt;
&lt;br /&gt;
Now the burden is on&amp;nbsp;com.redheap.clientbehavior.ShowAlertValueExpression which is a subclass of&amp;nbsp;javax.el.ValueExpression. It has to return the value of this expression in the getValue method that gets the correct ELContext from the framework:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class ShowAlertValueExpression extends ValueExpressionImpl {

    private ValueExpression message;

    public ShowAlertValueExpression(ValueExpression message) {
        this.message = message;
    }

    @Override
    public Object getValue(ELContext context) {
        Object msg = message.getValue(context);
        String strmsg = msg == null ? &quot;&quot; : msg.toString();
        return &quot;new RedHeapShowAlertBehavior(&#39;&quot; +
            StringEscapeUtils.escapeJavaScript(strmsg) + &quot;&#39;)&quot;;
    }
}
&lt;/pre&gt;
&lt;br /&gt;
It returns a snippet of javascript that instantiates a client side javascript object that handles the implementation. The actual message to show is supplied to the constructor as an argument, for example:&lt;br /&gt;
&lt;pre class=&quot;brush:javascript&quot;&gt;new RedHeapShowAlertBehavior(&#39;this is the message&#39;);&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Pro Tip:&lt;/b&gt; we use the StringEscapeUtils from org.apache.commons.lang. This is already available on your weblogic server (albeit an older 2.1.0 version). All you have to do is to add the &quot;WebLogic 10.3 Remote-Client&quot; library to your project to extend your compile time classpath. Runtime is already taken care of since it is on your weblogic server.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Client Side JavaScript&lt;/h2&gt;
Final step is to change the client side javascript object to receive and use the message attribute. We add an argument to the constructor and pass it to the initialization method which stores it in a member variable of the javascript object:&lt;br /&gt;
&lt;pre class=&quot;brush:javascript;highlight:[1,2,5,7]&quot;&gt;function RedHeapShowAlertBehavior(msg) {
  this.Init(msg);
}

RedHeapShowAlertBehavior.prototype.Init = function(msg) {
  RedHeapShowAlertBehavior.superclass.Init.call(this);
  this._msg = msg;
}&lt;/pre&gt;
&lt;br /&gt;
And of course the actual event handling code must use this value in showing the alert:&lt;br /&gt;
&lt;pre class=&quot;brush:javascript;highlight:4&quot;&gt;RedHeapShowAlertBehavior.prototype._handleAction =
function(event) {
  AdfAssert.assertPrototype(event, AdfUIInputEvent);
  alert(this._msg);
  event.cancel(); // cancel normal event processing
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;h2&gt;
Usage in JSPX&lt;/h2&gt;
&lt;div&gt;
Finally here is the JSPX source of a simple test page that uses the client behavior to show a message:&lt;/div&gt;
&lt;pre class=&quot;brush:xml;highlight:[2,5,9]&quot;&gt;&amp;lt;af:commandButton text=&quot;click for static message&quot; id=&quot;cb1&quot;&amp;gt;
  &amp;lt;redheap:showAlertBehavior message=&quot;static sample message&quot;/&amp;gt;
&amp;lt;/af:commandButton&amp;gt;
&amp;lt;af:commandButton text=&quot;click for dynamic message&quot; id=&quot;cb2&quot;&amp;gt;
  &amp;lt;redheap:showAlertBehavior message=&quot;#{&#39;dynamic sample message&#39;}&quot;/&amp;gt;
&amp;lt;/af:commandButton&amp;gt;
&amp;lt;af:forEach begin=&quot;1&quot; end=&quot;5&quot; varStatus=&quot;vs&quot;&amp;gt;
  &amp;lt;af:commandButton text=&quot;click foreach message #{vs.index}&quot; id=&quot;cb3&quot;&amp;gt;
    &amp;lt;redheap:showAlertBehavior message=&quot;message number #{vs.index}&quot;/&amp;gt;
  &amp;lt;/af:commandButton&amp;gt;
&amp;lt;/af:forEach&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
And here is the final result:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8dHGlOFNPP4vKyq3XjbiWIgkeMLaqjimv6EGFAm-EdMIegAGjBuPxthCF1AfYLbLcuE8NRZKWsCr5gnQOO7WhqkFnj2saO9dFJWid4wUJwmOoE0Zhtzs9IOg3CJdTfrcVfaNxxlOxos8/s1600/ClientBehaviorParams.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;266&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8dHGlOFNPP4vKyq3XjbiWIgkeMLaqjimv6EGFAm-EdMIegAGjBuPxthCF1AfYLbLcuE8NRZKWsCr5gnQOO7WhqkFnj2saO9dFJWid4wUJwmOoE0Zhtzs9IOg3CJdTfrcVfaNxxlOxos8/s400/ClientBehaviorParams.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Custom Client Behavior triggering a javascript alert&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;h2&gt;
Sample Application&lt;/h2&gt;
&lt;div&gt;
As always you can &lt;a href=&quot;http://java.net/projects/redheap/downloads/directory/jdev11116/ClientBehaviorParams&quot; target=&quot;_blank&quot;&gt;download the full sample&lt;/a&gt; application or &lt;a href=&quot;http://java.net/projects/redheap/sources/svn/show/jdev11116/ClientBehaviorParams&quot; target=&quot;_blank&quot;&gt;browse the subversion repository&lt;/a&gt; to look at the source code. The subversion project started as a copy of the previous sample without parameters, so look at the revision history to so the details of what was changed to support attributes. And even though it is not the most fancy application you can also see it &lt;a href=&quot;https://java-trialaam2.java.us1.oraclecloudapps.com/ClientBehaviorParams/&quot; target=&quot;_blank&quot;&gt;live on Oracle Cloud&lt;/a&gt;.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/6329189471693933011/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/03/adf-faces-client-behavior-with-parameters.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/6329189471693933011'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/6329189471693933011'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/03/adf-faces-client-behavior-with-parameters.html' title='ADF Faces Client Behavior with Attributes'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8dHGlOFNPP4vKyq3XjbiWIgkeMLaqjimv6EGFAm-EdMIegAGjBuPxthCF1AfYLbLcuE8NRZKWsCr5gnQOO7WhqkFnj2saO9dFJWid4wUJwmOoE0Zhtzs9IOg3CJdTfrcVfaNxxlOxos8/s72-c/ClientBehaviorParams.png" height="72" width="72"/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-6732445401785500969</id><published>2013-02-02T12:03:00.000+01:00</published><updated>2013-11-07T09:44:22.324+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="adf-js-features.xml"/><category scheme="http://www.blogger.com/atom/ns#" term="ClientBehavior"/><category scheme="http://www.blogger.com/atom/ns#" term="ELContext"/><category scheme="http://www.blogger.com/atom/ns#" term="getBehavior"/><category scheme="http://www.blogger.com/atom/ns#" term="getBehaviorExpression"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="JSP"/><category scheme="http://www.blogger.com/atom/ns#" term="JSPX"/><category scheme="http://www.blogger.com/atom/ns#" term="ShowAlertBehavior"/><category scheme="http://www.blogger.com/atom/ns#" term="TLD"/><title type='text'>Custom ADF Faces Client Behavior 11.1.1 JSP tag</title><content type='html'>This post will show how to create your own ADF Faces client behavior JSP tags which makes them suitable for ADF version 11gR1, also known as version 11.1.1, and version 11gR2 (11.1.2) when not using Facelets.&lt;br /&gt;
&lt;br /&gt;
ADF Faces client behavior tags provide declarative solutions to common client operations that you would otherwise have to write using JavaScript, and register on components as client listeners.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Using tags makes behavior much more reusable. All a page developer has to do is drag-and-drop the client behavior tag on the appropriate component and not worry about writing JavaScript and attaching the appropriate client listeners. ADF Faces 11gR1 has a number of&amp;nbsp;&lt;a href=&quot;http://docs.oracle.com/cd/E23943_01/web.1111/b31973/af_event.htm#DAFIEDFF&quot; target=&quot;_blank&quot;&gt;client behavior tags&lt;/a&gt;&amp;nbsp;and a couple more were&amp;nbsp;&lt;a href=&quot;http://docs.oracle.com/cd/E35521_01/web.111230/e16181/af_event.htm#DAFIEDFF&quot; target=&quot;_blank&quot;&gt;added in version 11.1.2&lt;/a&gt;. Some examples are the &lt;a href=&quot;http://docs.oracle.com/cd/E23943_01/web.1111/b31973/af_dialog.htm#CHDGHBAE&quot; target=&quot;_blank&quot;&gt;af:showPopupBehavior&lt;/a&gt; to disclose a popup or the&amp;nbsp;&lt;a href=&quot;http://docs.oracle.com/cd/E23943_01/web.1111/b31973/af_event.htm#DAFEEGCI&quot; target=&quot;_blank&quot;&gt;af:scrollComponentIntoViewBehavior&lt;/a&gt; to scroll the page.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Wouldn&#39;t it be great if we can create our own client behavior tags for things that ADF doesn&#39;t support out of the box? There are a number of blogs out there that describe something like that, such as &lt;a href=&quot;https://blogs.oracle.com/groundside/entry/placeholder_watermarks_with_adf_11&quot; target=&quot;_blank&quot;&gt;placeholder watermarks&lt;/a&gt; by Duncan Mills and &lt;a href=&quot;http://donatas.nicequestion.com/2012/04/component-to-set-initial-focus-in-adf.html&quot; target=&quot;_blank&quot;&gt;setting the initial focus&lt;/a&gt; component&amp;nbsp;by Donatas Valys. Unfortunately those blogs describe how to do this with facelets which requires JDeveloper 11.1.2 We needed a solution for JDeveloper 11.1.1 and thus JSP tags.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update&lt;/b&gt;: A follow-up post is available that explains how to &lt;a href=&quot;http://www.redheap.com/2013/03/adf-faces-client-behavior-with-parameters.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;add support for attributes to your custom client behavior&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
There are a number of things we need to get this to work:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;JSP tag handler java class&lt;/li&gt;
&lt;li&gt;Tag library descriptor (.tld) file to register the JSP tag&lt;/li&gt;
&lt;li&gt;javascript file with the object that implements the client behavior&lt;/li&gt;
&lt;li&gt;adf-js-features.xml to register with the&amp;nbsp;ADF Faces JavaScript Library Partitioning framework to dynamically load the javascript when needed&lt;/li&gt;
&lt;li&gt;Deploy this as a library so we can consume it in any project we want&lt;/li&gt;
&lt;li&gt;Optionally enhance the tag and behavior to accept attributes to customize the behavior&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Read on as we discuss these step by step based on a overly simplified example of showing a javascript alert when clicking a command component like a button. Remember this blog post is about showing how to wire everything up not about an actual useful client behavior. I will cover some real world examples in future posts.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h2&gt;
JSP Tag Handler&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
First let&#39;s start with writing the JSP tag handler. This is a java class that represents the actual tag in a JSP document. It is responsible for receiving any attribute values from the JSP document and normally instantiates the JSF component. In this case we don&#39;t really have a server side JSF component as we are implementing client behavior. The easiest way to accomplish this is to extend the class that the out-of-the-box ADF Faces behaviors also use. The class to extend is&amp;nbsp;oracle.adfinternal.view.faces.taglib.behaviors.BehaviorTag. Unfortunately this class is in the oracle.adfinternal package which means it is not part of the public javadoc and it might change in a future version as it is not an official public API. The easiest way to understand what is going on is to get a copy of the ADF source code from Oracle support and have a look for yourself.&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.redheap.clientbehavior;

import javax.faces.component.UIComponent;

/**
 * Implementation of showAlertBehavior JSP tag.
 * @author Wilfred van der Deijl, www.redheap.com
 */
public class ShowAlertBehaviorTag
  extends oracle.adfinternal.view.faces.taglib.behaviors.BehaviorTag {

    /**
     * Returns the snippet of javascript code that needs to be executed
     * on the client to construct the client behavior object.
     * @param component JSF component this behavior tag is attached to
     * @return snippet of javascript that instantiates an object
     */
    protected String getBehavior(UIComponent component) {
        return &quot;new RedHeapShowAlertBehavior()&quot;;
    }

    /**
     * Returns the name of a JavaScript library feature that provides
     * the client-side implementation of this listener/behavior.
     * This feature will be added to the set of features required for
     * this page/request, ensuring that corresponding JavaScript
     * library partition is available.
     * @return a javascript library feature name
     */
    @Override
    protected String getFeatureDependency() {
        return &quot;RedHeapShowAlertBehavior&quot;;
    }

}
&lt;/pre&gt;
&lt;br /&gt;
The javascript class that is returned by getBehavior will be implemented in a javascript file below, while the&amp;nbsp;behavior returned by getFeatureDependency is registered in a xml file below.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Pro Tip:&lt;/b&gt; As an alternative to getBehavior(UIComponent) you can also implement getBehaviorExpression(UIComponent) that doesn&#39;t return javascript itself but a ValueExpression that should evaluate to the javascript snippet. The benefit of this approach is that the ValueExpression is executed with the correct ELContext. An example would be a behavior in an ADF Table or Iterator where you need access to the iterator or row variable.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h2&gt;
Tag Library Descriptor&lt;/h2&gt;
&lt;div&gt;
Next thing we need is a tag libary descriptor file so the JSP parser understands our &amp;lt;redheap:showAlertBehavior&amp;gt; tag and links it to the java class we just created. Use the New Gallery (from the File menu) to add a JSP Tag Library:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggxIQkSFPuWS-eIHNgucDO8myCMdsURcmES3sQkpCcEPWF6IajtH-RSqvN8aEq12YP_fj9e-fUlKJ6rzUqu5Tk6HCTMCjpNhQmEcxlZJz8FppDKoXuMMnfYZUnwIIKAVxYigXtdcerhiw/s1600/new-gallery-taglib.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;285&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggxIQkSFPuWS-eIHNgucDO8myCMdsURcmES3sQkpCcEPWF6IajtH-RSqvN8aEq12YP_fj9e-fUlKJ6rzUqu5Tk6HCTMCjpNhQmEcxlZJz8FppDKoXuMMnfYZUnwIIKAVxYigXtdcerhiw/s400/new-gallery-taglib.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;new gallery for JSP taglib&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Most of the time you will be making these behaviors with reuse in mind, so we opt to create a deployable tag library that is intended to be used in a library that we include with all of our projects. If you want behavior tags just for your one project you could also create a project based taglib:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH2jK2k2G-ZlkJa0KtuRLRMYCHiWNO4FOlpaLRtY2D8eXBb3C77RBEROI0xdOHqJ96Q67yoGtYhHRjO2ZpjXFJ_5ney1cguBmXG1vASo8v-bqJZOmvOK4AtFqSc3c4WpDQ6Q48tDmTds8/s1600/taglib-deployable.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;186&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH2jK2k2G-ZlkJa0KtuRLRMYCHiWNO4FOlpaLRtY2D8eXBb3C77RBEROI0xdOHqJ96Q67yoGtYhHRjO2ZpjXFJ_5ney1cguBmXG1vASo8v-bqJZOmvOK4AtFqSc3c4WpDQ6Q48tDmTds8/s320/taglib-deployable.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;deployable taglib&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Finally we have to supply the information for the taglib itself. Use sensible values in your situation and remember the taglib URI doesn&#39;t have to be a real URL it just has to be a globally unique identifier, much like a XML namespace:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigQQCevDMhN5dYfxv9rCU2XPE0UMze9cRlomsdS-Pr8ZQqtogE8G7Beq_R4C4tzVOU_i5Pl_ubRJ7HkX4BWoBlivzqdC7D5K77gAkoFA4tDY3RzAijCoJzdgaG80DjQaOW-A9RsmEutOg/s1600/taglib-wizard.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;300&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigQQCevDMhN5dYfxv9rCU2XPE0UMze9cRlomsdS-Pr8ZQqtogE8G7Beq_R4C4tzVOU_i5Pl_ubRJ7HkX4BWoBlivzqdC7D5K77gAkoFA4tDY3RzAijCoJzdgaG80DjQaOW-A9RsmEutOg/s400/taglib-wizard.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;supplying taglib information&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Finish the wizard with all default values and you should end up in the editor for your new taglib file which should be located in the src/META-INF directory. Add a single tag to the taglib xml file and point it to the tag class we just created:&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;?xml version = &#39;1.0&#39; encoding = &#39;UTF-8&#39;?&amp;gt;
&amp;lt;taglib xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
        xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd&quot;
        version=&quot;2.1&quot; xmlns=&quot;http://java.sun.com/xml/ns/javaee&quot;&amp;gt;
  &amp;lt;description&amp;gt;Describe the purpose of your library here&amp;lt;/description&amp;gt;
  &amp;lt;display-name&amp;gt;redheap&amp;lt;/display-name&amp;gt;
  &amp;lt;tlib-version&amp;gt;1.0&amp;lt;/tlib-version&amp;gt;
  &amp;lt;short-name&amp;gt;redheap&amp;lt;/short-name&amp;gt;
  &amp;lt;uri&amp;gt;http://redheap.com/taglib&amp;lt;/uri&amp;gt;
  &amp;lt;tag&amp;gt;
    &amp;lt;description&amp;gt;Describe your component here&amp;lt;/description&amp;gt;
    &amp;lt;name&amp;gt;showAlertBehavior&amp;lt;/name&amp;gt;
    &amp;lt;tag-class&amp;gt;com.redheap.clientbehavior.ShowAlertBehaviorTag&amp;lt;/tag-class&amp;gt;
    &amp;lt;body-content&amp;gt;JSP&amp;lt;/body-content&amp;gt;
  &amp;lt;/tag&amp;gt;
&amp;lt;/taglib&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
One thing to note is that the short-name of the taglib itself will be used as the prefix of the tags in JSP documents (the redheap in &amp;lt;redheap:showAlertBehavior&amp;gt;) while the display-name will show up in the dropdown of component families in the component palette in JDeveloper.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h2&gt;
Javascript Client Behavior Implementation&lt;/h2&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div&gt;
The tag handler java class returned a snippet of javascript that instantiates a RedHeapShowAlertBehavior. Next thing we need to do is to actually implement this class in a javascript file.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpRCvpMpNcVOYwx6TVN2_9DxWJw4kCPQ2iS82-4sJ9W3LRxvQkBvOHgWg-fvi5fMy-FpZOis9qH_PLafLbUScm7x6OHJeawoerf543O1UIEXh4Rs4X_LAG6NwLZBOduEI6ya4lRPXf-GU/s1600/new-gallery-javascript.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;285&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpRCvpMpNcVOYwx6TVN2_9DxWJw4kCPQ2iS82-4sJ9W3LRxvQkBvOHgWg-fvi5fMy-FpZOis9qH_PLafLbUScm7x6OHJeawoerf543O1UIEXh4Rs4X_LAG6NwLZBOduEI6ya4lRPXf-GU/s400/new-gallery-javascript.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;new gallery for javascript file&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
This file doesn&#39;t have to be in the publicly accessible public_html directory but can be safely tucked away in the java src directory as it will be loaded by the ADF framework from the classpath and not directly by the client browser (more on that later). I opted to put the javascript file in the same package as the tag handler:&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqRjAl_8WbpnMDZbaK42HAjepMiK7VfYAwRfF1WSiItgIdbc9ZRzLbrikACDDzUdrlW8h-wOE9iQzdWn3a0DzVa6jhtvmIYQHAtkCEpzexDLzZmMd1AdIIlUPcPopXYVDIqY1HKNIvKLI/s1600/create-javascript-dialog.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;166&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqRjAl_8WbpnMDZbaK42HAjepMiK7VfYAwRfF1WSiItgIdbc9ZRzLbrikACDDzUdrlW8h-wOE9iQzdWn3a0DzVa6jhtvmIYQHAtkCEpzexDLzZmMd1AdIIlUPcPopXYVDIqY1HKNIvKLI/s320/create-javascript-dialog.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;put the javascript file in the src directory&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;br /&gt;
All that is left is to actually implement the javascript:&lt;br /&gt;
&lt;pre class=&quot;brush:javascript&quot;&gt;/**
 * javascript constructor that invokes the Init function
 */
function RedHeapShowAlertBehavior() {
  this.Init();
}

// register as a subclass of AdfClientBehavior
AdfObject.createSubclass(RedHeapShowAlertBehavior,
                         AdfClientBehavior);

/**
 * initialize this behavior
 * @override
 */
RedHeapShowAlertBehavior.prototype.Init = function() {
  // be sure to invoke initialization by superclass
  RedHeapShowAlertBehavior.superclass.Init.call(this);
}

/**
 * as part of the AdfClientBehavior behavior contract, initialize is
 * called when the component is created to give the behavior a chance
 * to register event listeners.
 * @param {AdfUIComponent} component
 */
RedHeapShowAlertBehavior.prototype.initialize =
function(component) {
  AdfAssert.assertPrototype(component, AdfUIComponent);
  component.addEventListener(AdfActionEvent.ACTION_EVENT_TYPE,
                             this._handleAction, this);
}

/**
 * handle invoking a command component with this behavior.
 * @param {AdfUIInputEvent} event
 */
RedHeapShowAlertBehavior.prototype._handleAction =
function(event) {
  AdfAssert.assertPrototype(event, AdfUIInputEvent);
  alert(&#39;Yes we managed to trigger the client behavior&#39;);
  event.cancel(); // cancel normal event processing
}
&lt;/pre&gt;
&lt;br /&gt;
We are registering this behavior class as a subclass of &lt;a href=&quot;http://docs.oracle.com/cd/E23943_01/apirefs.1111/e12046/oracle/adf/view/js/base/AdfClientBehavior.html&quot; target=&quot;_blank&quot;&gt;AdfClientBehavior&lt;/a&gt; just as the default ADF behaviors. This ensures the initialize method (lines 28-32) is called with a reference to the JSF component we are adding behavior to. All we do there is register appropriate event listeners on the component, in this instance for the action (click) event. There are many types of events you can choose from but all of them are subclasses of &lt;a href=&quot;http://docs.oracle.com/cd/E23943_01/apirefs.1111/e12046/oracle/adf/view/js/event/AdfComponentEvent.html&quot; target=&quot;_blank&quot;&gt;AdfComponentEvent&lt;/a&gt;. In this example we listen to the action event which is defined in &lt;a href=&quot;http://docs.oracle.com/cd/E23943_01/apirefs.1111/e12046/oracle/adf/view/js/event/AdfActionEvent.html&quot; target=&quot;_blank&quot;&gt;AdfActionEvent&lt;/a&gt; while keyboard events live in &lt;a href=&quot;http://docs.oracle.com/cd/E23943_01/apirefs.1111/e12046/oracle/adf/view/js/event/AdfUIInputEvent.html&quot; target=&quot;_blank&quot;&gt;AdfUIInputEvent&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Whenever the user clicks the JSF command component our handler (lines 39-43) will be invoked. In this example we only show a javascript alert and cancel the event itself to prevent normal processing. This prevents the default handling of a button to submit the page to the server.&lt;/div&gt;
&lt;div&gt;
&lt;h2&gt;
Register Javascript Feature&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
Registering an &lt;a href=&quot;http://docs.oracle.com/cd/E23943_01/web.1111/b31973/ap_config.htm#BABEBBAD&quot; target=&quot;_blank&quot;&gt;ADF javascript feature&lt;/a&gt; has the benefit of ADF taking care of dynamically loading the necessary javascript files when needed and as an added bonus it will take care of appropriate http headers &amp;nbsp;to influence caching of these resources. Start by adding a XML file to your project:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnyhCE8kDosSRHlYf7oKKEgjakxbb7e4ZOUOqlrZLthtWrP5NCyJEmdzOwzm0Tb8eV1fpAZDNYWaFLz0uUYhHhss0Fy6-8YtAH4MTJ-bMWN9hyphenhyphenH6W1tuJlWG3Mz5OXbueYpKHC1CqPKeg/s1600/new-gallery-xml.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;242&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnyhCE8kDosSRHlYf7oKKEgjakxbb7e4ZOUOqlrZLthtWrP5NCyJEmdzOwzm0Tb8eV1fpAZDNYWaFLz0uUYhHhss0Fy6-8YtAH4MTJ-bMWN9hyphenhyphenH6W1tuJlWG3Mz5OXbueYpKHC1CqPKeg/s320/new-gallery-xml.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;new gallery for XML document&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Be sure to name the file adf-js-features.xml and it&lt;b&gt; has to be located&lt;/b&gt; in the src/META-INF directory otherwise the framework cannot find it:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhercGXN4V9sSKupnzFgmrEvnIQL1WIy2G-BnIbTiEtnc2rJY_OSMIYiByoCMn8HHuIavxlY_QJMym91IG_oKiSITCvJ-oiM3EcqqnV1UNccN1Y6m5c4deo1N58TmELhXCfb-pHi3Of0p0/s1600/create-xml-dialog.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;191&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhercGXN4V9sSKupnzFgmrEvnIQL1WIy2G-BnIbTiEtnc2rJY_OSMIYiByoCMn8HHuIavxlY_QJMym91IG_oKiSITCvJ-oiM3EcqqnV1UNccN1Y6m5c4deo1N58TmELhXCfb-pHi3Of0p0/s320/create-xml-dialog.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;creating src/META-INF/adf-js-features.xml&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Register your javascript feature in this file. The feature-name has to match the name that was returned by&amp;nbsp;getFeatureDependency() in your tag handler class while feature-class is the path to your javascript file within the classpath:&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&amp;gt;
&amp;lt;features xmlns=&quot;http://xmlns.oracle.com/adf/faces/feature&quot;&amp;gt;
  &amp;lt;feature&amp;gt;
    &amp;lt;feature-name&amp;gt;RedHeapShowAlertBehavior&amp;lt;/feature-name&amp;gt;
    &amp;lt;feature-class&amp;gt;com/redheap/clientbehavior/RedHeapShowAlertBehavior.js&amp;lt;/feature-class&amp;gt;
  &amp;lt;/feature&amp;gt;
&amp;lt;/features&amp;gt;&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h2&gt;
Library Deployment And Usage&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
All that is left is to bundle this all up as a library and consume it in any project you like. First thing you have to do is set the compiler options in your project properties to also include javascript files. Double click the project in JDeveloper and add &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;;.js&lt;/span&gt; to the file types to copy to the output directory:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguzG4EcLWR1lB9yYEY45aFwqhzYa0fsf3OptYgaN89PGJ_M5ArSpqSlsT91yyBrfzc-5XG_OyO4V_mKwKMb_xDwdY6MO6hrxJoIhvBkp331lG-vf5bX25ks9DBlfz6LOW-PF5Lqwj2XpQ/s1600/copy-js-to-output.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;213&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguzG4EcLWR1lB9yYEY45aFwqhzYa0fsf3OptYgaN89PGJ_M5ArSpqSlsT91yyBrfzc-5XG_OyO4V_mKwKMb_xDwdY6MO6hrxJoIhvBkp331lG-vf5bX25ks9DBlfz6LOW-PF5Lqwj2XpQ/s400/copy-js-to-output.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;setup project to copy javascript to output directory&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
If you added the tag library through the wizards JDeveloper already added a deployment profile to the project. This profile is fine for these simple cases although you could also setup an ADF Library that includes both this behavior and some reusable ADF components. For now, let&#39;s just use the default taglib deployment profile:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIhBgAEC73gmpiruvqiLZ62fRU3EJY1DiHER4gLwVSQqHBYWK2e5RkELhSMcRd0OhHazA9EasAblezjP1h2HSWYdVlaa3v8s83b8RUEvoa-R0CQqd3KbcM48SnqCpmdLGinS9HbT1lrCQ/s1600/deploy.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;214&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIhBgAEC73gmpiruvqiLZ62fRU3EJY1DiHER4gLwVSQqHBYWK2e5RkELhSMcRd0OhHazA9EasAblezjP1h2HSWYdVlaa3v8s83b8RUEvoa-R0CQqd3KbcM48SnqCpmdLGinS9HbT1lrCQ/s320/deploy.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;deploy using default taglib deployment profile&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Now open the project where you want to consume this library. Double click the project to open the project properties. Navigate to the JSP Tag Libraries and add a new one to the project:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyOypz2i_yuHL4e214EC0kU6urwqPmU-7-6fazmJxy1HyAe_2g356guHFpeEobBu71VsSD5IsVhY96IgEJG_WaOVSyA6VghltK6i13gqo2NJe_o_VDleX3d060kkHEeUsNX-_8K-S4Tzs/s1600/add-taglib.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyOypz2i_yuHL4e214EC0kU6urwqPmU-7-6fazmJxy1HyAe_2g356guHFpeEobBu71VsSD5IsVhY96IgEJG_WaOVSyA6VghltK6i13gqo2NJe_o_VDleX3d060kkHEeUsNX-_8K-S4Tzs/s320/add-taglib.png&quot; width=&quot;286&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;adding JSP taglib to the project&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimdzumQQ7yi_zVbjzjs4Ff1Bu6rMbOG8WdFKFcZpRpk15TRDRJKKq3b_zjltETJzMtSWSSJQsBEYH0m3dagsTQuaN-vKBTVRATTNvaOFSTItag4CdK3v5c_MYPHvlD178f29t3wecjIeA/s1600/add-taglib2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimdzumQQ7yi_zVbjzjs4Ff1Bu6rMbOG8WdFKFcZpRpk15TRDRJKKq3b_zjltETJzMtSWSSJQsBEYH0m3dagsTQuaN-vKBTVRATTNvaOFSTItag4CdK3v5c_MYPHvlD178f29t3wecjIeA/s320/add-taglib2.png&quot; width=&quot;211&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;add JAR library to the project&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Browse to the JAR file we just created. When returning to the JSP Tag Library dialog check the checkbox to execute the tags in the visual editor. For behaviors there isn&#39;t really a need to run these in the visual editor in JDeveloper but we might add JSF or ADF components at a later stage that actually render something in the visual editor:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoI6jS-1ojgBLYsn7wwFWDjrI9HCLeLKLjlFK4Mq_R5OoThcA8WxMxrEr32PNPhatEnzEGQ3zjzzhrKD8CsgrqZEPN410Gs9jjRcNY8abBbIkOXfXPi9rmsm9u6PZyuWOw7_J6b66JytU/s1600/exec-in-visedit.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;279&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoI6jS-1ojgBLYsn7wwFWDjrI9HCLeLKLjlFK4Mq_R5OoThcA8WxMxrEr32PNPhatEnzEGQ3zjzzhrKD8CsgrqZEPN410Gs9jjRcNY8abBbIkOXfXPi9rmsm9u6PZyuWOw7_J6b66JytU/s320/exec-in-visedit.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;execute tags in visual editor&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Now finally build a simple page an in the visual editor select the new component family in the component palette:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEQTmmCsZN5-fhL_UHa68XhreHTH_-MRcoH-a3LMOsu2UW7uuJS7nV95sup3DVhrb_tch3FqNH-r9ObmRX_Jquk-f4hpJYW8DECQ6NHC0NZriG8fWkz_ft4RdpQUAvszW9TeugZDoxr9s/s1600/component-palette.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEQTmmCsZN5-fhL_UHa68XhreHTH_-MRcoH-a3LMOsu2UW7uuJS7nV95sup3DVhrb_tch3FqNH-r9ObmRX_Jquk-f4hpJYW8DECQ6NHC0NZriG8fWkz_ft4RdpQUAvszW9TeugZDoxr9s/s200/component-palette.png&quot; width=&quot;132&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;select component family&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Drag and drop the behavior on the component where you want to use it:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguS62l1e9DOGVURkO4nD1u1nZgFJbs3fkMy_Ng4x_dXLqTLZceVuhg-eeGvdoEbHtfzC0A7jVmAeTShoAqCGvyVFHZpH-GlkJRn_UtyRubY1X99YCcqwIRWjEJe6Lqf-tmGfb2JHOV9yA/s1600/drag-drop-component.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;111&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguS62l1e9DOGVURkO4nD1u1nZgFJbs3fkMy_Ng4x_dXLqTLZceVuhg-eeGvdoEbHtfzC0A7jVmAeTShoAqCGvyVFHZpH-GlkJRn_UtyRubY1X99YCcqwIRWjEJe6Lqf-tmGfb2JHOV9yA/s400/drag-drop-component.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;drag-and-drop behavior on component&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Finally run the page and click the button to see the behavior in action as it shows a javascript alert:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3PcLgzkCvOLYUiSCUjfizE8JMm7oH9o_ksJTyP70NAYlKHa16CIGUrruySac6-4-_d6KVq3IWLLXLlSb_Ga7hxPDk8Zx4YEMBst7nmwsSwUCV4pBsVe3jBYDtwk_rPgsUI_ux6EpHD_g/s1600/run.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;222&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3PcLgzkCvOLYUiSCUjfizE8JMm7oH9o_ksJTyP70NAYlKHa16CIGUrruySac6-4-_d6KVq3IWLLXLlSb_Ga7hxPDk8Zx4YEMBst7nmwsSwUCV4pBsVe3jBYDtwk_rPgsUI_ux6EpHD_g/s400/run.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;running sample&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;h2&gt;
Future Posts&lt;/h2&gt;
This post has already grown too big, so I&#39;ll try to wrap up and keep the other stuff for future posts. Things I still have to cover is how to pass parameters to the behavior (like customizing the message in this alert), how to complement the sample with a facelets tag library so it will also work in version 11.1.2 when using facelets and one real world sample where we use keyboard listener to insert a comma as decimal mark when the user is using the dot on the numerical keyboard.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Sample Application&lt;/h2&gt;
As always you can&amp;nbsp;&lt;a href=&quot;http://java.net/projects/redheap/downloads/directory/jdev11116/ClientBehavior&quot; target=&quot;_blank&quot;&gt;download the full sample&lt;/a&gt;&amp;nbsp;application or&amp;nbsp;&lt;a href=&quot;http://java.net/projects/redheap/sources/svn/show/jdev11116/ClientBehavior&quot; target=&quot;_blank&quot;&gt;browse the subversion repository&lt;/a&gt;&amp;nbsp;to look at the&lt;br /&gt;
source code. And even though it is not the most fancy application you can also see it &lt;a href=&quot;https://java-trialaam2.java.us1.oraclecloudapps.com/ClientBehavior/&quot; target=&quot;_blank&quot;&gt;live on Oracle Cloud&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Update&lt;/h2&gt;
A follow-up post is available that explains how to&amp;nbsp;&lt;a href=&quot;http://www.redheap.com/2013/03/adf-faces-client-behavior-with-parameters.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;add support for attributes to your custom client behavior&lt;/a&gt;.&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/6732445401785500969/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/02/custom-adf-faces-client-behavior-jsp-tag.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/6732445401785500969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/6732445401785500969'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/02/custom-adf-faces-client-behavior-jsp-tag.html' title='Custom ADF Faces Client Behavior 11.1.1 JSP tag'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggxIQkSFPuWS-eIHNgucDO8myCMdsURcmES3sQkpCcEPWF6IajtH-RSqvN8aEq12YP_fj9e-fUlKJ6rzUqu5Tk6HCTMCjpNhQmEcxlZJz8FppDKoXuMMnfYZUnwIIKAVxYigXtdcerhiw/s72-c/new-gallery-taglib.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-1490667354564075343</id><published>2013-02-01T21:41:00.001+01:00</published><updated>2013-03-11T20:01:28.874+01:00</updated><title type='text'>Deploy a simple ADF application to Oracle Cloud</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
I write sample applications to accompany blog posts. You can typically download the project as a zip file or get access to the subversion repository. But I also wanted to make it as easy as possible for people to see the running application. This where the &lt;a href=&quot;http://cloud.oracle.com/&quot; target=&quot;_blank&quot;&gt;Oracle Cloud&lt;/a&gt; comes in. I currently still have a free trial java cloud and this posts explains how I deployed one of the sample applications to that cloud.&lt;br /&gt;
&lt;br /&gt;
First thing you need is the latest version of &lt;a href=&quot;http://www.oracle.com/technetwork/developer-tools/jdev/downloads/jdeveloper11116-1377208.html&quot; target=&quot;_blank&quot;&gt;JDeveloper 11.1.1.6&lt;/a&gt;. If you already have JDeveloper installed be sure to check Help &amp;gt; About for the version number. For reasons beyond my comprehension Oracle decided to give the JDeveloper version with cloud support the same version number. The one you need is build 6229 and not the original build 6192:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhO-XbeyjpikelSB6cKeidMBOvtFQETO6ZUp6W0jh9GKvPOtY82B4EmF1Fo7pJtbv87q8FseRY4KCvJBe9JcZRKSxMT20yYh-4fG0D24LdU15yQJCPDA4uitvLpl0-WzKaFLn5WK4MNFoc/s1600/version-old.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;72&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhO-XbeyjpikelSB6cKeidMBOvtFQETO6ZUp6W0jh9GKvPOtY82B4EmF1Fo7pJtbv87q8FseRY4KCvJBe9JcZRKSxMT20yYh-4fG0D24LdU15yQJCPDA4uitvLpl0-WzKaFLn5WK4MNFoc/s320/version-old.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7s7dJWSpA_05Ov6pbieTLHH-5Crk0J-LFMNQP8gow-UYLUTK8GiBUvy-IYh8jN9HORLztVDtZwGmRJ9Y4xI4rWYOg6bdqPjC_m0kqMMAm7ZasNvo1FDev_JXU5kLBak5RpDMk7ZPCsv4/s1600/version-new.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;70&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7s7dJWSpA_05Ov6pbieTLHH-5Crk0J-LFMNQP8gow-UYLUTK8GiBUvy-IYh8jN9HORLztVDtZwGmRJ9Y4xI4rWYOg6bdqPjC_m0kqMMAm7ZasNvo1FDev_JXU5kLBak5RpDMk7ZPCsv4/s320/version-new.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Get the credentials that you use to logon to your Oracle cloud. This is a username, password and identity domain:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcUDbBAFk-QhnEzif0X10Wq4FuFpGxn4OkQy-5BnFjVTOHPoTKArDZqtk4lrlBobFB6FeTIQ2X9wQnhoJwijXc7JJKu3Q5owkQMnYRqQ7uBSBPJa2M552MGKzQLy8ozSeXjENNz-xOras/s1600/logon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;205&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcUDbBAFk-QhnEzif0X10Wq4FuFpGxn4OkQy-5BnFjVTOHPoTKArDZqtk4lrlBobFB6FeTIQ2X9wQnhoJwijXc7JJKu3Q5owkQMnYRqQ7uBSBPJa2M552MGKzQLy8ozSeXjENNz-xOras/s320/logon.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;get credentials for oracle cloud&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Then we need to register an Application Server connection to the Oracle Cloud with these credentials. From the resource palette (View &amp;gt; Resource Palette) add a new connection:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigtFXtmK6IuKP7MCHKE_m8tCGtGt7niJsXNo9kN6YmbIymA7Y9PhTbEghZFYNIiH_tVq4dRH7dN2PzekPV5fYVSM725nIcxLFRhfv2LImiIwOcWSIjW5Uc2DG8Hz0Xu3lXTTvXLs2wQRA/s1600/create-connection1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;156&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigtFXtmK6IuKP7MCHKE_m8tCGtGt7niJsXNo9kN6YmbIymA7Y9PhTbEghZFYNIiH_tVq4dRH7dN2PzekPV5fYVSM725nIcxLFRhfv2LImiIwOcWSIjW5Uc2DG8Hz0Xu3lXTTvXLs2wQRA/s320/create-connection1.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Be sure to select &quot;Oracle Cloud&quot; as the connection type:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgm53LpcguRB9YwtMXVCUfYjHm_Gm50JcHXPHcE3nuYaQ4faFaRDm8IcJ8gWMAEOS_u-o5ra1KfcG1rNBjlE2d1cSXB4xi86gb2ob8xtLeVLGg0Yk8kmy488qCBzhZlw5VqpknUJnMgwJ8/s1600/create-connection2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;218&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgm53LpcguRB9YwtMXVCUfYjHm_Gm50JcHXPHcE3nuYaQ4faFaRDm8IcJ8gWMAEOS_u-o5ra1KfcG1rNBjlE2d1cSXB4xi86gb2ob8xtLeVLGg0Yk8kmy488qCBzhZlw5VqpknUJnMgwJ8/s320/create-connection2.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;select Oracle Cloud as connection type&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZj0l5uU0dGpkiSMTSBO1VIfuaL4CZtc1RzFI2IIgfdpTwoHIKYRT1-MQ393P93cpOtxlzNdQtzX1hmbZ-OmakerCwXTakknwuNUIScualQuxmupKIfghT-C6p2H43rgLNRkPSegbIuIg/s1600/create-connection3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;140&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZj0l5uU0dGpkiSMTSBO1VIfuaL4CZtc1RzFI2IIgfdpTwoHIKYRT1-MQ393P93cpOtxlzNdQtzX1hmbZ-OmakerCwXTakknwuNUIScualQuxmupKIfghT-C6p2H43rgLNRkPSegbIuIg/s320/create-connection3.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;enter your Oracle Cloud credentials&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNOfGsCfRwW-PGFrpb0VKk6YSDKFZ9DY-evbK49pmUMbwwLXDeUV8NRxaw-GIdJKIWsdnAExZuptHTIKFwLiNNAEaOapZbeje7WD65jJ5FLwvjEwZpM_vg4mogZENZKw-gUZ9cX_103Xc/s1600/create-connection4.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;160&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNOfGsCfRwW-PGFrpb0VKk6YSDKFZ9DY-evbK49pmUMbwwLXDeUV8NRxaw-GIdJKIWsdnAExZuptHTIKFwLiNNAEaOapZbeje7WD65jJ5FLwvjEwZpM_vg4mogZENZKw-gUZ9cX_103Xc/s320/create-connection4.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;enter identity domain and name of the service instance&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
When using a trial cloud instance your service instance is typically called &quot;java&quot;. You can see this in your Oracle Cloud dashboard.&lt;br /&gt;
&lt;br /&gt;
I want my applications to be publicly available on the Oracle Cloud and not requiring any logon credentials. To accomplish this add an empty login-config entry to the web.xml file:&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;  ......
  &amp;lt;!-- empty logon-config to allow anonymous access on Oracle Cloud --&amp;gt;
  &amp;lt;login-config/&amp;gt;
&amp;lt;/web-app&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
I also added a welcome-file to the web.xml so requests to&amp;nbsp;xxx.oraclecloudapps.com/Application get redirected to xxx.oraclecloudapps.com/Application/faces/defaultPage:&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;  ......
  &amp;lt;!-- set welcome file so requests to / get redirected to the default page --&amp;gt;
  &amp;lt;welcome-file-list&amp;gt;
    &amp;lt;welcome-file&amp;gt;/faces/demo&amp;lt;/welcome-file&amp;gt;
  &amp;lt;/welcome-file-list&amp;gt;
&amp;lt;/web-app&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
If I forgot either of the above steps I would get an Error 403 - Forbidden when trying to access the homepage of my application:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZvrTnhIa_FDNrogiWnLsFFfz1nMrAMe0ajPHsIsWRSt1f4sXgHF6mLQ4ruqvMSfHtUt0MiFqug3tTYUCHewLHaFiH-at0TdjNWmN1tHKZigeNVzN_83Rwu-UTvPnlgcm7tXeQ2spFikA/s1600/403forbidden.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;198&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZvrTnhIa_FDNrogiWnLsFFfz1nMrAMe0ajPHsIsWRSt1f4sXgHF6mLQ4ruqvMSfHtUt0MiFqug3tTYUCHewLHaFiH-at0TdjNWmN1tHKZigeNVzN_83Rwu-UTvPnlgcm7tXeQ2spFikA/s400/403forbidden.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;403 error when not disabling security or setting homepage redirect&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
Now you can deploy from within JDeveloper as you would always do to a remote application server:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilsaYtzlSVcQjiLpdPVU0nzDqb1NnM-lCmY0_KjPaUhnKMnoRoLftCNgTayEOfnI4ZFsVpKX-opC-EEHntyetys9FcskaoWOHtn_ICqDQ-blremkhiNBQTHsjj0S8ResPqTxSlee4Y6i4/s1600/deploy.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;280&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilsaYtzlSVcQjiLpdPVU0nzDqb1NnM-lCmY0_KjPaUhnKMnoRoLftCNgTayEOfnI4ZFsVpKX-opC-EEHntyetys9FcskaoWOHtn_ICqDQ-blremkhiNBQTHsjj0S8ResPqTxSlee4Y6i4/s320/deploy.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;deploying the application&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF4VEgLk-PZpwy9RDDIU8zOThpsE2CN_XSmiM2gMSkUe1whTEcqPYoWbkL6vy6S-ch3TEuV8cO0gLCTCsnGBt83vJr7s-u8EdVp6B08ZeMycyprKuKaDVrKOD495QC6XNBNuXMVEWEdmE/s1600/deploy-log.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;122&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF4VEgLk-PZpwy9RDDIU8zOThpsE2CN_XSmiM2gMSkUe1whTEcqPYoWbkL6vy6S-ch3TEuV8cO0gLCTCsnGBt83vJr7s-u8EdVp6B08ZeMycyprKuKaDVrKOD495QC6XNBNuXMVEWEdmE/s400/deploy-log.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;log of deploying the application&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
If you now visit your Oracle Cloud console you can monitor the application and get the URL to run it. (BTW the run URL was also in the deployment log in JDeveloper)&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKcin3Oc2zHuAhf83-dxcrfujLnt3FswGB_vNDB6AxCmgrs_YaIEMpkFdbNK9-YfCA4v7l3AZvT7U3RqkIcwvaVwsObdcYJIkWfqpOUy46lo3n0Kze5bHPwn9XBicuHW2bI-7Xqn0_lCk/s1600/cloud-console.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;176&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKcin3Oc2zHuAhf83-dxcrfujLnt3FswGB_vNDB6AxCmgrs_YaIEMpkFdbNK9-YfCA4v7l3AZvT7U3RqkIcwvaVwsObdcYJIkWfqpOUy46lo3n0Kze5bHPwn9XBicuHW2bI-7Xqn0_lCk/s320/cloud-console.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;open the java service console from your dashboard&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEK3H0pmUWM83ZWrnSIZzp3m2GRpisSMRWMXCLaPwrc8o-8s1raJxUCm8-JauskGBUaWdC1KZtrHLisKmv5uh2e0ZolPtOMw2Ez50-g0i048UKnOEiSC0RBToBrEmEdHJyYp0DVGIaHNg/s1600/test-console.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;130&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEK3H0pmUWM83ZWrnSIZzp3m2GRpisSMRWMXCLaPwrc8o-8s1raJxUCm8-JauskGBUaWdC1KZtrHLisKmv5uh2e0ZolPtOMw2Ez50-g0i048UKnOEiSC0RBToBrEmEdHJyYp0DVGIaHNg/s400/test-console.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;monitor the instance and applications&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;br /&gt;
So here it is my &lt;a href=&quot;https://java-trialaam2.java.us1.oraclecloudapps.com/DateWithoutSeparator&quot; target=&quot;_blank&quot;&gt;very first live sample application&lt;/a&gt; on the Oracle Cloud. It is the sample from a previous blogpost on a &lt;a href=&quot;http://www.redheap.com/2013/01/global-datetimeconverter-without.html&quot; target=&quot;&quot;&gt;DateTimeConverter that accepts dates without separators&lt;/a&gt;.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/1490667354564075343/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/02/deploy-adf-application-to-oracle-cloud.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/1490667354564075343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/1490667354564075343'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/02/deploy-adf-application-to-oracle-cloud.html' title='Deploy a simple ADF application to Oracle Cloud'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhO-XbeyjpikelSB6cKeidMBOvtFQETO6ZUp6W0jh9GKvPOtY82B4EmF1Fo7pJtbv87q8FseRY4KCvJBe9JcZRKSxMT20yYh-4fG0D24LdU15yQJCPDA4uitvLpl0-WzKaFLn5WK4MNFoc/s72-c/version-old.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-1187194339349603526</id><published>2013-01-30T20:07:00.000+01:00</published><updated>2013-03-11T20:05:09.193+01:00</updated><title type='text'>Performance diagnostics with ADFLogger</title><content type='html'>This post will show how to use the ADF Logger for&amp;nbsp;performance&amp;nbsp;analysis and how to instrument your own code so it shows up in this analysis. Every ADF developer should know, or learn, about the ADF Logger. If you are new to the logger than read up on it at the &lt;a href=&quot;http://docs.oracle.com/cd/E23943_01/web.1111/b31974/web_testdebug.htm#BABDBCGF&quot; target=&quot;_blank&quot;&gt;official documentation&lt;/a&gt; or the great &lt;a href=&quot;https://blogs.oracle.com/groundside/entry/adventures_in_logging_index&quot; target=&quot;_blank&quot;&gt;Adventures in Logging&lt;/a&gt; series by Duncan Mills.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Configuring Oracle Diagnostic Logging&lt;/h2&gt;
First thing we need to do is to configure the proper ADF Logger levels as the default levels will only show warning and errors. Run your application so the integrated WebLogic server starts. The log window in JDeveloper will have an Actions pull down menu where you can opt to configure Oracle logging:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhA1hRC-ZtbYI4IY0gdCXJYUashqw3U_uyvkI_GEhYkA7gd8jZM2kP-8KD629rYw94Tk6wx0Mg5XxdUp2iSbKAOCXQEM1h9dgn5UWs7pZh929-4Ge_hasl-gQwZy-HLRyTfNO7GObZJ4D0/s1600/start-config.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;171&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhA1hRC-ZtbYI4IY0gdCXJYUashqw3U_uyvkI_GEhYkA7gd8jZM2kP-8KD629rYw94Tk6wx0Mg5XxdUp2iSbKAOCXQEM1h9dgn5UWs7pZh929-4Ge_hasl-gQwZy-HLRyTfNO7GObZJ4D0/s400/start-config.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;configuring Oracle Diagnostic Logging&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
This will open an editor to the logging configuration file at DefaultDomain/config/fmwconfig/servers/DefaultServer/logging.xml which is typically in JDEV_USER_HOME/system11.1.1.6.38.61.92&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
All the logging for performance diagnostics is done at the CONFIG level so be sure to set the Root logger and Oracle logger to CONFIG. While developing you might even want to crank up the levels for oracle.adf, oracle.adfinternal and oracle.jbo to FINEST but be aware that this will show a lot more logging which has a performance impact of its own.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ7QAgbsg_90tvCLxLaQBG1_Bi8u-TMFgrmK_620ZyuDwYXLIkQ6vur_u52myUaFQr2VuYQL7ZdgtKcwoCFLg5MdMJ9fsEW9tc2KCmsNKGyzD9irLaRlqI4SJppaHVrYASDkRR8pUZYNk/s1600/config-logging.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ7QAgbsg_90tvCLxLaQBG1_Bi8u-TMFgrmK_620ZyuDwYXLIkQ6vur_u52myUaFQr2VuYQL7ZdgtKcwoCFLg5MdMJ9fsEW9tc2KCmsNKGyzD9irLaRlqI4SJppaHVrYASDkRR8pUZYNk/s320/config-logging.png&quot; width=&quot;185&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h2&gt;
Run bad performing application&lt;/h2&gt;
Once this is done we return to our simple example application and apply a filter to an af:table that is based on a bean datacontrol:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicMpqjtrWudnbR6kiRrsO_joBIXhItWsHe_Plm0Iu7AW28-fi83psYB08V8Xp0323KSHiYYmUh_Nn2-GMjIA4O7DDwgU5-u-YPYEnLnbeuAUf1LsSO2TRcvpop-C00eZ99nT0u_MsVCb0/s1600/view-filtered.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;203&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicMpqjtrWudnbR6kiRrsO_joBIXhItWsHe_Plm0Iu7AW28-fi83psYB08V8Xp0323KSHiYYmUh_Nn2-GMjIA4O7DDwgU5-u-YPYEnLnbeuAUf1LsSO2TRcvpop-C00eZ99nT0u_MsVCb0/s320/view-filtered.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;filtering af:table that re-fetches data from slow data control&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
From the logging we can see that the employees are fetched again. This might be a surprise since the page had already retrieved the list of employees from the bean datacontrol. Why would filtering need to request the data from the data control again? When we experience bad performance in an application it would be nice if we can quickly analyze the logs and discover where time is spent.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWbi8qOhNDK1CNqyUt3gQPOUxcA5rccF71WuuSWBZIJMV1e8Z5t5DDLwLMICDO3mlG_sdzMZrl-BHSHjxl0quvOPZaqDc74dsXKqVBlyp4sHTcP0489-BAAUlt_Fty5ua8eV_IuJXn74c/s1600/logging.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;161&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWbi8qOhNDK1CNqyUt3gQPOUxcA5rccF71WuuSWBZIJMV1e8Z5t5DDLwLMICDO3mlG_sdzMZrl-BHSHjxl0quvOPZaqDc74dsXKqVBlyp4sHTcP0489-BAAUlt_Fty5ua8eV_IuJXn74c/s400/logging.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;logging showing up in console&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;h2&gt;
Analyze Log&lt;/h2&gt;
Luckily we instrumented our code to use the ADFLogger. This not only writes a line to the log window, but also makes it part of the log analysis. To see this working invoke the log analyzer from the same pull down menu in the log window:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGl7pJUvmkaRSj2CjH1qvWHfIQv_REQydju-mTVVoN7_r7ahEvm2-eq7D8aIgLiPseMAg9VkdWbR_p-23N6Ke1mtwndwsFmjFtcx3CVzBjFNSkZL2iWmZDuiViqwliwT60cL_7IkoHuH0/s1600/start-analyze.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;168&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGl7pJUvmkaRSj2CjH1qvWHfIQv_REQydju-mTVVoN7_r7ahEvm2-eq7D8aIgLiPseMAg9VkdWbR_p-23N6Ke1mtwndwsFmjFtcx3CVzBjFNSkZL2iWmZDuiViqwliwT60cL_7IkoHuH0/s400/start-analyze.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;starting log analyzer&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
We can now inspect individual requests and drill down in the separate phases. We can quickly see our fetchEmployees method was executed in this last request and it took 2973 milliseconds to complete.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzww22au-NDr9o4WKTdseWhiDIWfUxHd4cjOf3vJdOzQl-BRHZHYlSq5YrI8c5gMs3AHr7rzz2-F5MPVFOD7OEABM2BBekbflIhkFHuAd957W50xRvuq2r_ewxI5t59biN0v-NLJ4NwoU/s1600/analyzer.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;260&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzww22au-NDr9o4WKTdseWhiDIWfUxHd4cjOf3vJdOzQl-BRHZHYlSq5YrI8c5gMs3AHr7rzz2-F5MPVFOD7OEABM2BBekbflIhkFHuAd957W50xRvuq2r_ewxI5t59biN0v-NLJ4NwoU/s400/analyzer.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;log analyzer showing our own instrumented code&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;h2&gt;
Instrument Your Code&lt;/h2&gt;
The key to making this work is to invoke &lt;a href=&quot;http://docs.oracle.com/cd/E23943_01/apirefs.1111/e10686/oracle/adf/share/logging/ADFLogger.html#begin(java.lang.String, java.util.HashMap)&quot; target=&quot;_blank&quot;&gt;ADFLogger::begin&lt;/a&gt; and &lt;a href=&quot;http://docs.oracle.com/cd/E23943_01/apirefs.1111/e10686/oracle/adf/share/logging/ADFLogger.html#end(java.lang.String)&quot; target=&quot;_blank&quot;&gt;ADFLogger::end&lt;/a&gt; in your code. You should do this before and after any code that can be time consuming, for example requesting a URL, invoking a webservice, very expensive calculations, interacting with the file system, etcetera.&lt;br /&gt;
&lt;br /&gt;
Once you invoke ADFLogger::begin you have to make absolutely sure you also invoke ADFLogger::end even when exceptions occur. For this reason, you would typically use a try-catch-finally construct:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;logger.begin(&quot;[[DESCRIPTION]]&quot;);
try {
  // TODO: do your stuff here
} finally {
  // make sure you always call ADFLogger::end with same description
  logger.end(&quot;[[DESCRIPTION]]&quot;);
}
&lt;/pre&gt;
&lt;br /&gt;
One other nice feature about Oracle Diagnostic Logging is that you can supply additional context with a log message that will not clutter the default console logging but is available in the more advanced viewers such as the log analyzer. In this example you can see the java.specification.version but in a real application you would typically log information about the resource intensive task such as the URL being retrieved, query being performed or file being read.&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCiwkWTJs-IRmM53bef8lSpkAC4ylInzfTOEFv239uNQgWQOVXH73M-4_7ouZ3PMK6wSWy2B20tkDQrKsJjFhSF4HA9lEuLcWMctMdV68o4Cafus5NwO8_192p_uag82WfBtIAb5_YW3E/s1600/analyzer-details.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;117&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCiwkWTJs-IRmM53bef8lSpkAC4ylInzfTOEFv239uNQgWQOVXH73M-4_7ouZ3PMK6wSWy2B20tkDQrKsJjFhSF4HA9lEuLcWMctMdV68o4Cafus5NwO8_192p_uag82WfBtIAb5_YW3E/s400/analyzer-details.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;log analyzer showing supplied context&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Unfortunately &lt;a href=&quot;http://docs.oracle.com/cd/E23943_01/apirefs.1111/e10686/oracle/adf/share/logging/ADFLogger.html#begin(java.lang.String, java.util.HashMap)&quot; target=&quot;_blank&quot;&gt;ADFLogger::begin&lt;/a&gt; requires a full blown java.util.HashMap with this context. First of all it is bad practice to require specific classes when the java.util.Map intreface would suffice. But more annoying is that constructing a HashMap can require quite some lines of code which would clutter your java code. For this, I created a utility class that accepts a set of Strings as &lt;a href=&quot;http://docs.oracle.com/javase/1.5.0/docs/guide/language/varargs.html&quot; target=&quot;_blank&quot;&gt;varargs&lt;/a&gt;. The list of strings you supply as arguments are alternating keys and values hence the&amp;nbsp;requirement&amp;nbsp;for an even number of parameters.&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class LoggingUtil {
  private LoggingUtil() {}
&amp;nbsp; public static void begin(final ADFLogger logger, final String action,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;final String... context) {
    if (context.length % 2 != 0) {
&amp;nbsp; &amp;nbsp;   throw new IllegalArgumentException(&quot;even number of context parameters required (alternating keys and values)&quot;);
&amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; final HashMap&amp;lt;String, String&amp;gt; map = new LinkedHashMap&amp;lt;String, String&amp;gt;();
&amp;nbsp; &amp;nbsp; for (int i = 0, cnt = context.length; i &amp;lt; cnt; i += 2) {
&amp;nbsp; &amp;nbsp;   map.put(context[i], context[i + 1]);
&amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; logger.begin(action, map);
&amp;nbsp; }
&amp;nbsp; public static void end(final ADFLogger logger, final String action) {
    logger.end(action);
&amp;nbsp; }
}
&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
This keeps the actual java code very clean of logging code as constructing the HashMap is done in the utility class and only if the logging level actually needs this additional context:&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public List&amp;lt;Employee&amp;gt; getEmployees() {
  LoggingUtil.begin(logger, &quot;fetchEmployees&quot;,
&amp;nbsp;   &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;java.specification.version&quot;,
                    System.getProperty(&quot;java.specification.version&quot;));
  try {
  &amp;nbsp; fetchFromSlowSource();
&amp;nbsp; &amp;nbsp; return employees;
&amp;nbsp; } finally {
  &amp;nbsp; LoggingUtil.end(logger, &quot;fetchEmployees&quot;);
&amp;nbsp; }
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
You can &lt;a href=&quot;http://java.net/projects/redheap/downloads/directory/jdev11116/PerformanceLogger&quot; target=&quot;_blank&quot;&gt;download the full sample&lt;/a&gt; application or &lt;a href=&quot;http://java.net/projects/redheap/sources/svn/show/jdev11116/PerformanceLogger&quot; target=&quot;_blank&quot;&gt;browse the subversion repository&lt;/a&gt; to look at the source code. When running this application yourself be sure to setup the logging levels of your WebLogic server appropriately.</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/1187194339349603526/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/01/instrumentation-performance-diagnostics-with-adflogger.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/1187194339349603526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/1187194339349603526'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/01/instrumentation-performance-diagnostics-with-adflogger.html' title='Performance diagnostics with ADFLogger'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhA1hRC-ZtbYI4IY0gdCXJYUashqw3U_uyvkI_GEhYkA7gd8jZM2kP-8KD629rYw94Tk6wx0Mg5XxdUp2iSbKAOCXQEM1h9dgn5UWs7pZh929-4Ge_hasl-gQwZy-HLRyTfNO7GObZJ4D0/s72-c/start-config.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-8893299884842235536</id><published>2013-01-30T15:30:00.000+01:00</published><updated>2013-03-11T20:04:46.887+01:00</updated><title type='text'>SyntaxHighlighter at Blogger</title><content type='html'>Running a tech/developer blog means I will be posting source code and other technical text. This requires proper syntax highlighting and use of monospaced fonts. Unfortunately blogger.com doesn&#39;t really support this out of the box so we need to resort to 3rd parties. Alex Gorbatchev created an awesome syntax highlighter purely in javascript. This means it doesn&#39;t need a server side component and we can easily integrate it into blogger.&lt;br /&gt;
&lt;br /&gt;
To integrate SyntaxHighlighter into blogger you have to edit the HTML of your template:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1BO1IufIidorf-6k5E5mxM81GR4GtRpO7ikCfP4ZKRIgEaGG79Vu8T6kkRc4QDc3bWcWPK65KWl-JD015f2HOtEm7KD2_fgsSgOkvzyGgATTRU_h1gQTYxouqWe52_MAtDQ1TpdEywiM/s1600/edit-template.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;258&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1BO1IufIidorf-6k5E5mxM81GR4GtRpO7ikCfP4ZKRIgEaGG79Vu8T6kkRc4QDc3bWcWPK65KWl-JD015f2HOtEm7KD2_fgsSgOkvzyGgATTRU_h1gQTYxouqWe52_MAtDQ1TpdEywiM/s400/edit-template.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;how to get to editing your blogger template&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Next you have to insert some javascript and CSS just after the &lt;tt&gt;title&lt;/tt&gt; tag:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLOAjifrl_TrT0bWlMo0r1vYzfe1sFhqGYOnRTrDW0ixVOKBd9FWNwwVV6owqakp3sma6V1EWw7DPDWMkUwI6Uga_gSApQ5Hk2kgnfgy0uaef_GusZMtkuwEcfO_Dwk5ycKIPTpE9oMWg/s1600/edit-template2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;288&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLOAjifrl_TrT0bWlMo0r1vYzfe1sFhqGYOnRTrDW0ixVOKBd9FWNwwVV6owqakp3sma6V1EWw7DPDWMkUwI6Uga_gSApQ5Hk2kgnfgy0uaef_GusZMtkuwEcfO_Dwk5ycKIPTpE9oMWg/s400/edit-template2.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;editing the template html&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Here is the snippet I inserted:&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;script src=&quot;http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&#39;http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js&#39; type=&#39;text/javascript&#39;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&#39;http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js&#39; type=&#39;text/javascript&#39;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&#39;text/javascript&#39;&amp;gt;
  SyntaxHighlighter.config.bloggerMode = true;
  SyntaxHighlighter.defaults[&#39;auto-links&#39;] = false;
  SyntaxHighlighter.defaults[&#39;tab-size&#39;] = 2;
  SyntaxHighlighter.defaults[&#39;toolbar&#39;] = false;
  SyntaxHighlighter.all();
&amp;lt;/script&amp;gt;
&amp;lt;link href=&quot;http://alexgorbatchev.com/pub/sh/current/styles/shCore.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;&amp;gt;
&amp;lt;link href=&quot;http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
The first line loads the core javascript and then I load the javascript for each type of brush I intend to use. A &lt;a href=&quot;http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/&quot; target=&quot;_blank&quot;&gt;full list of brushes&lt;/a&gt;/syntax files and the required javascript can be found at Alex&#39; site.&lt;br /&gt;
&lt;br /&gt;
After loading the brushes there are a few lines of inline javascript. Prior to running the SyntaxHighlighter with SyntaxHighlighter.all() I enable bloggerMode as we are using this at blogger.com and I setup defaults. Documentation on &lt;a href=&quot;http://alexgorbatchev.com/SyntaxHighlighter/manual/configuration/&quot; target=&quot;_blank&quot;&gt;configuration of the highlighter itself and defaults&lt;/a&gt; for each highlighted element can be found at Alex&#39; site. You might want to tweak these for your site.&lt;br /&gt;
&lt;br /&gt;
Finally I add the core css file to the page as well as a css file with the theme I choose. You can &lt;a href=&quot;http://alexgorbatchev.com/SyntaxHighlighter/manual/themes/&quot; target=&quot;_blank&quot;&gt;pick your own theme&lt;/a&gt; that matchs your site.&lt;br /&gt;
&lt;br /&gt;
Finally, please consider hosting these files on your own server (although that can&#39;t be blogger). If you are using the files hosted by Alex himself, as in the examples, please consider&lt;a href=&quot;http://alexgorbatchev.com/SyntaxHighlighter/hosting.html&quot; target=&quot;_blank&quot;&gt; making a donation&lt;/a&gt; to cover his bandwidth costs and to show your appreciation with the work he&#39;s done.</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/8893299884842235536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/01/syntaxhighlighter-at-blogger.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/8893299884842235536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/8893299884842235536'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/01/syntaxhighlighter-at-blogger.html' title='SyntaxHighlighter at Blogger'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1BO1IufIidorf-6k5E5mxM81GR4GtRpO7ikCfP4ZKRIgEaGG79Vu8T6kkRc4QDc3bWcWPK65KWl-JD015f2HOtEm7KD2_fgsSgOkvzyGgATTRU_h1gQTYxouqWe52_MAtDQ1TpdEywiM/s72-c/edit-template.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4865637371278230637.post-8024824945294309017</id><published>2013-01-29T07:25:00.000+01:00</published><updated>2013-03-11T20:04:26.345+01:00</updated><title type='text'>Global DateTimeConverter without separators</title><content type='html'>We are developing an application where data processing speed is important and users have to enter a lot of dates into the system. This is replacing a legacy Oracle Forms system where people were used to entering dates without any separators. For example they want to enter &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;120613&lt;/span&gt; for June 12th 2013 (or December 6th 2013 if you&#39;re from the US).&lt;br /&gt;
&lt;br /&gt;
ADF Faces (and MyFaces Trinidad) has its own &lt;a href=&quot;http://docs.oracle.com/cd/E23943_01/apirefs.1111/e12419/tagdoc/af_convertDateTime.html&quot;&gt;DateTime converter&lt;/a&gt; that is already pretty advanced and lenient. You can give it a pattern and it will try to parse any input in several variations of the supplied pattern. For example, both &quot;Jan/4/2004&quot; and &quot;01.4.2004&quot; will be parsed with a pattern of &quot;MMM/d/yyyy&quot;. For months it will try MMM, MM and M and it will try any of the separators - or . or /&lt;br /&gt;
&lt;br /&gt;
But we wanted the converter to also try a pattern without any separators. You could specify a secondary pattern for a converter and it will also try to parse any input with this secondary pattern while still using the primary pattern for displaying the date/time. But I don&#39;t like the idea of manually setting a secondary pattern on each and every date field in the application.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
So we replace the default DateTime converter with our own. This custom converter extends from the default ADF Faces/Trinidad converter:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class LenientDateTimeConverter extends
       org.apache.myfaces.trinidadinternal.convert.DateTimeConverter&lt;/pre&gt;
&lt;br /&gt;
It can then override the getSecondaryPattern method and return a pattern without any separators:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;@Override
    public String getSecondaryPattern() {
        final String secPattern = super.getSecondaryPattern();
        if (secPattern != null) {
            // use secondary pattern when explicitly set
            return secPattern;
        }
        // get primary pattern (or default if none defined)
        final DateFormat dateFormat =
            getDateFormat(FacesContext.getCurrentInstance(), getPattern(),
                          true, null);
        if (dateFormat instanceof SimpleDateFormat) {
            return getPatternWithoutSeparators(((SimpleDateFormat)dateFormat).toPattern());
        }
        return null;
    }&lt;/pre&gt;
&lt;br /&gt;
The final trick is to register this custom converter as the default one for the entire application. The challenge is that there are a number of ways the ADF/JSF framework looks for a datetime converter and we have to replace all of them. This requires the registration of a number of converters in the faces-config.xml file:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;  &amp;lt;!-- for inputDates without explicit converter so they will use default JSF converter --&amp;gt;
  &amp;lt;converter&amp;gt;
    &amp;lt;display-name&amp;gt;Date Time Converter&amp;lt;/display-name&amp;gt;
    &amp;lt;converter-id&amp;gt;javax.faces.DateTime&amp;lt;/converter-id&amp;gt;
    &amp;lt;converter-class&amp;gt;com.redheap.datenosep.LenientDateTimeConverter&amp;lt;/converter-class&amp;gt;
  &amp;lt;/converter&amp;gt;

  &amp;lt;!-- for input- and output-components that use explicit af:convertDateTime --&amp;gt;
  &amp;lt;converter&amp;gt;
    &amp;lt;display-name&amp;gt;Date Time Converter&amp;lt;/display-name&amp;gt;
    &amp;lt;converter-id&amp;gt;org.apache.myfaces.trinidad.DateTime&amp;lt;/converter-id&amp;gt;
    &amp;lt;converter-class&amp;gt;com.redheap.datenosep.LenientDateTimeConverter&amp;lt;/converter-class&amp;gt;
  &amp;lt;/converter&amp;gt;

  &amp;lt;!-- for outputText without explicit converter who determine converter based on java class --&amp;gt;
  &amp;lt;converter&amp;gt;
    &amp;lt;display-name&amp;gt;Date Time Converter&amp;lt;/display-name&amp;gt;
    &amp;lt;converter-for-class&amp;gt;java.util.Date&amp;lt;/converter-for-class&amp;gt;
    &amp;lt;converter-class&amp;gt;com.redheap.datenosep.LenientDateTimeConverter&amp;lt;/converter-class&amp;gt;
  &amp;lt;/converter&amp;gt;
  &amp;lt;converter&amp;gt;
    &amp;lt;display-name&amp;gt;Date Time Converter&amp;lt;/display-name&amp;gt;
    &amp;lt;converter-for-class&amp;gt;java.sql.Date&amp;lt;/converter-for-class&amp;gt;
    &amp;lt;converter-class&amp;gt;com.redheap.datenosep.LenientDateTimeConverter&amp;lt;/converter-class&amp;gt;
  &amp;lt;/converter&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
The sample application comes with a demo page to test the different locale and input types (date, time or both). Below are some screenshots that show the computed secondary pattern as well as the accepted and parsed input in both en_US and nl locale:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgqs7XYTPRTtIS-eyjPtDl71kbRQra5bcw-_Guj_WytbxCbLucFzobagbjzRm81Dtzbm-ZljRS8NsmjIvIgqVmJPju_E0WDUi_O0QTjQgW2VrjBASwL5IjTynnaRDLMk5Tn3CXgjSqm0o/s1600/us-input.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;165&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgqs7XYTPRTtIS-eyjPtDl71kbRQra5bcw-_Guj_WytbxCbLucFzobagbjzRm81Dtzbm-ZljRS8NsmjIvIgqVmJPju_E0WDUi_O0QTjQgW2VrjBASwL5IjTynnaRDLMk5Tn3CXgjSqm0o/s320/us-input.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;entering date without separators in en_US locale&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4e7jTug72zrSJAZfXRbveWZmBeZzaOub9exVMNov74C99aVg9rhb6VhhKOVXzz70Ibjtqpd87Ub9KdDpYbqehD3p8ITD9mdFZ1u6xYHynY7YRy0BEgw1jxehHYxibfYfHAsSRt0J0jNg/s1600/us-done.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;165&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4e7jTug72zrSJAZfXRbveWZmBeZzaOub9exVMNov74C99aVg9rhb6VhhKOVXzz70Ibjtqpd87Ub9KdDpYbqehD3p8ITD9mdFZ1u6xYHynY7YRy0BEgw1jxehHYxibfYfHAsSRt0J0jNg/s320/us-done.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;finished entering date in en_US locale&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi67mMiyYQGkk06thyphenhyphenc0gHJ8RjdyK4VrRN4EugxDUEYDWmYE2DBV6zEsZcUW7Arq04Tyl0vkSqAQCgY6ymVvMuNYydP9OHGeTNHIoCTfbyaaV3NA2lww1sgn8cY90CqSo3GEShtwX-Jw1I/s1600/nl-input.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;165&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi67mMiyYQGkk06thyphenhyphenc0gHJ8RjdyK4VrRN4EugxDUEYDWmYE2DBV6zEsZcUW7Arq04Tyl0vkSqAQCgY6ymVvMuNYydP9OHGeTNHIoCTfbyaaV3NA2lww1sgn8cY90CqSo3GEShtwX-Jw1I/s320/nl-input.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;entering date without separators in nl locale&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkrWjy2EAGnwb4K43KgaaemEoCWXc4MNJjEaaQW5jOxqcbbxImzu2h17-zo196UTGS-LrDt9-vq_-1Nns78oXsyULcyy8VPJS2a9uldvb9iuB9lDHHYZ348AMv2hkWY1Pdfx2jjNB3Y90/s1600/nl-done.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;165&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkrWjy2EAGnwb4K43KgaaemEoCWXc4MNJjEaaQW5jOxqcbbxImzu2h17-zo196UTGS-LrDt9-vq_-1Nns78oXsyULcyy8VPJS2a9uldvb9iuB9lDHHYZ348AMv2hkWY1Pdfx2jjNB3Y90/s320/nl-done.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;finished entering date in nl locale&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
Sample application: &lt;a href=&quot;http://java.net/projects/redheap/downloads/directory/jdev11116/DateWithoutSeparator&quot; target=&quot;_blank&quot;&gt;DateWithoutSeparator&lt;/a&gt;&lt;br /&gt;
Source code repository: &lt;a href=&quot;http://java.net/projects/redheap/sources/svn/show/jdev11116/DateWithoutSeparator&quot; target=&quot;_blank&quot;&gt;DateWithoutSeparator&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.redheap.com/feeds/8024824945294309017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.redheap.com/2013/01/global-datetimeconverter-without.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/8024824945294309017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4865637371278230637/posts/default/8024824945294309017'/><link rel='alternate' type='text/html' href='http://www.redheap.com/2013/01/global-datetimeconverter-without.html' title='Global DateTimeConverter without separators'/><author><name>Gieofkkskfofd</name><uri>http://www.blogger.com/profile/16041770673036839729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgqs7XYTPRTtIS-eyjPtDl71kbRQra5bcw-_Guj_WytbxCbLucFzobagbjzRm81Dtzbm-ZljRS8NsmjIvIgqVmJPju_E0WDUi_O0QTjQgW2VrjBASwL5IjTynnaRDLMk5Tn3CXgjSqm0o/s72-c/us-input.png" height="72" width="72"/><thr:total>2</thr:total></entry></feed>