X

Technical Articles relating to Oracle Development Tools and Frameworks

Recent Posts

JET

Web Component Techniques - Integrating Components with VBCS Service Endpoints

Introduction In this article in the Web Components Techniques series I'm going to look at a fairly specialised topic, that of creating components that can call into VBCS Service Endpoints (REST Services managed by Oracle Visual Builder Cloud Service). Now as a matter of course we try and build components which are totally agnostic of where they will be used, I should be able to use that component both within JET or any JET based UI, including VBCS of course.  As such we might define our component API with properties which work with generic data-types such as Array or the JET DataProvider interface. However, there are cases where this is really not sufficient.  For example, you are building a complex CRUD (CReate Update Delete) screen as a re-usable component.  This will need to keep communicating with the appropriate REST endpoints within the context of the component, rather than just manipulating a set of data and allowing the hosting application to take care of the REST part (Note: this is just a pattern, not the pattern there are various ways for components to behave in these scenarios, there is no one-size fits all approach).  So how could we accomplish this? Well of course you could have the component take a URL to the endpoint as a property and then it can make the XMLHTTP requests internally, but the problem with that approach is that your component becomes responsible for managing any headers and security tokens that might be required, and, as it will be making a direct connection to the endpoints there may be more CORS configuration to be done on the server end to allow that communication. We also have to consider little inconveniences such as the fact that the endpoints may move between testing and production.  In this article, however, we'll be looking at a more satisfactory approach where we get all the flexibility of being able to re-use existing REST endpoints that VBCS has defined already, combined with the ability to make as many calls as required to those endpoints throughout the components operational lifecycle. Because the REST service definition and communication is managed by VBCS we can safely ignore security and endpoint relocation issues because VBCS will be handling all that for us.  The REST Helper API So in this article I'll be using the VBCS REST Helper API.  Internally this is the same API that the VBCS runtime uses for it's REST calling actions and the Service Data Provider variable types.  It provides a simple way to call a REST service using the abstract service and endpoint name to reference it.  The precise details of the authentication and actual URL of the endpoint are hidden from us behind that service definition so the code can remain clean and does not have to be cluttered up with concerns such as setting security tokens or having URLs move over time.  The illustrate this I'll use a very simple REST API provided by GITHub - https://api.github.com/licenses/{license} (you can try this in your browser using this to see what it returns). What I'll do is create a simple component that makes a call to this API to get the license text detail for a given license name.  Step 1 - Define the Service in VBCS The first thing that we have to do of course is to define the above endpoint. I've chosen a service here that you'll all be able to get to and one which does not require any API Keys or other authorisation, just to keep things simple and easy for you to have a go at.  We start by defining a new Service Connection: Choose Define By Endpoint: And define the service + endpoint: And press Next: Here of course we would usually define the authentication as well, however, in this simple example we can skip that.  However, do pay attention to the Service ID field. You will need this ID later when you come to call the service. You can change the value of you wish or use the default ID as generated.  I'll use the default value of apiGithubCom here. Next we go the the Test tab and make sure that we're getting the data we expect with an example license e.g. MIT: At this point we press the Copy to Response Body button to describe the basic shape of the response payload and we're done so we can press the Create button. Once the create is done, re-select the service and endpoint and make a note of the Endpoint ID as shown here. Again you can change this if you wish and I've updated mine from the default value of "getLicensesLicense" to the more readable value of getLicense. Step 2 - Make Sure the Service is Consumed This is the step that developers often forget and in doing so spend a lot of time trying to work out why the REST Helper is not working.  In Step 1, I just defined the service and the endpoint that I needed.  I did not, however, associate it with the application that I want to use it from.  Remember that in a VBCS project you might have several Web and Mobile applications, so there is no assumption that every service will be used in every project.  Now normally, if you are using a given endpoint in the default manner, e.g. you create a Service Data Provider that uses it, or you create an Action Chain that calls it, then VBCS design time will automatically map the service as being used in the process.  However, if you're only using this endpoint programatically then you have to ensure this mapping yourself.  There are two ways of doing this: Create, and then delete, a dummy action chain that calls a REST action that uses the service endpoint that you've created  Manually edit the app-flow.json file with the correct attributes If in doubt, use the first technique, you only have to do it once for a project to get the mapping defined. The result (and the information that you would add manually if taking approach 2) is: "services": { "apiGithubCom": { "path": "../../services/apiGithubCom/service.json" } }, Notice how the Service ID we noted earlier is mapped to its underlying definition. Step 3 - Using the REST Helper API Now all that pre-amble is complete I can actually get to some code.  At this point I'm assuming that you have a component already and as part of that component implementation you want to call the endpoint defined earlier.  Let's break this down into sub-steps: Step 3.1 Define your Component API You might not choose to do this, but I'd never want to hard-code any kind of connection information into my component so I'll add some properties with defaults to define the name of the service and endpoints that are going to be used: { "name": "demo-license-viewer", "displayName": "View License", "description": "Allows the user to select a license and view the full text for it", "version": "1.0.0", "jetVersion": ">=5.2.0 < 7.0.0", "properties": { "license":{ "displayName":"License", "description":"Short code for the license to display", "type":"string" }, "serviceId":{ "displayName":"Service ID", "type":"string", "value":"apiGithubCom" }, "endpointId":{ "displayName":"Endpoint ID", "type":"string", "value":"getLicense" } } } Step 3.2 Consume the Helper API Next we need to make the helper code available in the component viewModel. To do this you import the vb/helpers/rest module via the define() block of your component viewModel: define([ 'knockout', 'ojs/ojcore', 'vb/helpers/rest' ], function ( ko, oj, RestHelper ) { In this case, the module has been made available via the RestHelper argument to the module function, making it available throughout the component. This is the point of no-return, your component can only ever be loaded in VBCS now (unless you mock that module). Step 3.3 Get the Endpoint In order to start to configure and call the required endpoint we need to call the get() static function on the REST Helper passing the IDs of the service and endpoint concatenated together as a string using '/'. e.g. my endpoint would ultimately be apiGithubCom/getLicense. In my sample here, I'm going to use the properties that I configured on the API to construct this: self.endpointAddress = self.properties.serviceId + '/' + self.properties.endpointId; var ep = RestHelper.get(self.endpointAddress); Step 3.4 Set Parameters In this sample we are just doing a simple GET request, but we will still need to pass one parameter, that of the license code that is being looked up, e.g. MIT. If you recall from Step 1, where I defined the endpoint, in this case this was a path parameter called license (as defined by the token in curly braces in license/{license}. However, we do the same thing with query parameters as well, which is to construct an object with the required attributes matching the parameter names and pass those to the parameters() function on the endpoint object that was received from the helper. ep.parameters({"license":self.properties.license}); This call to parameters() can of course include as many attributes as are required to configure the call Step 3.5 Invoke the Endpoint Everything is now set and you just need to call the fetch() method on the endpoint to execute it. This will return a promise that will be resolved once the REST call is complete and the response is passed back as an object for you to parse. This returned object contains a body attribute and a response attribute which includes the following key attributes: bodyUsed Simple boolean flag to indicate if there is a body payload or not ok Boolean flag to indicate the overall state of the call status HTTP response code for the call statusText HTTP response text for the call redirected Boolean to indicate if the request was redirected So, in my example, the text of the license is returned by the GITHub API in an attribute called body within the response body (a little confusing but that's just that particular API): ep.fetch().then(function(result){ if (result.response.ok){ //update the observable that is bound in the UI self.licenseText(result.body.body); } else { //report the error! } }); More Than Just GET Requests In the simple example I used here, I used a GET endpoint.  However, we can use the REST Helper API with other endpoint types just as POST and DELETE as well. Everything is handled in the same way, and the fetch() method call is used to "execute" the REST call.  The main addition that you'll need to know about for POSTs in particular, is how to set the body of the request. Well, not surprisingly, you call a function called body() in the endpoint, passing it an object which defines the payload you need to send. There are some more advanced parts of the API for dealing with transformations, but those are for discussion in a further article. Conclusion The VBCS REST Helper API, as we've seen;  is a powerful, simple to use and all-in-all valuable tool for the custom component developer, but should only be selected if you're sure it's the only way and / or your component will only be ever used from within VBCS where the API is available. JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Architecture Learning Path

Introduction In this article in the Web Components Techniques series I'm going to look at a fairly specialised topic, that of creating components that can call into VBCS Service Endpoints (REST...

Web Component Techniques - Finesse the Component Lifecycle

Introduction In this occasional series of Web Component Techniques, I discuss common patterns and topics that Oracle JET Custom Web Component (CCA) authors are likely to need at one point or another.  In this article I'll be looking at how the component  is not quite as fixed in stone as it appears and the key technique that you can use to bend it to your will.  The "Problem" - Back to Basics To summarise the issue that you might be confronting let's just quickly re-visit the basic component initialisation lifecycle as implemented in JET: Component constructor - runs just the once of course and before the component is attached to the DOM activated - again fires just once, after the constructor and allows you to "hold" the initialisation of the component be returning a promise, in which case the component lifecycle will not move forward until that promise is resolved or rejected.  This is useful if your component needs to do some asynchronous setup before you can show anything, for example make a fetch from a REST endpoint connected - may fire multiple times over the lifespan of the component as it is attached / re-attached to the DOM, something that might happen if the component (for example) was in a popup. bindingsApplied - fires just once at the point that all of the internal components being used by the custom web component have been upgraded and are fully functional Component authors have to decide how best to use this sequence in terms of where to put certain functions.  For example, as discussed above, if the component absolutely must have data before it can be displayed then that code belongs in activated.  Likewise, if your code needs to do something like getElementById on one of it's subcomponents, then that has to be done in the bindingsApplied, because that's when any :id references in the component view will have been resolved.  Trying to find a component by ID earlier in the lifecycle will simply not work. So this illustrates a particular problem - what if you need to carry out some action in a phase of the lifecycle (let's pick on connected) that is dependent on a later phase in some way, e.g. bindingsApplied. This seems to be an intractable problem because the former executes after the latter?   This is where this pattern comes into play.  Promises Promises So here's how we deal with it.  You need an approach that will work both on the first run-though if the lifecycle and subsequent invocations such as call-backs to the connected method over the lifecycle of the component.  We achieve this using a promise which can be used to "hold" execution of a piece of code until all of the required parameters are met, something that will work no matter if this is the first run through the lifecycle or if this is a reconnect. So working with our example of connected requiring an element reference that won't be available until bindingsApplied....  Step 1 - Defer the code execution in connected() In our connected method we enclose the code that might need to be executed in a deferred manner in a then() block as follows MyComponentModel.prototype.connected(context){ var self = this; self.getInstanceSemaphore().then(function(){ // Do lifecycle critical stuff here // e.g. getElementById calls }); } As you will hopefully have gathered, the getInstanceSemaphore() function will be returning a promise and it when that promise resolves that the code can be executed Step 2 - Implement the getInstanceSemaphore() The getInstanceSemaphore() method is pretty generic, all it is really doing is just creating a marker promise that can be resolved at any point in the lifecycle that you choose. Note how it saves the resolve callback to the component model (via self) so that some other phase can resolve the promise and allow pending actions to take place MyComponentModel.prototype.getInstanceSemaphore = function () { var self = this; if (self.semaphorePromise) { return self.semaphorePromise; } else { self.semaphorePromise = new Promise(function (resolve) { self.instanceSemaphoreResolver = resolve; }); return self.semaphorePromise; } } Step 3 - Signal ready state in bindingsApplied() All that remains is for some piece of code to call the stored resolver for the semaphore promise. This would typically be in bindingsApplied as this is at the very end of the initialisation lifecycle and things such as dynamic IDs will have been evaluated and applied.  MyComponentModel.prototype.bindingsApplied(context){ var self = this; //Any normal code for this phase ... //And finally ready to resolve all the waiting code self.instanceSemaphoreResolver(); //clean up the resolver, we don't need it any more delete self.instanceSemaphoreResolver; } So, the use of this semaphore mechanism will mean that the very first time that the connected() method executes, the critical code will sit and wait for bindngsApplied() to have been run before it kicks off. However, on subsequent re-connects, the promise will have already have been resolved and the code can execute immediately, giving you the best of both worlds. JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Architecture Learning Path

Introduction In this occasional series of Web Component Techniques, I discuss common patterns and topics that Oracle JET Custom Web Component (CCA) authors are likely to need at one point or another.  ...

JET Custom Web Components in Oracle Visual Builder

  In this article, I'll be discussing various topics relating to how JET Custom Web Components can be optimized for use in Visual Builder Cloud Service. First of all - just to be clear - at one level, there is nothing to do. JET custom Web Components will "just work" out of the box with Visual Builder. This should come as no great surprise, after all, the user interface that you create in Visual Builder is just a JET UI. You can get away without doing any specific work for Visual Builder at all, however, there are several areas in which you can optimize the experience of consuming your components and this is what I'll be concentrating on in this article. I'm going to divide things up into two sections.  First of all some design considerations for the components from a functional point of view, and then a review of the metadata for your components and how that can effect Visual Builder design time  Good Practice in Component Design for Visual Builder So let's look at the couple of things that you need to consider when creating components for use by developers using Visual Builder. How it Looks at Design Time  When using the visual design view of Visual Builder, the page that you are creating is actually being run for you.  This is  so that you get a reasonable interpretation of how the final runtime page will appear with real data.  However, this can present a challenge for you as when your custom component is first dropped into the page. This is because when first dropped it will be dropped as a bare component tag and not configured in any way. A common result of this is that the component will often seem to "disappear" and be impossible to select on the visual canvas (although it can be selected in the structural navigator). Why is this? Well it's a problem with the component itself. Often when a component is instanciated without setting any of it's properties it will actually render no UI at all and it's this that makes it disappear, effectively it may collapse to a 0x0 px element. Various solutions are possible to prevent this happening and make it easier for the user to find the component once it's in the view.  Give the component a minimum height and width.  In the component CSS file define some minimum sizing just so it can't collapse to a zero point. If the component requires some information before it can even attempt to draw, then have it output some useful message as a placeholder that can disappear once configuration is complete.  For example, here's my Google Maps integration component when it is first dropped onto the canvas. This component needs a Google API key before it can operate, so whilst I'm waiting for the developer to provide that I at least tell them so: Of course as soon as the required information is supplied, the component then uses some sensible defaults to show something to the user which they can then further configure: You'll notice here that the property inspector is showing some default values for things like the map type and the zoom level, although the default map-centerpoint is something the component defaults internally until the component user overrides it.  This simple act of thinking about the consuming developers first encounter with your component is so important!  How the Component Reacts to Change Within the Visual Builder environment it's really important that your components are correctly listening for external changes to property values as they happen. It's not enough to just process the configuration properties in the constructor of your component and be done with it. You must also be watching for asynchronous changes to those properties once the component is instanciated.  The reason for caring about this is that when properties are bound to Visual Builder variables, the population of those variables might well be asynchronous and not be complete until after your component has been started. If you don't listen for ongoing changes to the property, then your component might not be seeing the correct configuration values.  This is a really common issue for rookie component developers - don't get caught out!  Fortunately JET makes it really easy to handle this situation, Custom Components internally support a propertyChanged() lifecycle method which will be automatically called whenever a bound variable is updated (either internally or externally to the component).  So you should always provide an implementation of this method to update your component as those changes occur.  Fully Formed metadata Now that I've looked at the key design mistakes to avoid, let's look at how you can improve the user experience of your components in Visual Builder design time; through the use of well formed metadata.  JET Custom Web Components have a comprehensive metadata definition that you can find in the JSDoc (here). Visual Builder design time pays particular attention to this information, and so the better the definition you provide, the better the end user experience will be.  Let's look at the key metadata attributes as used by the design time: "displayName" The displayName attribute can appear in multiple places in your metadata. At the top level it is applied to the component as a whole but can also be defined for individual properties and event as well. It is basically used to provide user-readable names for use in design time.  So for example, if the displayName is set at the component level then that will be used to label the component in the component palette, e.g. "Google Map" instead of the full tag name (oj-sample-google-map) which takes up more space and is harder to read. In the defintion: {   "name": "oj-sample-google-map",   "displayName": "Google Maps",   "version":"1.0.0",   ... } The images below show what the component palette entry would look like both with and then without the displayName being set: With displayName                                                   Without    We can also see how displayName is used for the Property Inspector when provided for individual properties. Again it just provides a nicer (and translatable!) label for the Property Inspector Field.  So for this property defintion: "zoom": {   "type": "number",   "displayName": "Zoom level",   ... } We get the nicer "Zoom level" label on the field. Longer, camel cased property names really benefit from this capability. "description" Just like displayName, the description attribute is present at various levels of the metadata and using it you can provide a additional information about the component as a whole or just a single property.  In either case you'll see a question mark icon displayed at design time and when you hover over that you'll get the description information displayed to help the user of the component. Component Level Property - "icon" The icon attribute only exists at the top level of the component defintion, and not surprisingly allows you to provide a custom image to display in the component palette for the component. This attribute actually provides three sub-attributes to allow you to set both the base, selected and hover-over state of the icon. (Note that currently the selected state is not used or needed so just define the base and the hover version) e.g.  {     "name": "oj-sample-google-map",     "displayName": "Google Maps",     "icon": {         "iconPath": "extension/images/map.png",         "hoverIconPath":"extension/images/map_hov.png"     }, You saw the result of this in the earlier image: Images should be in either png or svg format and if png should be sized to no greater than 20x20px to fit correctly (16x16 is ideal). SVG images will be scaled for you. The default color for the icon in normal state should be #8a8d8f and white (#ffffff) in the hover state if you supply that. Property Level Attribute - "value" The property level attribute value is used at runtime to provide a default value for the specified property, but it is also used at design time in Visual Builder and is displayed as a place-holder in the property inspector field so that the user can see what the default would be.  We saw this already in the screenshot of the zoom property PI. As it's a placeholder value it is displayed as a lighter grey colour and the user can of course overtype it: Property Level Attribute - "required" The required attribute in the property metadata is honored in the form of an indicator (*) on the field - just a hint to the user that this is a property that really must be supplied. Here we see it on the apiKey property of the map component: As you can see, the user will also get a gentle reminder if they still forget to provide that property! Property Level Attributes - "type" and "format" The type attribute of a Custom Web Component property tells the runtime how to handle the conversion of the string value found in the HTML tag into the datatype that the component actually asks for.  However, just like value and required attributes, this information is also used at design time to add some extra help for the user.  Different types will be serviced by different sorts of input fields - for example, we've seen the "Zoom level" Property Inspector field is shown as a number input with a spinner, not a plain text field control.  Design time actually combines the type attribute with a second attribute called format which can further refine what kind of control to display.  The supported values for format are: For when type=number double    floating point number with double precision float    floating point number with single precision int32    signed 32-bit integer int64    signed 64-bit integer For when type=string color    CSS color value date    date in RFC 3339 format, using the "full-date" profile date-time    date-time in RFC 3339 format, using the "date-time" profile time    time in RFC 3339 format, using the "full-time" profile In these cases specialised input fields such as date or colour pickers will be presented in the property inspector. Property Level Attributes - "minimum" and "maximum" When dealing specifically with a type=number, the minimum and maximum attributes will come into play to restrict the values that the user can enter into a field to those range constraints.  Note that this will prevent the property inspector from being used to enter out-of range values, however, the user can still edit the tag in the source code to breach the range.  therefore your component will still need to do some runtime checking to enforce the defined rule.  Property Level Attribute - "enumValues" Like number properties, string properties some times have a "range". In the case of stings this is specifically a set of valid values defined using the enumValues attribute.  When Visual Builder design time sees a string attribute with an enumValues then, rather than just displaying a text input field, it will instead display a select-one choice drop-down in the property inspector. In doing so, it helps the consuming developer by listing the values up front in a simple to use form, meaning that the developer does not need to refer back to the documentation. Property Level Attribute - "propertyEditorValues" Just like the use of displayName to make the labels for properties more readable, sometimes you don't want the actual enumeration values to be what you display in the enumValues drop-down.  If you need something more readable then you define a propertyEditorValues attribute for the property and for each enumeration optioin you can provide extra metadata for the displayName and description. Here's an example from the mapType property:   "mapType": {     "description": "Display style of the map",       "type": "string",       "writeback": true,       "enumValues": [           "roadmap",           "hybrid",           "satellite",           "terrain"       ],       "propertyEditorValues": {           "roadmap": {             "displayName": "Roadmap",               "description": "Displays the basic map style concentrating on road / transport links."           },           "hybrid": {               "displayName": "Hybrid",               "description": "Displays a mix of roadmap and satallite views."                 },                 "satellite": {                     "displayName": "Satellite",                     "description": "Displays Google Earth satellite images."                 },                 "terrain": {                     "displayName": "Terrain",                     "description": "Displays a physical map with roadmap overlay."                 }             },             "value": "roadmap",             "propertyGroup": "common"         }  Again notice how displayName is used to provide an alternate label in the drop down (in this case capitalized versions of the possible values). Here's the result: Property Level Attribute - "propertyGroup" Finally, each property can define which propertyGroup it is a part of.  PropertyGroup is a logical collection of properties and is used as a hint by Visual Builder design time to decide on which Property Inspector tab to display the property on. All properties are visible on the "All" tab in the Property inspector, but if your compoennt has an important property that needs to be set most of the time then you'll want it to appear on the General tab of the property inspector. To do this, you set the propertyGroup attribute to "common". Likewise you may set the propertyGroup to "data" to make the property appear on the Data tab. If we look again at the property inspector for the Map component: You can see how I've just put the most important properties, those that are set nearly all the time, on the General tab. The idea here is to help the user to understand what parts of the component API are the most important to set, so consider carefully which properties you prioritze in this way. Summary As you can see, with relatively little effort you can really improve a component consumers experience of using your component. In general, everything that I've listed here makes sense to define even if you are not particularly targeting the Visual Builder platform. This is simply because in doing so you are defining the API of your component more precisely which can only be a good thing! JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Architecture Learning Path

  In this article, I'll be discussing various topics relating to how JET Custom Web Components can be optimized for use in Visual Builder Cloud Service.First of all - just to be clear - at one level,...

JET

JET 6.0.0 Notes for Component Authors

In my usual roundup, let's have a quick look at what's new an noteworthy for JET Custom Component Authors in JET 6.0.0 which was released recently.  What's in a Name? If you read the documentation and have a look at the cookbook, you'll notice that there is a subtle re-naming operation slowly taking place.  We're talking less about "CCA" and more about Custom Web Components in those places.  There is nothing to worry about here though, they are both the same thing, but we're just switching to use the more industry standard term to refer to the custom components that you create (Yes you are creating real Web Components). Throughout my blog articles I'm sure I'll slip up from time to time and revert to using CCA (because it shorter!),  but I'll do my best... Changes to Deployment  A subtle but valuable change has occurred in what happens when you do an ojet build or ojet serve command on a project that includes Custom Web Components.  As you will know, if you use the ojet create component command your new component will be created in the /src/js/jet-composites folder, this has not changed, but two slightly different things happen when you deploy: You will see that in the deployed structure for the project (the /web folder) that rather than mirroring the exact structure of the /src folder, the custom components are now deployed into a sub-folder which is defined by a version number.  Thus the loader file for a component e.g. /src/js/jet-composites/demo-comp/loader.js would end up as /web/js/jet-composites/demo-comp/1.0.0/loader.js where in this case 1.0.0 is the version number in the demo-comp component.json file. This change is intended to set us up for the future and to handle the case where you might have multiple versions of the component and want to switch between them. To complement this change in location in the deployed component code the build process now automatically creates a RequireJS path for you that points to the correct deployment location. This path has the same name as the component (e.g. demo-comp) and will point to the correct runtime location for the component automatically. So what does this mean to you?  Well the major point is that when you consume a component in a view, in your define() block, rather than referring to the component by an absolute path e.g. jet-composites/demo-comp/loader, instead you can just use the path with the same name as the component e.g. simply demo-comp/loader. Over time this will be a good thing because it will allow you to carry out tasks such as bundling, or deploying your components to a CDN and not have to touch any of your code that relies on that component because all you will have to do is to tweak the RequireJS path for "demo-comp" (in this example). Changes to the Loader Script The final topic to discuss for the 6.0.0 release is a change you will see in the loader script generated for you by the ojet create component command.  In earlier versions you'll be familiar with loaders that look very much like this: define([     'ojs/ojcore',     './viewModel',     'text!./component.json',     'text!./view.html',     'css!./styles',     'ojs/ojcomposite' ], function (     oj,     viewModel,     metadata,     view) {         'use strict';         oj.Composite.register('demo-comp', {             view: view,             viewModel: viewModel,             metadata: JSON.parse(metadata)         });     } ); Whereas in 6.0.0 and above you will see this, with the  ojs/Composite class now "in charge" so to speak and no need to import ojcore: define([     'ojs/ojcomposite',     './viewModel',     'text!./component.json',     'text!./view.html',     'css!./styles' ], function (     Composite,     viewModel,     metadata,     view) {         'use strict';         Composite.register('demo-comp', {             view: view,             viewModel: viewModel,             metadata: JSON.parse(metadata)         });     } ); This change is part of a larger simplification / cleanup that you'll see over the next few releases to remove the need to use the oj. namespace as a root to access everything. Both forms still work, and if you want your components to be compatible with older versions of JET then you can revert to the pre-6.0.0 format without a problem. Tis is particularly important if you are creating components for versions of Visual Builder Cloud Service that are using these earlier versions of JET. JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Architecture Learning Path

In my usual roundup, let's have a quick look at what's new an noteworthy for JET Custom Component Authors in JET 6.0.0 which was released recently.  What's in a Name? If you read the documentation and...

JET Custom Components XXII - Template Slots

In JET 5.1.0 we introduced a really exciting and useful addition to the component authors toolbox, that of templated-slots. Before I dive into the mechanics though, I'd like to discuss the kind of problems that they are designed to solve: It's All About Scope If you have used normal slots, you will be aware that the intent is to allow the component author to leave placeholders in the component view for consumers to drop in their own content.  The typical example of this being something like a toolbar component which supplies a certain set of pre-ordained buttons, but which supports a slot for consumers to add some of their own.  So slot content is supplied by the consumer but "managed" from a layout perspective by the component. This is all very good, however, there is one restriction that can limit the usefulness of slots and that is the matter of data scoping.  Any components that you put into a slot may well end up as children of the custom component in UI / DOM terms, however, in data binding terms they are peers of the custom component. The slotted components cannot see the data that the CCA is managing internally and are effectively bound to the same parent viewModel as the custom component is.  This makes it tricky for the custom component to manage data in the slotted children and often results in compromised component design just to enable such data sharing to take place. The other big problem area with conventional slotting and the scoping rules surrounding it, is the creation of custom components that use stamping user interfaces to output sets of data. An example of such a component might be a customized list-view  where the custom component is managing the communications with a REST endpoint that is providing the data, however, you, as the component author, want the consumer to have the ability to shape how each row should be rendered as it's stamped out.  With conventional slotting, this type of use case is really not possible without cheating1 and this is really why templated slots have been introduced. Introducing Templated Slots Templated Slots introduce the idea of a data context to a slot, so rather than the components in the slot only seeing the same data from the parent viewModel as the component, they actually see (some selected) data from within the Custom Component as well.  This is a subtle but fundamental difference. Here's a simple example: <demo-list-o-data data="{{someData}}"> <template slot="employeeRowTemplate" data-oj-as="employeeRow"> <span> <oj-bind-text value="[[employeeRow.employeeName]]"></oj-bind-text> </span> </template> </demo-list-o-data> So in the above example the value for employeeName is actually being provided by the demo-list-o-data component itself, not the surrounding page model.  Breaking Down the Use of Templated Slots Looking at the above example there are some key things to note: The root child of a templated slot must be a <template> element as shown here. The name of the template-slot that this template relates to is indicated by the slot attribute on the template tag. So in this case the template will be used for the employeeRowTemplate slot. Just like normal slots, a templated-slot can be defined as the default slot for the component, in which case, the consumer would not have to define a slot attribute. The data-oj-as attribute on the template tag defines how the template-slot specific data can be accessed.  In this case, the data in the context of the template will be accessed through a variable called employeeRow.  Functionally this is the same as the as attribute you find on components such as oj-bind-for-each and oj-list-view.  I'll explain how you can actually define that set of data as a component author later. If data-oj-as is not supplied on the template then the data is exposed through a standard variable called $current. Within the template we can refer to the data provided by the custom component using that oj-data-as alias, hence the reference to employeeRow.employeeName in the <oj-bind-text>. Again, if data-oj-as had not been  supplied then the binding expression would use $current.employeeName instead. Apart from this, from the perspective of the consumer, using a templated-slot is really just like using any other slot. Templated-Slots for Component Authors Now let's look at what it takes to define a templated slot within your components Metadata First of all, of course, we want to make it clear to consumers (and tooling such as VBCS) that they are dealing with a templated-slot, not a "normal" slot. This is done by defining a data attribute in the slot metadata that describes the shape of the specific data that the component will be exposing through to the slot contents via $current or the assigned data-oj-as name. For our example here, this is what the component.json slot metadata might look like: "slots": { "employeeRowTemplate":{ "description":"Allows the consumer to control how each row in the list is laid out", "data": { "employeeId": { "description":"Unique identifier for the employee", "type":"number" }, "employeeName": { "description":"First and last name of employee", "type":"String" } } } } Note how I also give the user a clue here by appending the word "Template" to the slot name, that's probably a good practice to follow. In the Component View Once you have a templated-slot defined you assign it into your component view in much the same way as a conventional slot, except: You use the <oj-bind-template-slot> tag to act as the marker rather than just <oj-bind-slot> You set the data attribute on the oj-bind-template-slot to map the data that you want to expose through the data-oj-as / $current variable.  The shape of the data that you expose in this way should, of course, match the shape of the data that you defined in the metadata definition for the templated-slot. So the a fragment from a view implementation might look a little like this: <ol>   <oj-bind-for-each data="[[employees]]">     <template>       <li>         <oj-bind-template-slot name="eachRow" data="{{$current.data}}">         </oj-bind-template-slot>       </li>     </template>   </oj-bind-for-each> </ol> In this case, the templated-slot is being used to provide the row template for a looping/stamping construct (for-each), however, note that that does not have to be the case, a templated slot can be used anywhere in your component view. Note how the data attribute of the <oj-bind-template-slot> is passed the $current.data of the forEach loop (i.e. the row contents) and that data is then made available through the data-oj-as / $current variable for the template to use.  As a best practice, the component author should also provide a default implementation of the slot, just in case the user does not supply an implementation.  So expanding the version above we might have: <ol>   <oj-bind-for-each data="[[employees]]">     <template>       <li>         <oj-bind-template-slot name="eachRow" data="{{$current.data}}">   <template data-oj-as="defaultRowImpl">   <span>   <oj-bind-text   value="[[defaultRowImpl.employeeId + ' ' + defaultRowImpl.employeeName]]">   </oj-bind-text>   </span>   </template>         </oj-bind-template-slot>       </li>     </template>   </oj-bind-for-each> </ol> So that's about it for templated-slots, a small enhancement to the Oracle JET Composite Component Architecture which adds a huge amount of flexibility and power to your custom component toolbox!  You can read more about templated-slots in the JS doc for JET and play with the demo here.  JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Architecture Learning Path 1No I won't explain how you might try and do this, you shouldn't.

In JET 5.1.0 we introduced a really exciting and useful addition to the component authors toolbox, that of templated-slots. Before I dive into the mechanics though, I'd like to discuss the kind...

JET

JET Custom Components XX - Working With Properties Safely

Introduction In this article I wanted to re-visit one of the most basic features of Composite Components, that of properties. Specifically I want to talk about properties in the context of the lifecycle. If you've been following along with this series of articles you may be thinking, hold on, we know all about properties, that was all covered way back in the first few of the series - it's about as basic as you can get right? And you'd be correct, however, there are a couple of traps which are easy to fall into and can lurk as a time-bomb in your code just waiting to catch you out. It's all, as they say, in the timing... An Illustration of the First Problem Let's look at this with a simple bit of code, you'll recognise some of this from other articles, it's meaningless but illustrates the point: define(   ['ojs/ojcore', 'knockout', 'jquery'],    function (oj, ko, $) {   'use strict'   /*    * Component constructor    */   function CoyoteTrackerComponentModel(context) {     var self = this;     self.isLoonyTunes = false;     //Parse out and store the properties     context.props.then(function (propertyMap) {        //store the properties for easy reference       self.properties = propertyMap;              //Check for a certain coyote       if (propertyMap.coyoteName !== undefined &&           propertyMap.coyoteName === 'Wile E. Coyote' ) {         self.isLoonyTunes = true;       }     });   };   /*    * Attached Lifecycle method    */    CoyoteTrackerComponentModel.prototype.attached = function(context) {      //get the length of the coyote name       var nameLen = self.properties.coyoteName.length;    }; // And so on  So what's wrong? That fragment of code seems reasonable right? Well no, and the problem comes down to the fact that the properties supplied to the component are made available in the form of a promise (props) on the context. The point about this promise is that you can't make the assumption that it will have been resolved by any particular stage of the lifecycle. I've seen this catch several developers out because of course it's not consistent. It may well be that throughout all your testing the promise has resolved in time for the self.properties value to have been set by the time that the attached (or other) phase in the lifecycle executes. However, one day it won't! And the Solution? There are a couple of basic rules that you can follow to ensure that your code is saved from this particular trap: Within your (startup) lifecycle methods, only reference properties from within the resolved promise (e.g. the then clause. The methods all have the same context passed into them that contains the props promise and it will do no harm to have multiple context.props.then() statements across the lifecycle. Outside of the lifecycle methods you should code a little defensively whenever referencing a stored reference to properties. It is possible that some of your methods (especially event handlers) might be called before the promise has resolved Just being aware of this potential timing issue is the battle here, once you have your head around the implications of this on your component startup, the rest is easy. Here's the fixed attached method   /*    * Attached Lifecycle method    */    CoyoteTrackerComponentModel.prototype.attached = function(context) {     context.props.then(function (propertyMap) {       //get the length of the coyote name *safely*       var nameLen = self.properties.coyoteName.length;   });    }; The Second Problem - External Property Changes The second timing issue as a little more subtle and frankly I doubt that most developers are likely to be effected by it. However, it can lead to similarly hard to diagnose problems and fore-warned is fore-armed. The scenario here relates to a component when some parts of your component view are bound directly to the properties observables via the $props root. e.g. <!-- ko ifnot:$props.acmeInvsibilityCloak --> <input data-bind="ojComponent : {component: 'ojInputText', value: coyoteName}"> <!-- /ko --> And you are also listening to external changes to that same property via the implicit acmeInvsibilityCloakChanged event. The question in this case is what happens first?  Does the acmeInvsibilityCloakChanged event execute before the knockout "ifnot" evaluation is completed or visa-versa?   In most cases it frankly wouldn't matter, but it is possible that whatever you are doing inside of your event handler is depending upon some side effect of the $props.acmeInvsibilityCloak update having happened, as in this case, we might want to inspect the field within that if block and so we'll need to wait until it is there. So What's the Ordering?  So in fact, if a property is changed by some external agency (e.g. the event source is external) then your *Changed event will be delivered before the $props observable is updated. So it is possible that, should you inspect the state of any UI component in your view, you will be seeing the component view in a pre-update state. This is where problems can creep in. The real solution to this particular conundrum is to re-think the problem a little.  In this case, the code that you want to execute is dependent on something happening in the UI in response to the property changing.  So, rather that having code in the property *Changed listener why not wait for the actual change that you are relying on to take place. In many cases the optionChange event on any components that you are interested will fire when the change has had a chance to take effect.  In this particular example, however, we can't use an optionChange listener directly on the component because it won't exist to attach the listener to until the knockout ifnot statement is evaluated, so i's a bit of a Catch-22 situation. We can, however, take an alternative approach which is to handle the reactive action in  when the promise returned by the JET BusyContext whenReady() function resolves which you can define in the *Changed handler. It will then get processed asynchronously after the $props observable has been updated: $(self.composite).on('acmeInvisibilityCloakChanged', function (event) { if (event.detail.updatedFrom === 'external' &&   event.detail.value = false) {   //self.composite is a reference to the CCA element obtained from the context   var busyContext = oj.Context.getContext(self.composite).getBusyContext();   busyContext.whenReady().then( function(){   //only validate once the UI has been updated to make the coyoteInput visible var coyoteFieldValid = self.coyoteInput.ojInputText('validate'); ... }); } }); Bear in mind though, that it's always better to observe the results of the property change and then act on that, rather than trying to react to the property change event itself. JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Architecture Learning Path

Introduction In this article I wanted to re-visit one of the most basic features of Composite Components, that of properties. Specifically I want to talk about properties in the context of the...

JET

JQuery Style Selectors Inside of Composite Components

I hit a bug in one of my composite components the other day which I thought I'd share with you all as I feel that it's a trap that it's all too easy to fall into. The problem in question relates to the attachment of an keyPress listener on an input field within the component.  The basic functionality I was putting in place was simply to navigate to the next field in sequence if the user pressed the "." key.  Simple enough.... The Initial Solution   As I had several input fields that would need the same handler I decided that the simplest approach would be to use a JQuery selector based on a style class to apply listeners to each of the applicable fields rather than iterating through each one in turn.  $('.svi-segment').keypress(function (event) {...} This worked perfectly - job done, or so I thought.  Problem and Resolution Fast forward a few days, and I was testing the component in a situation where several instances where on the same page. It was then that I realized my mistake.  The CSS class I was using was of course unique to the composite component, so when used in the context of just one instance of the component on the page, its use as a selector worked as expected and just those fields that needed it had the handler attached. However, of course, when you have multiple instances of your component on the page, that component-private style-class is now common across all instances of the component.  The result of this is, that each input with the associated "svi-segment" class was getting a listener from every component instance on the page, i.e. the component that it was actually a part of and all the others as well. As you can imagine, the resulting behaviour was sub-optimal! The good news is that this is simple to fix once you are aware of it as an issue, you can use an decendent selector in combination with the class to narrow down the targets to the context of the actual component instance.  In my case this was just a tiny change to the code: //self.composite is a stored reference to the component element passed in via the context $('#'+ self.component.id + '.svi-segment').keypress(function (event) {...} The lesson here is simply to exercise a little caution when using JQuery selectors within a composite component, and even if you think that there will only ever be one copy on the page at once. Code defensively, just in case. Oh and before anyone mentions it, of course you can do all this without using JQuery to select the elements. The getElementsByClassName() API will do the trick, although again you need to start searching from the composite element as the root, rather than document, otherwise you'll end up with the same problem!

I hit a bug in one of my composite components the other day which I thought I'd share with you all as I feel that it's a trap that it's all too easy to fall into. The problem in question relates to the...

ADF

ADF - Saying No to the Change Manager

A common problem that we get asked about relates to one of the more powerful and less understood aspects of the ADF Faces framework, the Change Manager.  The Change Manager works behind the scenes to remember things for you, things like: What order are my table columns in?  How wide did I stretch that column last time I looked at this table? Which tab did I have selected when I last viewed this screen? And so on... Most of the time you don't realise that the Change Manager is doing this for you, it just happens thank you very much!  Of course where the real; power comes in is where you actually persist this memory across sessions using Meta Data Services. See Chapter 50 (Customizing Applications with MDS) and Chapter 51 (Allowing User Customizations at Runtime)  of the Oracle Fusion Middleware - Developing Fusion Web Applications with Oracle Application Development Framework in the Documentation for more information on all of this this.    The Problem  So what's the issue here?  Well it relates to the fact that the Change Manager is sometimes a little over enthusiastic in what it remembers. A common example is where you always want to enter a task flow and show the first tab in a tab-set to the user. However, the Change Manager remembers that the user has been here before and dutifully sets things up so that the last tab that the user visited on the last trip through this task flow is the one that is displayed.  Sometimes this just does not meet the requirements of the UI.  So how do we override that?  From the perspective of using MDS, we can control what gets persisted about a view by configuring the adf-config.xml file as part of the MDS setup.  This gives you a UI through which you can indicate exactly which properties of which component should be persisted across Sessions:   But this configuration only relates to cross-session persistence, it does not effect the persistence of memory within the lifetime of a single session.  Just Say No! OK, we understand the problem, but is there anything we can do about it?  Fortunately the answer is yes, on any given component instance you can add a change filter that will be given the opportunity to inspect the change in question and decide if it should be remembered or not.  This, as you might have guessed involves creating a little code. As a sample, here's the common case where we want to not remember that a tab (showDetailItem) in a tabset has been selected (disclosed) : package oracle.adf.demo; import javax.faces.component.UIComponent; import oracle.adf.view.rich.component.rich.layout.RichShowDetailItem; import org.apache.myfaces.trinidad.change.AttributeComponentChange; import org.apache.myfaces.trinidad.change.ComponentChange; import org.apache.myfaces.trinidad.change.ComponentChangeFilter; public class RejectTabComponentChangeFilter extends ComponentChangeFilter { public RejectTabComponentChangeFilter() { super(); } public ComponentChangeFilter.Result accept(ComponentChange componentChange, UIComponent uIComponent) { if (uIComponent instanceof RichShowDetailItem && "disclosed".equals( ((AttributeComponentChange)componentChange).getAttributeName())){ return ComponentChangeFilter.Result.REJECT; } else { return ComponentChangeFilter.Result.ACCEPT; } } } Basically you create a simple class which extends the org.apache.myfaces.trinidad.change.ComponentChangeFilter and override the accept() method with your logic.  This method will be called each time that the Change Manager wishes to persist a particular property change, and it will be passed information about the change and the component that the change relates to. The return from the accept call is either ACCEPT or REJECT as you wish. In this case, I've just illustrated how a single change type on a single type of component can be filtered out, but of course you have enough information passed into the accept() method to have it check for and reject multiple change types for multiple components. How Do I use it? The last part of the puzzle is how this should be wired up. Unfortunately it does not just drop in and magically work.  To use the filter class you need to add it to each component instance that might have a change you want to veto.  To do this you can use the addComponentChangeFilter() API which is present on the base class that all the ADF components use (UIXComponentBase).  So for example:  ((UIXComponentBase)tabItem).addComponentChangeFilter(new RejectTabComponentChangeFilter()); When you call the add API is up to you, it can be part of your backing bean code for a particular view, or perhaps you would use a phase listener to more generally call the addComponentChangeFilter() for all components of a certain type on a particular view1. If you take the latter approach, you just want to take care and only add the change filter if it's not already there (remember the lifecycle phases would get called with every post-back to the page). To help with this you can check what's already installed on a particular component by calling the getComponentChangeFilters() API which will return you an array of what filters are currently applied (may be multiple). 1 Now would be a great time to read my article on using the visitTree() API to iterate though the components in a view to detect which components you want to add the change filters to.

A common problem that we get asked about relates to one of the more powerful and less understood aspects of the ADF Faces framework, the Change Manager.  The Change Manager works behind the scenes to...

JET

JET Custom Components XIX - Sub-Properties

Introduction In the recent JET 3.0 release we made a couple of small changes to the Composite Component Architecture, some of which I've already talked about within this series of articles on the topic.  One new feature that is worth an article of it's own, however,  is the new support for nested properties, also referred to as  sub-properties. As the name suggests, this provides for a way in which a defined component property can be used to encapsulate a series of child properties. I'll look at how you define sub-properties in a moment, but first of all, let's consider why they might be useful... It's All About The API On the surface, being able to define a component property / tag attribute which has sub-properties does not really seem that exciting. Functionally it does not seem to offer any more than normal properties, and to an extent that is true.  However, what sub-properties to give you is the ability to define a much more organized and cleaner API for your component.  Let's illustrate that with a small example. Here's a simple component that specifies a value property, and then three properties for translatable strings that the consumer can pass in. The idea being that they can override the default message strings baked into the component. Prior to JET 3.0 we would have exposed the translatable strings as separate properties: <my-component value="{{value}}" hint="The name of the widget you are ordering" required-message="You must enter a widget name" required-detail="Without the name of the widget we can't place an order"> Or we might have defined the translatable strings as a complex object type allowing the user to use JSON inline to define the values: <my-component value="{{value}}" translations='{"hint":"The name of the widget you are ordering", "required-message":"You must enter a widget name" "required-detail":"Without the name of the widget we can''t place an order"}'> The main problem with this latter approach is that it's very simple for the consumer to make a mistake in the JSON string and hard to diagnose when that's the case. Sub-properties allow us to define (for this example) a top level translations property with sub-properties for each of the strings that may be overridden. The consumer can then specify those values using a dot notation: <my-component value="{{value}}" translations.hint = "The name of the widget you are ordering" translations.required-message = "You must enter a widget name" translations.required-detail = "Without the name of the widget we can't place an order"}'> On the face of it, this is not really very different from the very first example where we simply had separate properties for each translatable resource. However, there are a several distinct benefits to using nested properties: The similar properties are now all grouped together into a sort of namespace, allowing you to maintain a better balance between the lengths of the property names and their descriptiveness to the user The fact that sub-properties are grouped helps the consumer to understand that they are all related, something which might not be obvious otherwise You can bind either the whole property group, or individual members, to observables in the consuming viewModel. e.g. <my-component value="{{value}}" translations="[[translations]]"> There are some additional benefits for the CCA author which I'll come to shortly, but the cleaner API that can be presented is really the key advantage in my opinion. Using Sub-Properties in your Components So let's start off by reviewing how you, as a component author, can take advantage of sub-properties. Metadata To define sub-properties within your component.json, you literally define sub-properties! Here's the definition for the example component above { "name": "my-component", "version": "1.0.0", "description": "Example Component to Illustrate Sub-Properties", "jetVersion": ">=3.0.0", "properties": { "value": { "description": "The value of the widget to edit (Required)", "type": "string", "writeback": true }, "translations": { "description": "Options for specific error messages in the component (optional)", "writeback": false, "properties": { "hint": { "description": "Hint text to show in the help bubble", "type" : string }, "requiredMessage": { "description": "The error message to show if no value is entered", "type" : string }, "requiredDetail": { "description": "The message detail to show if no value is entered", "type" : string } } } } Notes As you see we just define sub-properties by nesting a properties attribute under the parent property (translations in this case) There is no type attribute defined for the translations property as the sub-properties effectively define the shape of the object The sub-properties follow the same naming rules as top level properties, that is camel-case words are converted to hyphenated forms in the tag usage (e.g. requiredDetail → required-detail) Sub-properties can have nested sub-properties in turn. As you would expect, these are then specified in the tag using nested dot notation e.g. styling.ok-button.width="2em" Sub-properties do not directly support the definition of default values via the sub-property value attribute (see below) The user of the component will be able to set sub-properties one by one using dot notation, or they can set the value for all by assigning a value just to the parent property. However, mixing and matching will cause an error Sub-Properties and Default Values I mentioned above that sub-properties do not honour the setting of the value attribute to define a default value in case the user does not specify it on the tag. It is, however, still possible to define defaults for sub-properties, it's just that these have to be defined on the parent property itself. To do this, you specify the value of the parent property as a JSON string, defining the value of each sub-property that needs a default. For example we could update the translations property definition thus: ... "translations": { "description": "Options for specific error messages in the component (optional)", "writeback": false, "value" : {"hint" : "Enter something", "requiredMessage" : "You need a value"}, "properties": { "hint": { "description": "Hint text to show in the help bubble", "type" : string }, "requiredMessage": { "description": "The error message to show if no value is entered", "type" : string }, "requiredDetail": { "description": "The message detail to show if no value is entered", "type" : string } } ... Note: The JSON string you define in the value can identify as many of the sub-properties as you need, it does not have to supply defaults for all of them Any explicit values defined for sub-properties are merged with the defaults defined here. In other words, explicitly specifying one sub-property within the tag will not prevent the others from defaulting if they are not explicitly supplied Eventing When using sub-properties, all of the changed events for a particular top level property and it's sub-properties are delivered via the normal parent property changed event. In order to support this, the detail attribute of the event object now contains an attribute called subproperty which in turn contains the following attributes: path - a string containing the name of the sub-property that has been changed. This is formatted as path in dot notation starting from the root parent property name. Thus, if the translations hint sub-property was updated then the path would read translations.hint. Likewise if you have sub-properties within sub-properties then those names will all be chained together in the path. Example: styling.okButton.width previousValue - the old value of the sub-property value - the new value for the sub-property In the same event, the overall detail.value and detail.previousValue attributes will reflect the consolidated object including the changed sub-property. Just for illustration, here's a basic example of what such a change event handler might look like: $(self.composite).on('stylingChanged',function(event){ if (event.detail.updatedFrom === 'external'){ if (event.detail.subproperty.path === 'styling.okButton.width'){ $('#'+self.okButtonId).ojButton('widget').css('max-width', event.detail.subproperty.value); } } }); Setting Properties from Outside of the Component If your consumer wants to change the value of a sub-property after your component is loaded then they can do that in a couple of ways. Simplest of course, is to bind the tag attribute value to an observable and change the observable value. In this case the property will be automatically updated and the *Changed event fired. If, however, they want to explicitly set the value (maybe it was initially set to a literal in the page), then they need to use the setProperty() API on the element to do so. As before, you use the dot notation within the property name to specifically set the sub-property: element.setProperty('styling.okButton.width', '20em'); Note that the new getProperty(«property name») and setProperty(«property name», «value») APIs on composite components are new in 3.0 and are the preferred way of programatically changing properties after the component has been instantiated. Bound Properties and Write-Back As I've already alluded, you can assign binding expressions ({{...}}, [[...]]) to sub-properties as well as the parent property, although you should not try and bind both the parent property and one of the sub-properties at the same time of course. However, apart from that, the bindings work in exactly the same way as with normal "top-level" properties. Standards I mentioned towards the beginning of this article that one of the great benefits of sub-properties is the opportunity that it affords to clean up otherwise complex tag APIs. As you start to build real-world Composite Components you may find yourself exposing sets of properties across multiple components that are functionally similar. Therefore it makes a lot of sense to standardize your property naming using sub-properties as a tool. You want your consumers to know, for example, that if you provide a way of overriding say an error message, they should expect a parent property root of translations with sub-properties for each of the messages. The most common property roots might be something like: These are only suggestions, but the idea would be to provide a degree of consistency across all your custom components to aid feature discovery. There will always be a debate, of course, as to if a particular property "deserves" a top level property of it's own, or if it should be buried in a sub-property. The rule here would be to consider how likely the user is to want to set it. You'd not, for example, want to hide field label properties under a translations root. Label is something that the user is likely to want to override very often so put it front and centre in a property of it's own. translations - a group of properties with nested sub-properties for defining replaceable strings for messages and errors options - a group of sub-properties used for advanced and rarely used options on a component styling - a group of properties, maybe with nested sub-properties for defining style based configuration of the component, e.g. field widths and colors JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path

Introduction In the recent JET 3.0 release we made a couple of small changes to the Composite Component Architecture, some of which I've already talked about within this series of articles on the...

JET

JET Custom Components XVIII - Fields with Labels

Introduction One way in which you might want to use a Composite Component is to combine a particular type of input field and it's label into a single component. If you recall, this was actually an example that I used way back in Article I of this series. On the surface, this seems to be trivial, however, there is a small trick to getting this play nicely with oj-form-layout. Let's look at that. The Pattern In this pattern I'm making the assumption that you are using oj-form-layout to provide a responsive layout for form fields, and maybe you already have some fields in place. Meanwhile you have created a CCA that will include a label and one or more  fields that you want to be able to drop in and align correctly.  So here's an example of an existing form where we have a vanilla field and label combination: <div class="oj-form-layout"> <div class="oj-form oj-sm-odd-cols-12 oj-md-odd-cols-3 oj-md-labels-inline"> <div class="oj-flex"> <div class="oj-flex-item"> <label for="f1">Label for normal input</label> </div> <div class="oj-flex-item"> <input id="f1" data-bind="ojComponent: {component: 'ojInputText', value:someValue}"/> </div> </div> </div> </div> Step 1 - The Composite View Inside of the composite view we want to emulate the layout container <div>s that we would use for a label / field pair in a standard form. Note, however, that we omit the outer oj-flex and just use the oj-flex-item <div>s. So the CCA view might look like this: <div class="oj-flex-item"> <label data-bind="attr:{for:'ccaf1'+$unique,text:$props.label}"> </div> <div class="oj-flex-item"> <input data-bind="attr:{id:'ccaf1'+$unique}, ojComponent: {component: 'ojInputText', value:$props.value}"/> </div> Note how I'm being careful to use unique IDs as outlined in the last article. Step 2 - Using the Composite Component The key to getting the layout to work comes in this next step. When consuming the component you set the class of the component itself to oj-flex. Remember that all CCAs extend the base HTML element type and so include the id and class attributes automatically. So when using the component in our simple form it will look like this: <div class="oj-form-layout"> <div class="oj-form oj-sm-odd-cols-12 oj-md-odd-cols-3 oj-md-labels-inline"> <div class="oj-flex"> <div class="oj-flex-item"> <label for="f1">Label for normal input</label> </div> <div class="oj-flex-item"> <input id="f1" data-bind="ojComponent: {component: 'ojInputText', value:someValue}"/> </div> </div> <labeled-input-cca label="CCA Label" value="{{someOtherValue}} class="oj-flex"> </div> </div> And that's it. When we run the form, we can see, as shown here, that the fields align correctly even when a small screen size forces the labels to the top of the fields: JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path

Introduction One way in which you might want to use a Composite Component is to combine a particular type of input field and it's label into a single component. If you recall, this was actually an...

JET

JET Custom Components XVII - Beware the IDs

Introduction When developing Composite Components, we need to be careful about our element IDs, particularly when multiple instances of the component will be used on the same page. This article explores one such use case in relation to labels and input fields in form style layouts Background In the last article I discussed how you can use a Composite Component for input within the context of an oj-form layout. This article looks at forms in a slightly different way, specifically implementing a form layout within a Composite Component. What's the Problem? On the face of it there is no problem here. You can build a Composite Component that lays out a series of fields using standard JET form layout styles, for example, this might be the view for my component: <div class="oj-form-layout"> <div class="oj-form oj-sm-odd-cols-12 oj-md-odd-cols-4 oj-md-labels-inline"> <div class="oj-flex"> <div class="oj-flex-item"> <label for="name">Name:</label> </div> <div class="oj-flex-item"> <input id="name" data-bind="ojComponent: {component: 'ojInputText', value:name, required: true}"></input> </div> </div> <div class="oj-flex"> <div class="oj-flex-item"> <label for="type">Type:</label> </div> <div class="oj-flex-item"> <select id="type" data-bind="ojComponent: {component: 'ojSelect', value: type, required:true}"> <option value="string">string</option> <option value="boolean">boolean</option> <option value="number">number</option> <option value="object">object</option> <option value="array">array</option> <option value="function">function</option> </select> </div> </div> </div> </div> That all looks OK right? - we have the label tag associated with the relevant input component using the matched ids referenced by the for attribute of the label to the id attribute of the matching input. Indeed this example with work perfectly when there is only one instance of the CCA in the view. If, however, you have two instances running at once, you'll find that the layout of one of them is all messed up. In the above case, this would only be noticeable on the ojSelect field, its label would loose all styling and not show the required indicator. What's going on? Well, as you might have guessed, the problem here is down to the ids that we are referencing to manage the label to input relationship. If I have two instances of this CCA on the same screen (even if one is hidden in a dialog) I now have two fields with the id of name and two with the id of type. As you will be aware. Multiple DOM elements with the same ID are going to cause some degree of problem and in this case it manifests as a broken layout. The Fix Once you appreciate the risk for elements with an assigned id, the pattern that you can use to address it is very simple and should be used as a matter of course within your CCAs, even if you think that there will only be one instance. Step 1 - Get an Instance Identifier Recall from the article on lifecycle (No. VII in this series, linked below), that the context object that is passed into our CCA constructor includes an attribute called unique. This use-case is exactly what it is for. You can cache this value for programatic use. In your CCA constructor, just store the value of unique onto a convenient attribute on the component model. I always use unique thus: self.unique = context.unique; However, most of the time you will actually need this value in the HTML template, and the framework provides a pre-canned object for you in the form of $unique.  This can be used within your template where-ever you need to create a unique ID or ID reference. Step 2 - Generate IDs and FOR attributes Now that we know we have  the $unique variable we can re-write the problem view using the attr:{} knockout binding, thus: <div class="oj-form-layout"> <div class="oj-form oj-sm-odd-cols-12 oj-md-odd-cols-4 oj-md-labels-inline"> <div class="oj-flex"> <div class="oj-flex-item"> <label data-bind="attr:{for:'name'+$unique}">Name:</label> </div> <div class="oj-flex-item"> <input data-bind="attr:{id:'name'+$unique}, ojComponent: {component: 'ojInputText', value:name, required: true}"></input> </div> </div> <div class="oj-flex"> <div class="oj-flex-item"> <label data-bind="attr:{for:'type'+$unique}">Type:</label> </div> <div class="oj-flex-item"> <select data-bind="attr:{id:'type'+$unique}, ojComponent: {component: 'ojSelect', value: type, required:true}"> <option value="string">string</option> <option value="boolean">boolean</option> <option value="number">number</option> <option value="object">object</option> <option value="array">array</option> <option value="function">function</option> </select> </div> </div> </div> </div> With this minor change to the code, each instance of the CCA will now have a unique id = for pair generated. One point to note, however, is that this unique id may change from use to use of the same CCA instance. So if your CCA viewModel also wants to manipulate its own DOM or attach listeners based on a specific id, then again you should use the context.unique value to ensure that you get the correct element. You overall goal, however, should be to assign explicit ids to as few a number of elements that you can get away with. Selecting by class may be a better strategy for many DOM manipulation cases. Step 2 - Generate IDs and FOR attributes (For JET 4 and above) I thought that it was worth updating to this article to cover JET 4.0 and the new web-component syntax, just to keep it up to date and relevant.  There are are actually two important things to note: How we can inject a dynamic ID when using web component syntax (i.e. without data-bind="attr:{...}) Taking advantage of the new uniqueId attribute on the context Let's just talk about the second of these -  uniqueId first. Recall that earlier in this article I talked about generating the IDs for the elements within the component using $unique or context.unique as a part of a generated ID, so in the example above we used type+$unique, which would generate to something like "type_composite0".  This is fine but it has one drawback that particularly effects those writing QA tests.  This is that the generated ID is not stable, e.g. on one run of the page you might end up with type_composite0 but on a second, type_composite1.  So the IDs will be unique, but sadly not guaranteed to be stable.  The new uniqueId value on the context addresses it.  It acts as a proxy for whatever ID you assigned to the CCA instance itself, so if you had embedded the following inside of your page <my-cca id="c1">  then context.uniqueId (and $uniqueId) will contain the value "c1". This value of course will be stable and so QA test writers can rejoice. Note that if you use uniqueId within a CCA that does not have a formal ID assigned by the consumer then it will inherit the same value as context.unique, so things are guaranteed to keep working.  So onto updating our testcase above to use the new element syntax.  Rather than using data-bind="" syntax to set the IDs we can use the special attribute colon syntax which allows you to assign expressions to certain of the base HTMLElement attributes (see this page in the cookbook for more) . In this case we are interested in :for and :id. Here's the updated code, note the use of both the colon syntax and $uniqueId <div class="oj-form-layout"> <div class="oj-form oj-sm-odd-cols-12 oj-md-odd-cols-4 oj-md-labels-inline"> <div class="oj-flex"> <div class="oj-flex-item"> <oj-label :for="[['name_'+$uniqueId]]">Name:</oj-label> </div> <div class="oj-flex-item"> <oj-input-text :id="[['name_'+$uniqueId]]" value="{{name}}" required="true"></oj-input-text> </div> </div> </div>   ... </div> JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Architecture Learning Path

Introduction When developing Composite Components, we need to be careful about our element IDs, particularly when multiple instances of the component will be used on the same page. This article...

JET

JET Custom Components XVI - Components in Form Layouts

Introduction A common use for Composite Components is to create enhanced input components that address specialized use cases. A good example of this might be a specialized input component for entering IP Address formats. With this kind of component you would want to be able to use it everywhere that a normal JET input* type could be used. This article discusses the pattern that you can adopt to make this happen. What's the Problem? To illustrate this process I'm going to use an example form from a little application that I'm building. This is a wizard based UI that, guess-what, helps you to create CCAs. Here's an early version of one of the screens: This form uses a classic oj-form-layout to responsively align the fields: <div class="oj-form-layout"> <div class="oj-form oj-sm-odd-cols-12 oj-md-odd-cols-3 oj-md-labels-inline"> <div class="oj-flex"> <div class="oj-flex-item"> <label for="ccaname" data-bind="text:res.ccawEditor.nameLabel"/> </div> <div class="oj-flex-item"> <input id="ccaname" placeholder="my-component" data-bind="ojComponent: {component: 'ojInputText', value:workingCopy.name, required: true, rootAttributes: { style:'max-width:30em'}}"> </div> </div> <div class="oj-flex"> <div class="oj-flex-item"> <label for="ccaversion" data-bind="text:res.ccawEditor.versionLabel"/> </div> <div class="oj-flex-item"> <input id="ccaversion" data-bind="ojComponent: {component: 'ojInputText', value:workingCopy.version, required: true}"> </div> </div> <div class="oj-flex"> <div class="oj-flex-item"> <label for="ccajversion" data-bind="text:res.ccawEditor.jetVersionLabel"/> </div> <div class="oj-flex-item"> <input id="ccajversion" data-bind="ojComponent: {component: 'ojInputText', value:workingCopy.jetVersion, required: true}"> </div> </div> <div class="oj-flex"> <div class="oj-flex-item"> <label for="ccadesc" data-bind="text:res.ccawEditor.descriptionLabel"/> </div> <div class="oj-flex-item"> <textarea id="ccadesc" rows="6" style="resize: both;" data-bind="ojComponent: { component: 'ojTextArea', value: workingCopy.description, rootAttributes: {style:'max-width:60%'}}"></textarea> </div> </div> </div> </div> In this screen we can see a couple of version related fields. Right now these are simple ojInputText fields but I want to replace them with something a little more intelligent that would include behaviors such as validating the version according to Semantic Versioning rules and allowing range selection. So this seems like a good candidate for a Composite Component! So the Composite Component (called <ccaw-semvar-input>) is created and dropped into replace the existing version number inputs: <div class="oj-form-layout"> <div class="oj-form oj-sm-odd-cols-12 oj-md-odd-cols-3 oj-md-labels-inline"> <div class="oj-flex"> <div class="oj-flex-item"> <label for="ccaname" data-bind="text:res.ccawEditor.nameLabel"/> </div> <div class="oj-flex-item"> <input id="ccaname" placeholder="my-component" data-bind="ojComponent: {component: 'ojInputText', value:workingCopy.name, required: true, rootAttributes: { style:'max-width:30em'}}"> </div> </div> <div class="oj-flex"> <div class="oj-flex-item"> <label for="ccaversion" data-bind="text:res.ccawEditor.versionLabel"/> </div> <div class="oj-flex-item"> <ccaw-semver-input id="ccaversion" version="{{workingCopy.version}}" placeholder="1.0.0" range-selection="false" required="true"/> </div> </div> <div class="oj-flex"> <div class="oj-flex-item"> <label for="ccajversion" data-bind="text:res.ccawEditor.jetVersionLabel"/> </div> <div class="oj-flex-item"> <ccaw-semver-input id="ccajversion" version="{{workingCopy.jetVersion}}" placeholder="2.3.0" range-selection="true" required="true"/> </div> </div> <div class="oj-flex"> <div class="oj-flex-item"> <label for="ccadesc" data-bind="text:res.ccawEditor.descriptionLabel"/> </div> <div class="oj-flex-item"> <textarea id="ccadesc" rows="6" style="resize: both;" data-bind="ojComponent: { component: 'ojTextArea', value: workingCopy.description, rootAttributes: {style:'max-width:60%'}}"></textarea> </div> </div> </div> </div> Unfortunately, if you just do a straight substitution like this, then the result is not what you'd like: As you can see we have two problems, firstly we've lost the alignment with the other field labels and secondly we've lost the required indicator. Let's look at solving each of those in turn. Correcting the Alignment What we're seeing here is not a bug in the framework, it is expected behavior for cases where you are mixing non-JET components into the form layout. The solution is actually outlined within the existing cookbook demo Form Layout - Non Components. All we have to do is to apply the classes oj-label-nocomp oj-label-for-non-control to the label e.g. <div class="oj-flex"> <div class="oj-flex-item"> <label for="ccaversion" class="oj-label-nocomp oj-label-for-non-control" data-bind="text:res.ccawEditor.versionLabel"/> </div> <div class="oj-flex-item"> <ccaw-semver-input id="ccaversion" version="{{workingCopy.version}}" placeholder="1.0.0" range-selection="false" required="true"/> </div> </div> This will ensure that the labels are now correctly aligned. Adding the Required Indicator For the case of using a non-JET component, the framework supplies a class specifically for rendering the *required indicator. This class is called oj-label-required-icon. However, one thing we can't do is this: <label class="oj-label-nocomp oj-label-for-non-control oj-label-required-icon" .../> Doing so would result in this: As you can see, the required indicator is overriding both the color and font information for the label if it is applied directly. Thus the correct usage is: <label class="oj-label-nocomp oj-label-for-non-control" style="display: inline-block;" for="ccajversion"> <span class="oj-label-required-icon oj-component-icon"/> <span data-bind="text:res.ccawEditor.jetVersionLabel"/> </label> Here we have done two things: Moved the oj-label-required-icon into it's own span to limit its influence and set the oj-component-icon class as well Set display:inline-block; on the containing label component. This ensures that the required indicator will remain correctly aligned with the label text even when the form layout re-locates the label to above the field in small screens With these small changes to the label styles the layout and responsiveness of your oj-form-layouts will return and you can mix in your composite components at will. Here's the fixed form: And when resized to SM screen size to force a label move JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path

Introduction A common use for Composite Components is to create enhanced input components that address specialized use cases. A good example of this might be a specialized input component for entering...

JET

JET Custom Components XV - Translations

Introduction Once you start to get serious about building truly reusable components, the issue of language support will come to the fore. The JET components that you use within your CCA will of course do the right thing based on the language and locale settings of the application, however, what about your own resources? Background on Translatable Strings in JET In the context of a JET application, an application developer will usually define translatable resources using the following steps: Create a /resources/nls folder under /js Create one subfolder under this nls folder for each supported language / region Define the default bundle with a particular name (e.g. myappstrings.js) in the /nls folder Define corresponding translated versions of myappstrings.js in each language subdirectory Configure the requirejs ojL10n plugin to merge the custom bundle (myappstrings.js) with the built-in JET bundles This is all covered in detail in the documentation. Reading this, however, you might notice two particular issues which have a direct bearing on Composite Components.   The configuration of the application bundle merging is done within the main application code (usually main.js) You can actually only merge one custom bundle into JET Both of these restrictions make it impossible for a Composite Component to magically merge its strings into the default JET bundle for access via oj.Translations.getTranslatedString() and oj.Translations.gerResource(). So what should you do? Steps to Apply Translations to Your Composite Components Defining Your Bundles I'd recommend that you define a single resource bundle file for your Composite component, there would be little need to have more that one. The base bundle in your default language should be placed in a suitable subdirectory of your composite component. To keep things consistent, I'd recommend using /resources/nls as the subdirectory. This /nls directory would then contain further subdirectories for the required language / region combinations. Thus, should your component support english as the base language, along with german and french you might end up with the following folders and files: /js /jet-composites /acme-coyote-tracker loader.js acme-coyote-tracker.json acme-coyote-tracker.html acme-coyote-tracker.css acme-coyote-tracker.js /resources /images paintedDesert.png /nls acme-coyote-tracker-strings.js /de acme-coyote-tracker-strings.js /fr-FR acme-coyote-tracker-strings.js The actual formatting of the translation bundles will be exactly the same as that shown in the doc for the main application bundles. Referencing Your Resources Once you have the bundles set up, you can still use default JET functionality to do the heavy lifting for you and to load the correct bundle for the current language in use (be that based on the HTML lang setting or oj.Config.setLocale()). In your Composite Component viewModel script, simply inject the bundle using the define block with the ojL10n plugin. For example: define( ['ojs/ojcore','knockout','jquery', 'ojL10n!./resources/nls/acme-coyote-tracker-strings' ], function (oj, ko, $, coyoteTrackerStrings) { 'use strict'; function CoyoteTrackerComponentModel() { var self = this; self.res = coyoteTrackerStrings; .... }; return CoyoteTrackerComponentModel; }); Note how the bundle is mapped to a variable called self.res via the injected coyoteTrackerStrings. This can then be referenced by the Composite Component viewModel or directly by the composite view itself: <h1 data-bind="text:res.coyotetracker.pageTitle"></h1> ... <input data-bind="attr:{placeholder:res.coyotetracker.coyoteName.placeholder}, ojComponent : {component: 'ojInputText', value: coyoteName, required: true, translations: { 'required': { messageSummary: res.coyotetracker.nameRequiredMessage, messageDetail: res.coyotetracker.nameRequiredDetail } } }"> </input> Managing Strings with Substitution You'll note that because you have direct access to the string bundle via the injected reference, you don't need to access the string through the oj.Translations.getTranslatedString() API. That's good because your code is somewhat less verbose, however, what about the token substitution feature of that API? Fortunately, this feature is available separately through the oj.Translations.applyParameters(pattern, parameters) API. So you can still manage your token substitutions without having to write a separate function to do so. JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path

Introduction Once you start to get serious about building truly reusable components, the issue of language support will come to the fore. The JET components that you use within your CCA will of course...

JET

JET Custom Components XIV - A Pattern for Multi-view Components using ojModule

Introduction In general, one would expect components to be fairly limited in scope and only have to define a single UI (albeit one that might be reasonably dynamic as discussed in this previous article). However, the occasion may arise where the component needs to be more complex and maybe needs some scoped sub-views. A good example of this might be a wizard-style UI in which you need to encapsulate several distinct "pages" to step though, into a single component. This article outlines an approach you can take to implementing this kind of Composite Component by leveraging the capabilities of JET modules (ojModule). I would emphasize that this approach is only needed when your sub-views within the Composite Component all need their own viewModels. If all you want to do is define a number of views all based off of the Component viewModel then you can stick to Knockout templates to switch the UI. Note this article has been updated for JET version 3.1.0 and above, where this all got easier - so make sure that you follow the parts of the article that match the version you are using. What's The Problem? For this scenario I want to package up the module views and viewModels as part of the Composite Component. So for example I might have the following file structure: /js /jet-composites /ccdemo-wizard loader.js component.json ccdemo-wizard.js ccdemo-wizard.css ccdemo-wizard.html /modules /views ccdemo-wizard-page1.html ccdemo-wizard-page2.html ccdemo-wizard-page3.html /viewModels ccdemo-wizard-page1.js ccdemo-wizard-page2.js ccdemo-wizard-page3.js Normally when using ojModule, the location of the views and viewModels for a named module are global to the application and defined by convention as /js/views and /js/viewModels respectively. Now obviously, a particular Composite Component cannot go around changing the default load locations for modules, that would possibly break the consuming application. So we need to find a way to direct ojModule to load each wizard page from within the Composite Component folder structure. As well as that requirement, we need to ensure that the life-span of each viewModel that makes up the wizard pages matches that of the Composite Component as a whole and that we can successfully use multiple instances of the component concurrently without running into problems. Versions Post 3.1.0 - The Approach JET 3.1.0 made this use case really simple to implement. In versions prior to 3.1.0, ojModule always loaded the views and viewModels from a hardcoded location defined by the main application. As of this version, however, you can now directly specify the locations of both the view and the viewModel used by the module as part of the module configuration.   Let's step through the process. (>=3.1.0) Step 1 - Define the Core Composite Component To illustrate this I'll start off with a basic component called ccdemo-wizard here's the metadata: { "name":"ccdemo-wizard", "version" : "1.0.0", "jetVersion":">=2.2.0", "events" : { "wizardCancelled": { "description" : "Called if the user presses the Cancel button in the wizard", "bubbles" : true, "cancelable" : false }, "wizardComplete": { "description" : "Called if the user presses the Finish button in the wizard", "bubbles" : true, "cancelable" : false } } } As you can see it's pretty simple and really only defines two events to allow the consumer to detect the overall state of the wizard. The component will also have a very standard loader script (loader.js) and style sheet (ccdemo-wizard.css). There is nothing unusual about these so I've not reproduced them here. (>=3.1.0) Step 2 - The Component View Template Next, the HTML template for the Composite Component itself (ccdemo-wizard.html). This just contains a module binding and the buttons to control the paging though the wizard and to raise the wizardCancelled or wizardFinished events: <div class="oj-panel-alt5"> <div data-bind="ojModule: wizardModuleSettings"/> <div> <button data-bind="click: previousPage, enable : previousEnabled">Previous</button> <button data-bind="click: nextPage, enable : nextEnabled">Next</button> <button data-bind="click: cancelWizard">Cancel</button> <button data-bind="click: finshWizard">Finish</button> </div> </div> So the key thing here is the <div> with the data-bind to ojModule. This binds the ojModule to an object called <strong>wizardModelSettings</strong> in the Composite Component viewModel (>=3.1.0) Step 3 - The Composite Component ViewModel I'll start off by listing the code for the Composite Component viewModel and then I'll break down each part: define(['ojs/ojcore','knockout','jquery', './modules/viewModels/ccdemo-wizard-page-1', './modules/viewModels/ccdemo-wizard-page-2', './modules/viewModels/ccdemo-wizard-page-3', 'text!./modules/views/ccdemo-wizard-page-1.html', 'text!./modules/views/ccdemo-wizard-page-2.html', 'text!./modules/views/ccdemo-wizard-page-3.html', 'ojs/ojmodule' ], function (oj, ko, $, Page1Model, Page2Model, Page3Model, page1View, page2View, page3View) { 'use strict'; function CCDemoWizardComponentModel(context) { var self = this; self.composite = context.element; self.currentPage = ko.observable(1); self.pageArray = [{model:Page1Model,view: page1View}, {model:Page3Model,view: page2View}, {model:Page3Model,view: page3View}]; self.wizardModuleSettings = ko.computed(function(){ return {viewModel:self.pageArray[self.currentPage()].model, view: self.pageArray[self.currentPage()].view}   }); self.nextEnabled = ko.pureComputed(function(){ return self.currentPage() < 3; }); self.previousEnabled = ko.pureComputed(function(){ return self.currentPage() > 1; }); }; CCDemoWizardComponentModel.prototype.cancelWizard = function(viewModel, data){ var eventParams = {'bubbles' : true,'cancelable' : false}; this.composite.dispatchEvent(new CustomEvent('wizardCancelled',eventParams)); }; CCDemoWizardComponentModel.prototype.finshWizard = function(viewModel, data){ var eventParams = {'bubbles' : true, 'cancelable' : false}; this.composite.dispatchEvent(new CustomEvent('wizardComplete',eventParams)); }; CCDemoWizardComponentModel.prototype.nextPage = function(viewModel, data){ this._changePage(this.currentPage() + 1); }; CCDemoWizardComponentModel.prototype.previousPage = function(viewModel, data){ this._changePage(this.currentPage() - 1); }; CCDemoWizardComponentModel.prototype._changePage = function(pageNo){ this.currentPage(pageNo); }; return CCDemoWizardComponentModel; }); Let's break that down:... Module viewModel Imports in the Define Block The first thing that this model does is to define the viewModels for each of the separate modules that will make up the wizard (three in all). By using the define block in this way, we are automatically loading the files (e.g. ccdemo-wizard-page-1.js) from a location relative to the Composite Component Folder, rather than from the default module location of /js/viewModels. Each viewModel constructor for the modules is being mapped into the main function block as Page1Model, Page1Model etc. These can be totally standard ojModule viewModels. Module view Imports in the Define Block Just like the viewModels we use the define block to read all the view HTML streams using the text plugin. In this use case we're assuming that all the pages care going to be visited so are loading everything. If you wanted to defer the loading of the HTML you could do so using a defined createViewFunction in the module ViewModels - but that's a topic for another article. The views and associated viewModels are then stashed into an array for ease of access via the selected currentPage. Set up a currentPage Observable We'll need to keep track of which "page" and therefore module, should be displayed. This is done by creating the currentPage observable, set initially to the value 1 Defintion of wizardModuleSettings This knockout computed function just returns a configuration for the module based on the selected currentPage. As currentPage changes then the wizardModuleSettings will recompute and the newly selected module will be swapped in. And that's it... Versions Prior to 3.1.0 - The Approach The approach I'm recommending in these older versions of JET (before ojModule supported the direct definition of view and viewModel),  fulfils all of these requirements by taking advantage of the viewModelFactory capability of ojModule. The use of a factory to create the viewModel for a particular module is then coupled with a facility, also supported by ojModule, for a modules viewModel to expose a method to generate or otherwise obtain the view portion dynamically. Using these two capabilities together we can load the view and viewModels we want to use from anywhere, including within the Composite folder structure. Let's step through the process. (<3.1.0) Step 1 - Define the Core Composite Component To illustrate this I'll start off with a basic component called ccdemo-wizard here's the metadata: { "name":"ccdemo-wizard", "version" : "1.0.0", "jetVersion":">=2.2.0", "events" : { "wizardCancelled": { "description" : "Called if the user presses the Cancel button in the wizard", "bubbles" : true, "cancelable" : false }, "wizardComplete": { "description" : "Called if the user presses the Finish button in the wizard", "bubbles" : true, "cancelable" : false } } } As you can see it's pretty simple and really only defines two events to allow the consumer to detect the overall state of the wizard. The component will also have a very standard loader script (loader.js) and style sheet (ccdemo-wizard.css). There is nothing unusual about these so I've not reproduced them here. (<3.1.0) Step 2 - The Component View Template Next, the HTML template for the Composite Component itself (ccdemo-wizard.html). This just contains a module binding and the buttons to control the paging though the wizard and to raise the wizardCancelled or wizardFinished events: <div class="oj-panel-alt5"> <div data-bind="ojModule: wizardModuleSettings"/> <div> <button data-bind="click: previousPage, enable : previousEnabled">Previous</button> <button data-bind="click: nextPage, enable : nextEnabled">Next</button> <button data-bind="click: cancelWizard">Cancel</button> <button data-bind="click: finshWizard">Finish</button> </div> </div> So the key thing here is the <div> with the data-bind to ojModule. This binds the ojModule to an object called wizardModelSettings in the Composite Component viewModel. (<3.1.0) Step 3 - The Composite Component ViewModel I'll start off by listing the code for the Composite Component viewModel and then I'll break down each part: define(['ojs/ojcore','knockout','jquery', './modules/viewModels/ccdemo-wizard-page-1', './modules/viewModels/ccdemo-wizard-page-2', './modules/viewModels/ccdemo-wizard-page-3', 'ojs/ojmodule' ], function (oj, ko, $, Page1Model, Page2Model, Page3Model) { 'use strict'; function CCDemoWizardComponentModel(context) { var self = this; self.composite = context.element; self.currentPage = ko.observable(1); self.pageArray = [new Page1Model(this), new Page2Model(this), new Page3Model(this)]; self.wizardModuleSettings = ko.observable( {createViewFunction:'resolveModuleView', viewModelFactory: self.modelFactory}); self.modelFactory = { createViewModel: function(params, valueAccessor){ return Promise.resolve(self.pageArray[self.currentPage()-1]); }}; self.nextEnabled = ko.pureComputed(function(){ return self.currentPage() < 3; }); self.previousEnabled = ko.pureComputed(function(){ return self.currentPage() > 1; }); }; CCDemoWizardComponentModel.prototype.cancelWizard = function(viewModel, data){ var eventParams = {'bubbles' : true,'cancelable' : false}; this.composite.dispatchEvent(new CustomEvent('wizardCancelled',eventParams)); }; CCDemoWizardComponentModel.prototype.finshWizard = function(viewModel, data){ var eventParams = {'bubbles' : true, 'cancelable' : false}; this.composite.dispatchEvent(new CustomEvent('wizardComplete',eventParams)); }; CCDemoWizardComponentModel.prototype.nextPage = function(viewModel, data){ this._changePage(this.currentPage() + 1); }; CCDemoWizardComponentModel.prototype.previousPage = function(viewModel, data){ this._changePage(this.currentPage() - 1); }; CCDemoWizardComponentModel.prototype._changePage = function(pageNo){ this.currentPage(pageNo); this.wizardModuleSettings.valueHasMutated(); }; return CCDemoWizardComponentModel; }); Let's break that down:... Module viewModel Imports in the Define Block The first thing that this model does is to define the viewModels for each of the separate modules that will make up the wizard (three in all). By using the define block in this way, we are automatically loading the files (e.g. ccdemo-wizard-page-1.js) from a location relative to the Composite Component Folder, rather than from the default module location of /js/viewModels. Each viewModel constructor for the modules is being mapped into the main function block as Page1Model, Page1Model etc. We'll look at the definition of those classes in a moment. Set up a currentPage Observable We'll need to keep track of which "page" and therefore module, should be displayed. This is done by creating the currentPage observable, set initially to the value 1 Create Instances of Module viewModels Next we create the array pageArray which will hold a concrete instance of a viewModel for each of the modules that can be loaded into the wizard. Notice how a reference to the main Composite Component viewModel is passed as a this reference into the constructor for each veiwModel. This will allow communication between the page module and the component as a whole. Note that you could of course make this instantiation lazy should you want to, I've just gone for simple and clear in this example. Defintion of wizardModuleSettings The wizardModuleSettings object is the object being reference from the data-bind statement for the module. Its job is to configure the ojModule using the available options. In this case we are specifying two key bit of information: A viewModelFactory to tell ojModule how to obtain an instance of the viewModel for the module createViewFunction to tell ojModule the name of a function to call in the supplied module viewModel to obtain the matching view for the module You could define other settings here as well (except name and viewName which we have removed the need for by sourcing the information via the factory). Notice how the wizardModuleSettings variable is defined as a knockout observable. This is important because we want to have a way to automatically refresh the ojModule binding to switch pages as we step through the wizard - we'll see how that is done in a moment. Defintion of the Factory The viewModelFactory property of the wizardModuleSettings is pointing to the next object defined in this class: modelFactory. The expectation is that whatever object is pointed to by viewModelFactory should provide a method call called createViewModel. This object and method will be called to create / obtain the new viewModel to use for the module. We already have an array of possible viewModels ready to go in the pageArray, so all my factory createViewModel method has to do is to select the correct one based on the value of the currentPage and return it. The framework expects the return value from the createViewModel to be a promise, so we just wrap the correct viewModel instance for the correct page up in one using Promise.resolve(...). The fact that a promise is expected here is actually useful as it means that you could, as a variation to the pattern, dynamically load a viewModel using require() and still have it all work. And the Rest There is, in fact, not an awful much more of interest in the Composite Component viewModel. The remaining functions shown are all concerned with either raising the supported events or managing the navigation through the pages. The one remaining bit to discuss though is inside of the _changePage() function which is called when moving forward or backwards through the set of pages. Note how this calls valueHasMutated() on the wizardModuleSettings observable. Although the actual values inside of that object have not changed at all, by telling knockout that it has changed the data-bind for the ojModule will be re-evaluated and the correct module loaded in the process. (<3.1.0) Defining the moduleViewModels So, we have injected constructors for each of the wizard pages into the Composite Component viewModel. Each of these viewModels will of course have their own settings internally depending on the data that they need to deal with. However, they will all have to share the same essential backbone. I'll use the Page1Model to illustrate this: define(['ojs/ojcore','knockout','jquery','text!../views/ccdemo-wizard-page-1.html' ], function (oj, ko, $, moduleView) { 'use strict'; function CCDemoWizardPage1ViewModel(componentVMRef) { var self = this; self.parentComponentVM = componentVMRef; }; CCDemoWizardPage1ViewModel.prototype.resolveModuleView = function() { return moduleView; }; return CCDemoWizardPage1ViewModel; }); Injection of the Module View In the define block for this class, I inject the relative location of the matching HTML template for the module. In this case, the location will be relative to this viewModel script. This view is loaded using the requirejs text plugin and stored in the moduleView parameter. Constructor Function Defintion Recall from main Composite Component viewModel listing, that we instantiate instances of each module viewModel, passing in a back-reference to the Composite Component viewModel in the process. This is so that the wizard page can write state back to the main component if needed. Accordingly, we need to add a parameter to its viewModel constructor CCDemoWizardPage1ViewModel(componentVMRef). This is the stored in parentComponentVM for later use. Defintion of resolveModuleView Function The configuration that we passed to ojModule specified a value for createViewFunction which I hardcoded to the string 'resolveModuleView'. This means that the framework will try and call a function with this name in the supplied viewModel, so we just need to implement that. Fortunately this function can be really simple because requireJS has already done the hard work to load the view HTML for us. We just need to return the moduleView parameter populated by requireJS. (<3.1.0) That's It So you now have the core pattern to follow if you need to create these sorts of multi-module Composite Component. There are, of course, many possible variations in the way that this pattern can be used or adapted, however, the basic use of the ojModule viewModelFactory is going to be a key part of any such strategy. JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path

Introduction In general, one would expect components to be fairly limited in scope and only have to define a single UI (albeit one that might be reasonably dynamic as discussed in this previous...

JET

JET Composite Components XIII - Patterns for Deferred and Asynchronous UI Loading

Introduction This article outlines a series of simple approaches that you can use in Custom JET Components that do not have a fixed user interface. These might be UIs that are generated or altered dynamically based on the attributes defined for the component tag, or maybe based on data that the component itself is retrieving from a remote service as it starts up. In the article I will outline three basic patterns in order of complexity: Pattern 1 - Simple Conditional and Looping based UIs Pattern 2 - Consolidated Template based UIs Pattern 3 - Separately Templated UIs In all cases, the view that ends up being used for the component shares the same basic component viewModel. All we are doing here is making the UI part a little more dynamic. These approaches can be useful when you want to display alternate views based on data that you simply don't have when the component is defined. For example, you may need the view to be sensitive to the runtime user role, the particular shape of a collection being displayed or even the type of device being used. Note that the patterns explained here can actually be blended together in various ways as well. Pattern 1 - Simple Conditional and Looping based UIs The pattern 1 approach simply leverages the power of basic conditional syntax to dynamically vary the UI. Specifically you can use conditional and looping constructs <oj-bind-if>, <oj-switch> and <oj-bind-for-each> within the basic view that you define for the component. The framework will automatically resolve these as the component has it's bindings applied. As a simple example to illustrate this, imagine that I have a component where I want to support two display modes for the consumer to be able to select from compact or full. To do this I could expose a compactView boolean property in my Custom Component metadata: { "properties": { …, "compactView": { "description" : "Hides the First-Name if set to TRUE, defaults to FALSE", "type": "boolean", "value" : false } }, … } Then the consumer can set the value to true if needed, thus: <ccdemo-name-badge compact-view="true" badge-name="..."/> Then in my component view definition, ccdemo-name-badge.html I could use a <oj-bind-if> test to only display the first name data if the mode is not compact: <div class="badge-face"> <img class="badge-image" :src="[[$props.badgeImage]]" :alt="[[$props.badgeName]]"/> <oj-bind-if test="[[$props.compactView !== true]]> <h2><oj-bind-text value="[[upperFirstName]]"></oj-bind-text></h2> </oj-bind-if> <h3><oj-bind-text value="[[$props.badgeName]]"></oj-bind-text></h3> </div> Pattern 2 - Consolidated Template Based UIs Leading on from the basic use of  inline tag base evaluation in the view HTML, we can take the logical next step of using the full Knockout template mechanism. The simplest version of this would be to define the alternative view templates inline in the base view HTML for the component. To show this, I'll use the same component compactView boolean property as before. The big alteration is in the component view definition (ccdemo-name-badge.html): <div class="badge-face" data-bind="template: { name: viewModeTemplate}"/> <!-- Templates follow in-line --> <script type="text/html" id="compactTemplate"> <img class="badge-image" :src="[[$props.badgeImage]]" :alt="[[$props.badgeName]]"/> <h3><oj-bind-text value="[[$props.badgeName]]"></oj-bind-text></h3> </script> <script type="text/html" id="fullTemplate"> <img class="badge-image" :src="[[$props.badgeImage]]" :alt="[[$props.badgeName]]"/> <h2><oj-bind-text value="[[upperFirstName]]"></oj-bind-text></h2> <h3><oj-bind-text value="[[$props.badgeName]]"></oj-bind-text></h3> </script> In this version of the HTML you can see that the main bulk of the component markup has been removed from the outer <div> and instead it has gained a template data-binding that uses a viewModel value called viewModeTemplate. Additionally, the HTML has gained two scripts of type html/text called compactTemplate and fullTemplate respectively (based on their id attribute). These two scripts1 provide two alternative user interfaces that can be substituted into the main <div>. The final ingredient to make this pattern work is the implementation of the viewModeTemplate property in the custom component viewModel. The Knockout template evaluation will expect this to contain a string which matches one of the available templates (e.g. "compactTemplate" or "fullTemplate"). In my example I'm triggering the change based on a boolean attribute called compactView. So in the property resolution for the component I can add a little logic to inspect that boolean value and store the appropriate template name into a property called viewModelTemplate. Here's the property resolution block2 with this added. … function CCDemoNameBadgeComponentModel(context) { var self = this; context.props.then(function(propertyMap){ //Save the resolved properties for later access self.properties = propertyMap; //Extract the badge-name value var badgeNameAttr = propertyMap.badgeName; self._extractFirstName(badgeNameAttr); //New code to select the correct template to use var compactMode = propertyMap.compactView; if (compactMode){ self.viewModeTemplate = 'compactTemplate'; } else { self.viewModeTemplate = 'fullTemplate'; } }); … Pattern 3 - Separately Templated UIs The final variation is naturally the most powerful but does involve a little more code. In this version, we'll still use the Knockout template mechanism, but rather than encoding the different template options into <script> tags within the view HTML we instead define totally separate HTML files for each UI variant desired. Using this approach we can actually remove the need for a placeholder HTML file and instead in-line that into the bootstrap loader.js. So in terms for files for our running sample composite component we might end up with: /ccdemo-name-badge loader.js ccdemo-name-badge.json ccdemo-name-badge.js ccdemo-name-badge.css ccdemo-name-badge-compact.html ccdemo-name-badge-full.html Next we make a slight alteration in the boostrap component.js so as to not inject an initial HTML view via the RequireJS text plugin: define(['ojs/ojcore', './ccdemo-name-badge','text!./ccdemo-name-badge.json', 'css!./ccdemo-name-badge', 'ojs/ojcomposite'], function (oj, ComponentModel, metadata, css) { 'use strict'; oj.Composite.register('ccdemo-name-badge', { metadata: JSON.parse(metadata), viewModel: ComponentModel, view: "<!-- ko template: {'nodes' : templateForView} --><!-- /ko -->" }); } ); Notice in the view property of the register() parameters I'm now injecting an HTML string directly and this encodes just a Knockout template reference. You'll also notice that this then supplies the nodes property of the template, not the name. (for more information about this see the Knockout doc). Injecting this HTML inline in this way simply removes the requirement to define a separate HTML file which would need to loaded in the define block as per the previous examples we've seen3. Next we need to contrive how to get hold of the two possible template files within the component viewModel. The simplest approach here is to inject them through the define() block of the viewModel (although you could load them in other ways too, e.g. using require()). So amending our ccdemo-name-badge.js define block gives: define(['ojs/ojcore','knockout','jquery', 'text!./ccdemo-name-badge-compact.html', 'text!./ccdemo-name-badge-full.html' ], function (oj, ko, $,compactTemplate,fullTemplate) { 'use strict'; … Notice how the two HTML text streams are injected into the define function block as compactTemplate and fullTemplate respectively. With this pattern, there is one more thing to do which is to set up the templateForView property that Knockout is expecting to contain the element subtree used to implement the template. We do this using the activated lifecycle method in the Composite Component. This will check our compactMode boolean property and then use the ko.utils.parseHtmlFragment() API to convert the correct template text stream into the subtree that Knockout expects: CCDemoNameBadgeComponentModel.prototype.activated = function(context) { if (this.properties.compactMode){ this.templateForView = ko.utils.parseHtmlFragment(compactTemplate); } else { this.templateForView = ko.utils.parseHtmlFragment(fullTemplate); } }; There are many variations of this final pattern that you could use, including building a completely dynamic UI with no source HTML files on disk at all. What's Next? In the next article I take the idea of dynamic CCA content one step further by showing you how a custom component can use ojModule to present multiple views, each with their own viewModel. JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path 1 Of course you are not restricted to just two alternative templates here, you can use as many as you like. 2 This is all using the same sample that I've been working with throughout this series of articles. Jump back to Part II if you've not encountered it before. 3 This does not stop you from doing so, however, it just depends on how you want to organize your code.

Introduction This article outlines a series of simple approaches that you can use in Custom JET Components that do not have a fixed user interface. These might be UIs that are generated or...

JET

JET Custom Components XII - Revisiting the Loader Script

Introduction Just to complete the core set of technical articles on custom components, before I move onto the more use-case driven topics, I wanted to revisit the loader script. Recall that way back in Part II of the series I mentioned that the the loader script was mostly boilerplate and unchanging apart from perhaps the injected script names? Well that's certainly mostly true, but there are some tweaks and advanced options to discuss before we can say that the topic is totally complete. So here I want to look at three things: Custom property parsing Options for Register Configuration Properties Loading remote modules Note there have been some significant changes in this area for JET 5.0.0 and above. I have left this article intact for historical reference and for those of you working on older versions but do note the following and amend your coding appropriately if you are using JET 5+ The register command no longer needs to take an object with an inline or promise attribute. The promise option has been removed all together and so techniques using that will not work in JET 5.0.0 or above Custom Property Parsing One of the advanced capabilities of the loader script is to supply a custom parsing function for properties as part of the oj.Composite.register(...) call. I've included a mention of it for completeness, however, it was the subject of a whole article on it's own, so if you need to learn about this, jump back to Part X to read all about it. Options for Register Configuration Properties If we look at a typical loader script, you will note that the various configuration properties for the composite are marked with inline here for example is the one that I've been using throughout this series for the ccdemo-name-badge component. define( ['ojs/ojcore', './ccdemo-name-badge', 'text!./ccdemo-name-badge.html', 'text!./ccdemo-name-badge.json', 'css!./ccdemo-name-badge', 'ojs/ojcomposite'], function (oj, ComponentModel, view, metadata) { 'use strict'; oj.Composite.register('ccdemo-name-badge', { metadata: {inline: JSON.parse(metadata)}, viewModel: {inline: ComponentModel}, view: {inline: view} }); } ); The use of inline here simply indicates to the framework that the value for the property is right here and no promise resolution is required to use it. You can also literally define the property contents "inline" should you wish, although the readability of your definition might suffe. That aside, the implication is that the various values for these configurations do not have to be supplied via the define block. If you want to obtain your viewModel (for example) in some other way, say using a factory, then that would be fine. In an extreme case we might not use the define block for any direct injection at all: define( ['ojs/ojcore', 'plugins/ModelFactory' 'ojs/ojcomposite'], function (oj, factory) { 'use strict'; var metadata = {"name" : "ccdemo-name-badge", "version" : "1.0.0", ...}; var viewHTML = '<div><h2>Test Composite</h2>...'; oj.Composite.register('ccdemo-name-badge', { metadata: {inline: metadata}, viewModel: {inline: factory.makeModel()}, view: {inline: viewHTML} }); } ); I'd really not encourage over-use of the loader script in this way, unless the configurations are super simple, otherwise things just get hard to read and you may breat compatibility with any future tooling that is expecting a more standard file layout format. But the principle stands, that the register() API configuration properties are not magical, you can populate them in any way that you choose. The use of factories for creating the viewModels and views may be the most likely type of deviation from the standard pattern. To help support this further, the register() API configuration properties can also be provided as {promise:...} as an alternative to {inline:...}. As you would expect, this instructs the CCA that the value for the property is supplied as a promise and internally it will wait for the promise to resolve before the registration is completed. So for example we might use the requireJS require() API to load a view from some dynamic location 1: var viewPromise = new Promise( function(resolve, reject){ var viewLocation = '/js/random/'; require(['text!' + viewLocation + 'ccdemo-name-badge.html'], function(resolvedView){ resolve(resolvedView); };); }); oj.Composite.register('ccdemo-name-badge', { metadata: {inline: JSON.parse(metadata)}, viewModel: {inline: ComponentModel}, view: {promise: viewPromise} }); It goes without saying that you should not define both inline:... and promise:... for the same configuration property. Remote Module Loading On the subject of the loading of component constituents, ie the view, viewModel etc., we need to think about the case where loading is remote to the consuming application. As a matter of course, your loader script (e.g. ccdemo-name-badge/loader.js in my case) should load all of it's resources using relative paths in the loader define block. This is what we have been doing all along. By sticking to relative paths in the loading, the only requireJS configuration needed on the part of the consumer is to define the home / root location of the Composite Component. Right? Well almost. That's fine if the component has been sucked into the consuming application codebase. If you wanted to load the component from a remote location, however, for example a CDN, then here is one additional piece of configuration for the consumer. This is actually nothing to do with the CCA per say, but rather relates to the default behavior of requireJS when loading from separate origins 2. By default, the requireJS text plugin will, as a security measure, not allow resources (such as the view and metadata) to be fetched. Only .js files will work from a different origin. To fix this is a simple configuration task in the requireJS configuration of the consuming application. The configuration for the text plugin should define a useXhr function to return true for the source server for the component. Here's an example requireJS configuration for an application that implements the most general version of this: requirejs.config( { baseUrl: 'js', // Path mappings for the logical module names paths: { 'knockout': 'libs/knockout/knockout-3.4.0.debug', 'jquery': 'libs/jquery/jquery-3.1.0', 'jqueryui-amd': 'libs/jquery/jqueryui-amd-1.12.0', 'promise': 'libs/es6-promise/es6-promise', 'hammerjs': 'libs/hammer/hammer-2.0.8', 'ojdnd': 'libs/dnd-polyfill/dnd-polyfill-1.0.0', 'ojs': 'libs/oj/v2.2.0/debug', 'ojL10n': 'libs/oj/v2.2.0/ojL10n', 'ojtranslations': 'libs/oj/v2.2.0/resources', 'text': 'libs/require/text', 'css' : 'libs/require-css/css', 'signals': 'libs/js-signals/signals' }, // Shim configurations for modules that do not expose AMD shim: { 'jquery': { exports: ['jQuery', '$'] } }, , //Additional Configuration config: { text: { useXhr: function (url, protocol, hostname, port) { // Allow cross-domain requests to get Text resources // Remote server must set Access-Control-Allow-Origin header return true; } } } } ); Note the implementation here is wide open because it blindly returns true from the useXhr function. In reality the consumer should only return true if the load is from a trusted source as determined from the supplied hostname etc. What's Next? Over the past 12 articles I've covered the core knowledge-base needed to create your own JET Custom Components to quite a sophisticated level. The following articles in this series are more focused on examining specific use cases and techniques that I've encountered when working with this technology. The next article will specifically be looking at how to create User Interfaces within your components on the fly rather than having them all pre-defined as part of the component definition. JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path 1 Note that I'm not recommending this as a way to dynamically load variable views, that's a subject of the next article. 2 I should point out that this is in addition to any CORS configuration.

Introduction Just to complete the core set of technical articles on custom components, before I move onto the more use-case driven topics, I wanted to revisit the loader script. Recall that way back in...

JET

JET Custom Components XI - Metadata Extensibility

Introduction In previous articles in this series, I have discussed some of the ways in which you can extend or override the Composite Component Framework. These include the overriding of lifecycle method callback names (not recommended and no longer supported) and custom property parsing (very useful but rare). Additionally, of course you have the lifecycle methods themselves as a place to carry out the internal operations of your components. This all adds up to a pretty rich working environment, but the addition of the custom metadata capability really completes this story. In this article, I'll be looking at how to define and work with extended metadata. Defining Custom Metadata in the Composite Component Architecture We have already seen how the definition metadata can contain information above and beyond that which is strictly required for runtime use. The description property and method parameter properties are examples of this. The intention of course being that consumers of the component can receive a richer description of it. However, even those "Design Time" attributes may not be enough and so the framework also supports an extension mechanism. Additional metadata of your own can be introduced anywhere within the custom component metadata definition (e.g. its component.json file) using the property extension. The value of this property can be defined as a complex object in it's own right allowing you to define an unlimited amount of ancillary information on top of the base API. Here's an example of metadata with some extensions added: { "name" : "ccdemo-meter-reader", "version" : "1.0.0", "jetVersion" : ">=2.3.0", "extension": { "author" : "Duncan Mills", "license": "MIT" } "properties" : { "fromMonth" : { "description" : "Start of display range", "type" : "date", "extension": { "validate" : { "type" : "range" "minValue" : 1, "maxValue" : 12 } } }, "utility" : { "description" : "gas | electricity", "type" : "string", "extension" : { "validate" : { "type" : "enumeration" "values" : ['gas','electricity'] } } } } } In this case I've just decorated the top level and the two properties, however, you can supply an extension attribute to any of the definition objects within the metadata except the properties, methods or events root objects which would, of course interpret the extension keyword as just another property, method or event definition respectively.  The Composite Component framework itself, will do nothing with these extension properties after the metadata is parsed. Any functionality (such as the range and enum checking that I've illustrated here) is a task for the component author1, or exists to help some design time tool that you develop in-house to use the extension. By design, there are currently no prescribed set of attributes for any extension metadata that you define. You have total freedom as to how you use the facility, however, be aware that some further evolution and standardization of CCA metadata will be taking place over the next few releases of JET. So you should certainly keep an eye on the release notes for changes in this area, Accessing the Extended Metadata Just being able to extend the metadata definition without being able to read it again afterwards would not be very useful. Therefore, framework provides two ways to access the metadata including any extension information that you have supplied: From a Custom Property Parser - as I discussed in Part X, one of the attributes passed to any custom parser that you register, is the metadata for the property being parsed. This would provide a convenient place to read the extension metadata as defined for that property and use it, for example, providing a validation mechanism as illustrated here. You only see property metadata here though, not the whole metadata defintion. From oj.Composite - the oj.Composite object provides a static method called getMetadata() to retreive the whole metadata object for the Composite Component. This takes the name of the component (the same one passed to the oj.Composite.register() function) and returns a promise to the resolved metadata object. Because this function is both static and external to the custom component, it can be used both within the component itself or by external entities such as Design Time tooling that wishes to introspect the component. Note that the component has (of course) to be loaded / registered before it can be described by this API2. Between them, these two approaches provide the access you need. The rest is up to you! Don't Forget to Standardize! It's all very well having the freedom to extend the CCA metadata in pretty much any way that you want. However, you want to be consistent in how you approach this task. Keep in mind that the CCA is constantly evolving and more standard metadata will be added as new releases arrive. So you should be prepared to revisit your use of metadata with each release and migrate any custom definitions to the standardized ones. This will ensure maximum compatibility with any tooling that reads the metadata. You should also never add custom attributes directly to the JSON outside of the extension property buckets. This will ensure that you don't inadvertently add a property which might clash with a future feature property added by the framework. The extension properties are your "safe zone", stick to adding value there. Furthermore, I would recommend that you namespace your extension metadata within the extension object, for example:  "extension" : { "acme" : { "extensionProp1":"Some Value" } } This will enble you, and any of the consumers of your Composite Component, to clearly identify the relationship between the extension metatdata and it's usage. This will become particularly important if you build many CCAs, some of which will share "common" extension metadata maybe used by your "superclasses" as well as having component specific extension metadata. What's Next? We're almost done with the core technology aspects of the Composite Component Architecture, in the next article I wrap that all up with some of the more advanced topics around the loader script and registration process. JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path 1 Actually you can look forward to basic enumeration being a core part of the formal property definition in the future, but at the time of writing this is not the case yet so this will still serve as an effective illustration. 2 In lifecycle terms the metadata promise is resolved before the CCA component viewModel constructor or initialize() is invoked so you should have no problems accessing it as you component starts up.

Introduction In previous articles in this series, I have discussed some of the ways in which you can extend or override the Composite Component Framework. These include the overriding of...

JET

JET Custom Components X - Custom Property Parsing

Introduction In Part IV of this series, I discussed how the the underling JET Composite Component framework was capable of carrying out basic parsing tasks to manage the conversion of string values, supplied in the tag attribute, to the type defined in the custom component metadata. We saw how basic conversion can take place to both primitives, arrays and simple objects. In some cases, however, you may need to carry out a more sophisticated parsing task, maybe where the supplied object is missing defaults or a string needs formatting / conversion. One way that you could achieve this by defining the attribute as a simple string and then managing the parse within your property processing. The framework, however, does provide a slightly more elegant approach by allowing your component to specify a custom parsing function.  I'm sure that 99% of you will never need to use this capability, but just in case, here we go.  Plugging in a Custom Property Parser You specify the use of a custom parser as part of the register() function for the JET Custom Component. In the previous examples of the register() call we've seen how this looks in broad terms: oj.Composite.register('«tag name»',{«configuration properties»}); The custom parsing function is simply added as an additional property to the configuration properties argument (and is of course optional). So here's a version of the register call with the new configuration property parseFunction added: Version prior to JET 5.0.0 oj.Composite.register('ccdemo-name-badge', { metadata: {inline: JSON.parse(metadata)}, viewModel: {inline: ComponentModel}, view: {inline: view}, parseFunction:customParseFunction }); Version in JET 5.0.0 or above where the register call is a little simpler oj.Composite.register('ccdemo-name-badge', { metadata: JSON.parse(metadata), viewModel:ComponentModel, view: view parseFunction:customParseFunction }); So in this case I've added the name of a function to do the parsing - customParseFunction. This function can be placed anywhere that is accessible in / from the loader script. If it is simple enough you can also define the function anonymously inline: oj.Composite.register('ccdemo-name-badge', { … parseFunction: function(value, name, meta, defaultParseFunction){ … }) }); Once defined, this parsing function will be called for every tag attribute that is being passed to the component, except for those bound to observables/variables through {{...}} and [[...]] which bypass this parsing all together. Defining a Custom Parse Function The custom property parse function takes four parameters: value - the string value supplied for the tag attribute being processed name - the name of the property (not the mapped tag attribute,) being processed meta - the metadata definition for the property that is being processed. This gives you access to information such as type, the default value and any extension metadata defaultParseFunction - a handle to the default framework parsing function, so that you can pass-though properties that you don't have any special processing for. As an example let's imagine that I have a custom component that allows the user to specify a range for a metering component based on a start month, (with the end date being the current date): { "properties" : { "fromMonth" : { "description" : "Start of display range", "type" : "date" }, "utility" : { "description" : "gas | electricity", "type" : "string" } } } Used thus: <ccdemo-meter-display from-month="10" utility="gas"> Internally I want to convert the numerical value for from-month into a date object. Here's what the parse function might look like: function (value, name, meta, defaultParseFunction) { if (name === 'fromMonth'){ var year = new Date().getFullYear(); return new Date(year,value-1,1); } else { //Pass through to the default processing return defaultParseFunction(value); } } Note how I use the name argument of the function to decide if special processing is needed for this property, or if the default conversion routine should be used via defaultParseFunction. You could also use some of the other information provided to the function to manage this process, for example the metadata injected through the meta parameter. The value returned by the custom function is assigned to the relevant property and will then be made available via the properties context to the component. This property parsing takes place in the lifecycle before the viewModel instance is created. What's Next? In the next couple of articles I'll be examining some advanced topics, the extension of custom component metadata. JET Custom Component Series If you've just arrived at Custom JET components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path

Introduction In Part IV of this series, I discussed how the the underling JET Composite Component framework was capable of carrying out basic parsing tasks to manage the conversion of string values,...

JET

JET Custom Components IX - Advanced Slotting

Introduction In the previous article, I introduced slotting and showed how it can be used to inject external content into specific places within your Custom Components. In this article we'll look at some more advanced topics that relate to the use of components with slots, specifically: Nesting Looping Slotting and the Lifecycle Nested Components There is no restriction as to what elements you can assign inside of a component slot and therefore it follows that it's going to be possible to nest your Custom JET Components, and indeed this extends to nesting the same type of component with exactly the same set of slots. For example, imagine that I have two components, ccdemo-component-1 and ccdemo-component-2 where each component defines an <oj-bind-slot> with a name of content. These would all be valid combinations: Example 1 <!--Slot containing just a span, we've seen this before--> <ccdemo-component-1 value={{name}}> <span slot="content">Component 1 Content</span> </ccdemo-component-1> or Example 2 <!--Slot containing a different CCA--> <ccdemo-component-1 value={{name}}> <ccdemo-component-2 value={{name}} slot="content"> <span slot="content">Component 2 Content</span> </ccdemo-component-1> </ccdemo-component-1> or Example 3 <!--Slot containing another Instance of the same CCA--> <ccdemo-component-1 value={{name}}> <ccdemo-component-1 value={{name}} slot="content"> <span slot="content">Inner Component 1 Content</span> </ccdemo-component-1> </ccdemo-component-1> The key things to understand with all three variants are: How each slot is actually allocated What the binding expressions reference Looking at the slot management issue first of all. The rule here is pretty simple, any slot attribute is scoped to the component that is the immediate parent of the element with slot defined. It is not possible for an element to "jump generations" and have itself allocated to any ancestor component's slot apart from that of its immediate parent. This even extends to the case where an element is allocated a slot name which it's immediate parent does not recognize but it's grandparent does. In this case the content allocated to that slot would not be displayed because it's parent component does not recognize it. On the issue of binding scope, nested components are all treated as siblings. In example 2 above, both ccdemo-component-1 and ccdemo-component-2 will be bound to the same source observable name in the common parent view that contains this markup. Put another way, the inner component does not gain access to the viewModel of the outer component, that remains private. Sharing Information between Nested Components As stated above, a nested component does not have magical access to its parent's viewModel. So should you need to share information between them then introducing a common context object in the shared top level viewModel is probably the best way. This context object can then be supplied to both the parent component and the child/children via a bound property ({{...}}) on each. However, If you have a use case where you do need to pass information between components in this way, then perhaps slotting is not the way that they should be combined. In later articles I'll be discussing how to manage deferred UI creation and also how to communicate between components in a loosely coupled fashion. These may both be better strategies in many cases. Multiple Nodes in a Slotting In the previous article in this series I noted how you can assign multiple child nodes to the same slot. Something like: <ccdemo-name-badge id="cc1" badge-name="{{personName}}" badge-image="[[personImageURL]]" compact-view="false"> <span slot="greetingArea">Hello</span> <div slot="greetingArea"> <span>I &hearts;</span> <img src="images/oracle_jet_icon.png" style="vertical-align:middle"/> </div> </ccdemo-name-badge> If you do this,  then  as I mentioned,  both DOM nodes will be relocated into the designated slot position in the order that they are defined. However, you can exercise a little more finesse here. The <oj-bind-slot> tag that you use within the Composite Component view template to indicate where to place slot content, actually supports an additional attribute as well as the name attribute that we saw before. The extra attribute is called index. The index attribute allows you to refer to the nodes that have been defined by the component consumer as belonging to this slot. So for example we might have a simple HTML template for the Composite component like this: <div> <oj-slot name="content" index="0"/> <hr> <oj-slot name="content" index="1"/> </div> And the consumer might use this component thus: <ccdemo-example> <p slot="content">Hello</p> <p slot="content">Goodbye</p> <p slot="content">This will not be rendered</p> <ccdemo-example> The result would be that the text Hello would end up above the <hr> line and the Goodbye would be below. As indicated the third node is not referenced by the template and so would be ignored. Slotting and Looping You can use slot references within a looping construct in your Custom JET Component view HTML template, but only in a very specific way. It is not, for example, possible to do this: <!-- ko foreach: myItems --> <div class="oj-panel"> <oj-bind-slot name="item"/> </div> <!-- /ko --> This is because we can't place a slotting marker in more than one place. However, we can reference the same slot multiple times if we use both name and index attributes <!-- ko foreach: myItems --> <div class="oj-panel"> <oj-bind-slot name="item" index="{{$index()}}"/> </div> <!-- /ko --> Now rather than trying to put the same content in multiple places, we're specifically placing indexed slot children in different places which is allowed. Note that you need to be cautious here, of course, to ensure that the number of DOM nodes supplied by the consumer matches the number of loop iterations that you will go through. Otherwise, in this case, you'd be stamping out empty panels or similar. Slotting and the Lifecycle In the context of the component lifecycle there are two sub-topics to look at: Discovering what slots are in use What happens to the DOM during slotting What Slots are in Use? If you refer back to the main article on lifecycle you will see that the context object that is passed to the various lifecycle methods contains a promise called slotNodeCounts. When resolved, this gives rise to an object with a property for each slot name that the consumer has referred to, and the value of that property is the number of DOM nodes that are allocated to that slot. This then is useful information for the component to understand what the user has specified in terms of the advertised slots, for example in the looping scenario as discussed above. Note: in JET 2.3 and earlier this promise will not resolve until after the component lifecycle is completed. This means that you cannot rely on the slot count information during the setup phases of the lifecycle. This in turn reduces the value of this information considerably, as generally you would want to actually change the UI created by the component based on what the consumer has provided for each slot. This problem has been addressed and in later versions of JET the promise should resolve in a more timely manner. As a workaround, you can inspect the DOM with JQuery to manually count the slot entries that you are interested in. (ideally you would do this in the activated() phase): var nodesInSlot = $(context.element).children('[slot="slotName"]').length Slotting and the DOM As you can imagine, internally the component needs to rearrange DOM nodes in the view to weave the correct nodes into the designated slot positions defined by the view template. Looking back at the lifecycle article again, I stated that (for example) during the activated phase of the lifecycle, the child DOM within the Custom JET Component is empty and does not get populated until attached. This was not strictly true. In fact, during the activated phase (and earlier), if the component consumer has defined child elements for placement into slots, then those nodes will be present in the DOM as direct children of the component. When you get to the attached phase of the lifecycle you will find that the nodes have disappeared as direct children of the component. They have, in face, just been temporarily shunted off into a holding area. Finally, when you get to the bindingsApplied phase the nodes will be positioned in their new homes based on the <oj-bind-slot> markers in the template. What's Next? We've now covered all of the core elements of Custom JET Component creation, covering properties, methods, events and slotting. The next couple of topics round out the story with some more advanced techniques, starting out with custom property parsing. JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path

Introduction In the previous article, I introduced slotting and showed how it can be used to inject external content into specific places within your Custom Components. In this article we'll look at...

JET

JET Custom Components VIII - Basic Slotting

Introduction Not every  component can be totally self contained. There are some use cases where as well as setting configuration attributes on the tag, you want the consumer to supply whole chunks of markup to embed within the component. An example of this might be a component which shows a collection as a table with a standard toolbar. If you want to be able to allow the consumer to add their own content to the toolbar how might you do it? Well, slotting is one way. Simply put, slotting is a way of naming reserved spots within the JET Custom Component into which consumer content can be injected. This allows you to make your components more extensible without having to dream up and code for every possible form of extension. For those of you familiar with the Java EE JavaServer Faces framework, slots are analogous to named facets in JSF components. Using a Custom Component with Slots First of all, let's look at the process of consuming a component which has one or more slots defined, some of the JET core components also use slotting so this may be familiar. To illustrate this, we'll go back to the ccdemo-name-badge component that we've been using throughout this series and imagine that the component has defined a slot called greetingArea for the consumer to use. The idea is that the user can add whatever they like into this area, be it a text or perhaps an image, or both as shown here: To place content in the new greetingArea slot the consumer of the component puts the required content as a child of the custom component tag and sets the slot attribute on the content root which names the slot to use. <ccdemo-name-badge id="cc1" badge-name="{{personName}}" badge-image="[[personImageURL]]" compact-view="false"> <div slot="greetingArea"> <span>I &hearts;</span> <img src="https://blogs.oracle.com/images/oracle_jet_icon.png" style="vertical-align:middle"/> </div> </ccdemo-name-badge> Futhermore, you can define multiple references to a named slot and the component will gather them up and place them into the slot in the order that they are defined, thus:   <ccdemo-name-badge id="cc1" badge-name="{{personName}}" badge-image="[[personImageURL]]" compact-view="false"> <span slot="greetingArea">Hello</span> <div slot="greetingArea"> <span>I &hearts;</span> <img src="https://blogs.oracle.com/images/oracle_jet_icon.png" style="vertical-align:middle"/> </div> </ccdemo-name-badge> Results in: Note how the HTML nodes defined with the slot="greetingArea" can be of different types. Defining Your Slots So we've seen now simple it is to place content into slots, what about defining them? Well that's really just as simple and involves the use of the <oj-bind-slot> tag in the custom component view along with some basic metadata for documentation purposes. Note: In earlier versions of JET this tag was simply called <oj-slot>, that version is now deprecated in favour of <oj-bind-slot> to be more consistent with the other new <oj-bind-*> components introduced in JET 4.0 First the Metadata As you would expect we define a little metadata to help document the slotting capabilities of the component. This uses a top level property called slots which is a peer of the properties, events and methods properties that we've already seen. The basic metadata for each slot is really just to declare it and provide some description of what it does, although you can, as ever, extend the metadata to include your own information should you desire, (see Part XI). Here's the completed metadata json for the ccdemo-name-badge component that includes the slot definition { "name" : "ccdemo-name-badge", "version" : "1.0.0", "jetVersion" : ">=2.2.0", "properties": { "badgeName": { "description" : "Full name to display on the badge", "type": "string" }, "badgeImage": { "description" : "URL for the avatar to use for this badge", "type": "string" } }, "events" : { "badgeSelected" : { "description" : "The event that consuming views can use to recognize when this badge is selected", "bubbles" : true, "cancelable" : false, "detail" : { "nameOnBadge" : {"type" : "string"} } } }, "methods" : { "changeBackground" : { "description" : "A function to update the background color of the badge", "internalName" : "_setBackgroundColor", "params" : [{ "description":"Color name or hex color code", "name" : "colorToSet", "type": "string" }], "return" : "boolean" } }, "slots" : { "greetingArea":{ "description" : "Put your customized greeting here", } } } X Marks the Slot The <oj-bind-slot> tag takes an attribute called name. This name attribute is the official name of the slot that the consumer will use in the corresponding slot attribute in their injected content. This name is case sensitive. So here's the new version of the markup for the ccdemo-name-bage.html which defines a named slot called greetingArea for injected content: <div class="badge-face"> <img class="badge-image" data-bind="attr:{src: $props.badgeImage, alt: $props.badgeName}"/> <h2 data-bind="text: upperFirstName"/> <h3 data-bind="text: $props.badgeName"/> <div class="greeting-area"> <oj-bind-slot name="greetingArea"/> </div> </div> You can define as many named slots like this within your component view template as you desire. You should not define more than one <oj-bind-slot> with the same name attribute, however. Only one of the duplicates would be used and the others ignored. Defaulting Slot Contents In some cases you might want to supply some default content for a particular slot, just in case the user does not supply their own content. To do this, all you need to do is to add the required elements to your vomponent view template HTML as children of the relevant slot. For example, we might decide to default in a standard greeting of "Hi" into the greetingArea slot if the consumer does not specify something themselves. <div class="badge-face"> <img class="badge-image" data-bind="attr:{src: $props.badgeImage, alt: $props.badgeName}"/> <h2 data-bind="text: upperFirstName"/> <h3 data-bind="text: $props.badgeName"/> <div class="greeting-area"> <oj-slot name="greetingArea"> <!-- Default Content --> <span>Hi</span> </oj-slot> </div> </div> If the consumer does not specify anything for the slot then this default will be used. However, if they supply any content for the slot then any default value is ignored and not displayed. Slots are not in any way compulsory and should the user not provide any content and the slot itself has no default content, then the slot is just ignored. Default Slot As well as supporting named slots to target specific child elements to specific places within the final DOM tree, Composite Components also support the concept of a default slot. The default slot is just defined using a plain <oj-bind-slot> tag with no specified name attribute. Then, any content assigned as a child of the Composite Component that does not specify a slot="…" attribute, will be assigned to this default slot. As many nodes as are required can be placed into the default slot, and again they will appear in the order in which they were defined. If you do not define a default slot, then any children of the Composite Component that do not include the slot attribute will be ignored because there is nowhere to put them. Note that if you define a child node of the component with an invalid slot name, then it will also not appear. Importantly you should note that slot names are case sensitive, thus content defined as: <ccdemo-name-badge id="cc1" badge-name="{{personName}}" badge-image="[[personImageURL]]" compact-view="false"> <span slot="GreetingArea">Hello</span> </ccdemo-name-badge> Would not display the "Hello" content because the example custom component slot name uses a lowercase leading "g" not the uppercase used by slot="GreetingArea". Scoping of Slotted Content We've seen that using the slotting capability , component consumers are able to inject their own markup into the midst of the component. An important question to ask, however, is what's the viewModel scope?. For example if I utilize a statement such as this: <ccdemo-name-badge id="cc1" badge-name="{{personName}}" badge-image="[[personImageURL]]" compact-view="false"> <oj-bind-text slot="greetingArea" value="[[greetingMessage]]"/> </ccdemo-name-badge> Then where is greetingMessage coming from? The answer is not from the Custom Component. Any binding expressions that you use within slotted content are associated with the viewModel of the view that contains the reference to the component. Effectively, although it appears that slotted content is a child of the Custom Component, the reality is that it is its peer. When you think about it, this makes a lot of sense. As a consumer of a component you are not privy to the internal implementation of that component and its viewModel should be hidden from you. What's Next? In the next article, I'll be looking at some of the more advanced aspects of slotting, specifically how it integrates into the JET Custom Component lifecycle and how looped content is handled. JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the  Custom JET Component Learning Path Appendix Updated ccdemo-name-badge.css File Now the component supports slotting the CSS has changed a little to define the new greeting-area class and to increase the height of the component as a whole. Here's the full version of the CSS in case you want to update your copy of the code if you have been following along using the sample created in Part II of the series: ccdemo-name-badge:not(.oj-complete){ visibility: hidden; } ccdemo-name-badge{ display : block; width : 200px; height: 260px; margin : 10px; padding: 10px; } ccdemo-name-badge .badge-face { height : 100%; width : 100%; background-color : #80C3C8; border-radius: 5px; text-align: center; padding-top: 30px; } ccdemo-name-badge .badge-image { height : 100px; width : 100px; border-radius: 50%; border:3px solid white; } ccdemo-name-badge .greeting-area { max-height: 60px; min-height: 0px; border-style: solid; border-width: 1px; border-radius: 5px; background-color: #DCE3E4; padding:5px; margin : 10px; text-align: center; overflow : hidden; }

Introduction Not every  component can be totally self contained. There are some use cases where as well as setting configuration attributes on the tag, you want the consumer to supply whole chunks of...

JET

JET Custom Components VII - The Lifecycle

Introduction Once you get into any serious usage of JET Custom Components it becomes useful to understand the lifecycle of any component in some detail, this is particularly true if, for example, your components UI needs to be dynamically adjusted at runtime. Fortunately the lifecycle is simple to understand and work with, so let's get on. The Complete Lifecycle In the following table I outline all of the events and lifecycle methods that can be called, within your component viewModel, as a Custom Component is rendered in a view. Note that all of the methods mentioned are optional, you don't need to create them for the component to work (with the exception of the basic Constructor for the object of course). Note that this table has been updated as of JET 4.2.0 and deprecated events and lifecycle methods have a strikethough and an explanation as to what to use instead 1 pending event raised If the consuming view has registered a listener on the JET Custom Component for the pending event it will be received as the first indication that the component is loading. This event should be  replaced with a check of the oj.busyContext. 2 Component viewModel object constructed If the bootstrap script for the component was passed an object constructor as it's viewModel definition, an instance of the component viewModel will be physically created. The Constructor will be passed a context object (see below). or initialize lifecycle method executed In the case where an already constructed object (as opposed to a constructor) is passed as the viewModel then the framework will call this initialize method, passing a context object. 3 activated lifecycle method executed The activated lifecycle method is called and passed the standard context object. At the point in time that this method executes, the base component element will exist in the HTML DOM, however it will not yet have any child nodes1 so you cannot manipulate the UI at this stage. You can return a promise from this method which will delay the rest of the component initialisation until it is complete 4 attached lifecycle method executed The attached lifecycle method is called and passed the standard context object. At this phase, the view defined by the Composite Component bootstrap script will have been processed and the Composite Component element will now have child elements in the DOM that you can locate and manipulate if necessary. If you need to set up any viewModel values that will be used by knockout bindings in the generated view, this is your last chance to do so. Replaced by the connected method 5 connected lifecycle method executed The connected lifecycle method is called and passed the standard context object. At this phase, the view defined by the Composite Component bootstrap script will have been processed and the Composite Component element will now have child elements in the DOM that you can locate and manipulate if necessary. If you need to set up any viewModel values that will be used by knockout bindings in the generated view, this is your last chance to do so. Unlike the deprecated attached method, this method is called every time that the element is connected to the DOM, not just the first time 6 bindingsApplied lifecycle method executed The bindingsApplied lifecycle method is called and passed the standard context object. At this phase, the Knockout applyBindings has been called on the subtree and any data-bind or other Knockout directives will have been applied. Thus it would be too late to change a DOM element to add a data-bind at this stage. 7 ready event raised If the consuming view has registered a listener on the Composite Component for the ready event it will be received as the indication that the Composite Component has completed its loading. This is deprecated and the oj.busyContext should be used instead 8 dispose lifecycle method executed As a module containing this Composite Component is being replaced, this dispose lifecycle method is called with a reference to the Composite element object. This gives you the opportunity to do clean up if required. Note that dispose does not get called if the user resets the page with a manual browser refresh or explicit navigation that does not first replace the current module. Therefore, you cannot rely on this method as the only way of releasing resources. Replaced by the disconnected method. 9 disconnected lifecycle method executed The disconnected lifecycle method is called with a reference to the Composite element object every time the component is detached from the browser DOM. This gives you the opportunity to do clean up if required (esp. any listeners that the component may have registered). As well as these lifecycle methods and events, you can also receive property-changed events throughout the lifetime of the component should you have listeners registered to do so. The context Object As shown above, most of the lifecycle objects, as well as the viewModel constructor are passed a common context object. This object contains the following properties: element - the DOM element that represents the JET Custom Component itself. Useful if you want to attach listeners (such as property-change listeners) or to manipulate the DOM subtree for the component. props - A promise that will return the property map for the component. See Part IV in this series for information on it's usage. Generally I'd recommend storing the resolved property map reference on the component viewModel as soon as you can2. This will ease later access in event handlers, methods and so forth. However, for the purpose of accessing properties in one of the startup lifecycle phases, always use this pops promise that you obtain from the context i.e. using context.props.then(). That will ensure that you're not caught out by assuming that a stored reference has already been resolved during an earlier stage in the lifecycle. slotNodeCounts - Another promise which, when resolved, returns a list of the slots defined within the JET Custom Component and the number of nodes assigned to those slots. We cover the slotting feature in Parts VIII and IX of this series. unique - A string value generated by the framework which will return a unique "identity" for the Composite Component. This identity will take the form of _ojcomposite0 where the trailing number increments for each composite in the view. This value is also available for direct reference in your view using $unique. Note, although this composite identity will be unique within the parent view that embeds the composite component, the generation is not idempotent and the unique identity that is provided for a particular instance of a Composite Component might change from run to run of a view. As such the unique value is useful for ensuring unique ids within an instance of a CCA. For a more stable unique identity that will not change from run to run, you could consider assigning an id to the Composite Component instance in the consuming view. You can then access that id through the supplied element reference e.g. element.id. uniqueId - A varient of the unique attribute, uniqueid will either contain the specific element ID assigned by the user to the custom component element, or, if that has not been set, then the same value as the unique attribute View-Model Constructor v's Object You will notice that in step 2 of the lifecycle table, as illustrated above, there are two paths. This specifically relates to what exactly was passed as the viewModel property during the registration phase. Let's explore that. If we start off with a conventional JET Custom Component viewModel definition, something like: define(['ojs/ojcore','knockout','jquery'], function (oj, ko, $) { 'use strict'; function CCDemoNameBadgeComponentModel(context) { var self = this; … }; … return CCDemoNameBadgeComponentModel; }); This defines a constructor function CCDemoNameBadgeComponentModel and then returns it. Contrast this with the subtly different variant which is more like what you might use with a standard Knockout view / ojModule: define(['ojs/ojcore','knockout','jquery'], function (oj, ko, $) { 'use strict'; function CCDemoNameBadgeComponentModel() { var self = this; … }; … return new CCDemoNameBadgeComponentModel; }); Note that there are two physical differences here, the first being the lack of a context argument to the constructor function and the second being the use of the new keyword in the return statement. The effect of this new statement, is that rather than just returning the constructor function, this second version returns a pre-created instance of the component viewModel. The JET Custom Component registration process only takes place once for a particular composite, no matter how many instances are being used in the view. During that registration call, if the object passed to the viewModel property is a constructor function then, as each new instance of the physical component is created on the view, the framework will use this constructor to create a corresponding viewModel. As noted above, the constructor is passed a context object as part of this. This viewModel is therefore dedicated to that instance of the component. In this normal variant of the lifecycle the initialize lifecycle method is never called. If the object passed to the viewModel is instead a instance, rather than a constructor, as in the second example, then all instances of the component created in that view will use this same pre-created viewModel object. In this case the alternate version of the lifecycle kicks in and the initialize function is called with a context that is appropriate for that instance of the Composite Component. It is, in fact, somewhat unusual to be using this second approach, if you do, it would generally be when you are leveraging a factory object that in turn would be creating a viewModel instance. You should rarely (if ever!) use this variant. (Deprecated) Lifecycle Method Name Customization In versions of JET prior to 3.0 it is possible to override the lifecycle function names used by the lifecycle callbacks (initialize, activate and so forth). This was accomplished by updating the defaults property of oj.Composite. This feature has been deprecated and should not be used, changing these values would make your CCAs incompatible with every other application that does not use the same names which defeats the whole object of a component standard. It goes without saying that you should not use this capability. What I've Not Covered This article is covers the basic custom component lifecycle. There are two related further topics that will be discussed in later articles in this series: Custom Property Parsing The use of promises during registration   These are both advanced topics that deserve independent coverage. What's Next? In this article we encountered the slotNodeCount property of the lifecycle context object. Therefore it makes sense to take a look next at very powerful feature of the WebComponents / Composite Component Architecture - slotting. JET Custom Component Series If you've just arrived at JET Custom Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path 1 This is not strictly true in the case where you are using slotting, something I cover in the next couple of articles. However, that's not to say that you therefore have free reign to go playing with the DOM nodes at this stage in the lifecycle, you probably shouldn't! 2 This assumes you are defining a separate viewModel instance for each component instance. If you are using a shared viewModel for all instances then you would have to be careful to always use the props reference that you receive with each lifecycle method. This will ensure you are using the correct set of properties and other context information for the component instance in play.

Introduction Once you get into any serious usage of JET Custom Components it becomes useful to understand the lifecycle of any component in some detail, this is particularly true if, for example, your...

JET

JET Custom Components VI - Methods

Introduction In parts IV and V of this series I covered the JET Custom Component API in terms of properties and events. This part will complete the story by looking at component methods. Methods, in this context, are functions that are exposed by the component that you are able to call on the JET Custom Component once it is running. You can use these as a way to pass information into the compnent after it has been started, or manipulate the component as a whole in some other way.  A Note on Passing Data into A Running JET Custom Component As a side note it's worth reminding you of alternative ways of passing data into the component once it is up and running. Although methods can indeed be used for this, they are not the only way. You can leverage the binding syntax ([[...]] or {{...}}) combined with property change listeners as discussed in the previous article to achieve this as well. Likewise you can set the properties directly from JQuery without using bindings e.g. $('#cc1').prop('badgeName','Fred Flintstone'); or even directly on the DOM element $('#cc1')[0]['badgeName'] = 'Fred Flintstone'; or document.getElementById("cc1")['badgeName'] = 'Fred Flintstone';. All of these will achieve the end of passing data changes in to the component when the relevant data endpoint for doing so is exposed as a writeable component property.   The one advantage of using a JET Custom Component method though is, of course, that the method call can encapsulate a potentially complex data structure to pass and maybe you also need to update the internals of the component that are not exposed through published properties.  Defining Custom Methods Just like properties and events, JET Custom Component methods are declared in the component.json metadata. As an example, let's take our ongoing ccdemo-name-badge component and add a method called changeBackground that will update the background color of the badge. We'll have this take a single string parameter with the color name or code to assign. I'll also have it provide a return value to illustrate how that's done. Not surprisingly we do this by adding a top level property to the metadata object called methods to the component.json file. This object then defines a sub-attribute for each method that the component needs to expose. { "name" : "ccdemo-name-badge", "version" : "1.0.0", "jetVersion" : "^4.2.0", "properties": { "badgeName": { "description" : "Full name to display on the badge", "type": "string" }, "badgeImage": { "description" : "URL for the avatar to use for this badge", "type": "string" } }, "events" : { "badgeSelected" : { "description" : "The event that consuming views can use to recognize when this badge is selected", "bubbles" : true, "cancelable" : false, "detail" : { "nameOnBadge" : {"type" : "string"} } } }, "methods" : { "changeBackground" : { "description" : "A function to update the background color of the badge", "internalName" : "_setBackgroundColor", "params" : [ { "description":"Color name or hex color code", "name" : "colorToSet", "type": "string" } ], "return" : "boolean" } } } Let's look at each of the attributes of the changeBackground method The description As in the other cases within this metadata, the description property is simply there to help your consumers and provide information for design time tooling to display. As such it's optional but recommended. The internalName This is an optional property which allows you to define a name for the implementing function inside of your JET Custom Component viewModel which is different from the public name that you provide as the API. In this example, the public name that consumers will use is called changeBackground but the implementing function in the component is called _setBackgroundColor. The framework automatically manages the mapping for you. You don't have to set an internalName, if you don't then the framework will just map directly to a function within the component that matches the public method name. The params As the name suggests, params is a place to declare any parameters that your public method may accept. The params property itself, if specified (it's optional), should define an array of sub-objects which are defined with a description, name and type property as shown here. The type definition matches the those you would use for defining properties although there is no type coercion in this case, the definition is purely informational, although design time tooling may take advantage of it. The return Should your method return a value you can declare this in the metadata. Again this is purely for informational purposes and no conversion or checking takes place. Implementing a JET Custom Component Method In order to implement your method, all you need to do is to define the appropriate function in the component View Model. The name of the function should match the name that your declared in the metadata, or the supplied internalName if you supplied that. So, here's our running example where I've implemented the custom method by creating a function with my allocated internalName - _setBackgroundColor. define( ['ojs/ojcore','knockout','jquery' ], function (oj, ko, $) { 'use strict'; function CCDemoNameBadgeComponentModel(context) { var self = this; context.props.then(function(propertyMap){ //Save the resolved properties for later access self.properties = propertyMap; //Extract the badge-name value var badgeNameAttr = propertyMap.badgeName; self._extractFirstName(badgeNameAttr); }); self.composite = context.element; $(self.composite).on('badgeName-changed',function(event){ if (event.detail.updatedFrom === 'external'){ self._extractFirstName(event.detail.value); } }); //Wire the custom event raise function into the click on //the composite $(self.composite).on('click keypress',function(event){ self._raiseBadgeSelection(event); }); }; CCDemoNameBadgeComponentModel.prototype._extractFirstName = function (fullName) { if (this.upperFirstName === undefined){ this.upperFirstName = ko.observable(); } this.upperFirstName(fullName.split(' ')[0].toUpperCase()); }; //Generate and raise the custom event for Badge Selection CCDemoNameBadgeComponentModel.prototype._raiseBadgeSelection = function (sourceEvent) { if (sourceEvent.type === 'click' || (sourceEvent.type === 'keypress' && sourceEvent.keycode === 13)){ var eventParams = { 'bubbles' : true, 'cancelable' : false, 'detail' : { 'nameOnBadge' : this.properties.badgeName } }; //Raise the custom event this.composite.dispatchEvent(new CustomEvent('badgeSelected',eventParams)); } }; //Internal implementation of the changeBackground component method CCDemoNameBadgeComponentModel.prototype._setBackgroundColor = function (colorToSet) { var wasChanged = true; if (this.lastSetColor !== undefined && this.lastSetColor === colorToSet){ wasChanged = false; } else { $(this.composite).children('.badge-face').css('background',colorToSet); this.lastSetColor = colorToSet; } return wasChanged; }; return CCDemoNameBadgeComponentModel; }); The implementation as you can see trivially updates the background-color of the main badge div and then returns a boolean value based on if the incoming value is the same as or different from the last one set. Calling JET Custom Component Methods Once the implementation function and the associated metadata is defined, the named custom method is just exposed on the custom component element. Thus we could call it using syntax such as: var wasChanged = document.getElementById("cc1").changeBackground("red"); or var wasChanged = $("#cc1")[0].changeBackground("red"); The important thing here is that other methods within the component viewModel, that are not exposed through the metadata, are kept private and cannot be accessed in this way. What's Next In the next article, I'll be taking a look at the lifecycle methods exposed by the underlying Composite Component Architecture and how that might be affected by your component definition. JET Custom Component Series If you've just arrived at JET composite components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path

Introduction In parts IV and V of this series I covered the JET Custom Component API in terms of properties and events. This part will complete the story by looking at component methods. Methods, in...

JET

JET Custom Components V - Events

Introduction In this article I'll be looking at both the built-in events supported by the Custom JET Component architecture and the way that you can add in events of your own on top of that. Build-In Events Out of the box, every custom component that you create will support a set of pre-defined events that are just normal DOM events that your application can listen to: Property Changed events pending event (deprecated) ready event (deprecated) Property Changed Events A really nice feature of the architecture is the automatic creation of property changed events for the properties that you defined in the component metadata. You don't have to do anything here in the component, to make this happen, it's automatic. The event is named after the name of the component property with Changed appended.  So I could add an event handler to my consuming (workArea) viewModel to listen for a change on the badgeName property. Note that I have to follow the same camel case to hyphen conversion that we use for property to tag attribute name mapping to account for the case insensitive nature of the HTML tag.  So although the actual event raised is called (in this case) badgeNameChanged, the attribute to wire up a listener is on-badge-name-changed. <div> <h2>Test Composite</h2> <ccdemo-name-badge id="cc1" badge-name="{{personName}}" badge-image="[[personImageURL]]" on-badge-name-changed="[[badgeNameChangeWatcher]]" </div> Information with a PropertyChanged Event Key to the event object that you will be passed for a Composite property change event is the detail attribute. This will encapsulate an object with three properties: previousValue - the value of the property before it was changed value - the new value for the property updatedFrom - will be set to either the value external or internal to indicate where the property change was instigated. If, for example, your property is bound through the tag attribute to an observable in the consuming view (using {{...}} syntax) and the consuming viewModel updates the observable, that change will be automatically propagated into the component property and the event raised with external as the updatedFrom value. Correspondingly, a change to the property from within the component  will set the value as internal. Note that property change events do not bubble and so you must add the handler directly to the custom component or more usually you actually register the handler inside of the component itself. Let's look at that next. Property Changes within a Custom Component As mentioned, we can also use the in-build property changed events within the component itself. This is mostly going to be useful in the binding case where the change to the property is triggered at some random point in time by an external (to the component) change. If we go back to our running example. In Part IV I added some code to extract the first name in upper case format from the inbound badge-name property. I mentioned in that article that because the lifecycle is not re-run when a property changes, then even if a bound observable changes, this uppercased first-name value would not get recomputed. Now that we have learnt about the property change listener, it becomes trivial to fix this. So here's the revised version of the component viewModel. I've made the following changes: Extract the first-name generation process into its own function to allow re-use The upperFirstName value is now defined as an observable Registered a listener for the  badgeNameChanged event within the composite which will call this new function. I've put this listener into the attached lifecycle method which is generally where you will need to do such things. (more on this in a later article)   define( ['ojs/ojcore','knockout','jquery' ], function (oj, ko, $) { 'use strict'; function CCDemoNameBadgeComponentModel(context) { var self = this; context.props.then(function(propertyMap){ //Save the resolved properties for later access self.properties = propertyMap; //Extract the badge-name value var badgeNameAttr = propertyMap.badgeName; self._extractFirstName(badgeNameAttr); }); }; CCDemoNameBadgeComponentModel.prototype.attached = function(context) { self.composite = context.element; self.composite.addEventListener('badgeNameChanged',function(event){ if (event.detail.updatedFrom === 'external'){ self._extractFirstName(event.detail.value); } }); }; CCDemoNameBadgeComponentModel.prototype._extractFirstName = function (fullName) { if (this.upperFirstName === undefined){ this.upperFirstName = ko.observable(); } this.upperFirstName(fullName.split(' ')[0].toUpperCase()); }; return CCDemoNameBadgeComponentModel; }); You should notice from this code that we are obtaining the reference to the component element from the context object that is passed into the attached() lifecycle method. This is the same object that carries the property promise into the constructor. One additional point on lifecycle here. Notice that I'm still calling the _extractFirstName from the constructor as well as from the property change listener. This is because the initial setting of the property value from the tag attribute does not raise the property change events, these are only emitted after the component is ready. Deprecated events The following two events have been deprecated by the component framework and should no longer be used in JET 4.0 or above. Instead the BusyContext is used to handle this, something which I'll talk about in a later article. The pendingEvent The pending event is raised to let consuming views know that a particular Composite Component is about to render. The event itself will include the identity of the Composite Component that raised the event in its target property. The readyEvent As a companion to pending, the Composite Component will also raise a ready event once it is fully rendered. Like the pending event, it will include the identity of the source Composite Component. Custom Events Useful as the build-in events are, complex custom components may need to specify a more complex and function-orientated API for its consumers to use. For example, a Custom JET Component that provides a chat capability may need to omit an event to signal an incoming message, allowing the consuming view to react to this in some way. The JET Component Architecture provides for such custom events in the metadata that you define for the component. These are standard DOM custom events. Looking at our ongoing example of the ccdemo-name-badge component we currently only define properties in the metadata JSON file (component.json). As a peer of the existing properties definition within that object structure we can define events as well. So as an example, I'll add an event called badgeSelected to the Component. Here's what the metadata will now look like: { "name" : "ccdemo-name-badge", "version" : "1.0.0", "jetVersion" : "^4.2.0", "properties": { "badgeName": { "description" : "Full name to display on the badge", "type": "string" }, "badgeImage": { "description" : "URL for the avatar to use for this badge", "type": "string" } }, "events" : { "badgeSelected" : { "description" : "The event that consuming views can use to recognize when this badge is selected", "bubbles" : true, "cancelable" : false, "detail" : { "nameOnBadge" : {"type" : "string"} } } } } This is all pretty self explanatory in terms of the attributes that define the event. The detail sub-object definition may need a little explanation though. This is simply so that you can declare an specific information that you will be passing back within the detail property of the event. In this case, I'll be putting the current badgeName value into the detail, referenced as nameOnBadge. A key point to stress at this stage is that adding an events section to the metadata in this way does not actually do anything at runtime. It simply provides documentation to the consumer and design time tooling about what events are emitted and what the properties of those events are. In fact, it is the responsibility of you, the component author to actually create and raise the event, in doing so, you should be careful that it matches the API that you have declared in the metadata. Raising a Custom Component Event To actually raise an event you will need to use the dispatchEvent function. In this revised version of the component viewModel you can see this done in the _raiseBadgeSelection function which is triggered by a click or enter key on the composite. define( ['ojs/ojcore','knockout','jquery' ], function (oj, ko, $) { 'use strict'; function CCDemoNameBadgeComponentModel(context) { var self = this; context.props.then(function(propertyMap){ //Save the resolved properties for later access self.properties = propertyMap; //Extract the badge-name value var badgeNameAttr = propertyMap.badgeName; self._extractFirstName(badgeNameAttr); }); }; CCDemoNameBadgeComponentModel.prototype.attached = function(context) { self.composite = context.element; self.composite.addEventListener('badgeNameChanged',function(event){ if (event.detail.updatedFrom === 'external'){ self._extractFirstName(event.detail.value); } }); //Wire the custom event raise function into the click //and return key on the component self.composite.addEventListener('click',function(event){ self._raiseBadgeSelection(event); }); self.composite.addEventListener('keypress',function(event){ self._raiseBadgeSelection(event); }); }; CCDemoNameBadgeComponentModel.prototype._extractFirstName = function (fullName) { if (this.upperFirstName === undefined){ this.upperFirstName = ko.observable(); } this.upperFirstName(fullName.split(' ')[0].toUpperCase()); }; //Generate and raise the custom event for Badge Selection CCDemoNameBadgeComponentModel.prototype._raiseBadgeSelection = function (sourceEvent) { if (sourceEvent.type === 'click' || (sourceEvent.type === 'keypress' && sourceEvent.keycode === 13)){ var eventParams = { 'bubbles' : true, 'cancelable' : false, 'detail' : { 'nameOnBadge' : this.properties.badgeName } }; //Raise the custom event this.composite.dispatchEvent(new CustomEvent('badgeSelected', eventParams)); } }; return CCDemoNameBadgeComponentModel; }); Notice how the custom event is created with parameters which match those declared in the metadata. The listening code can therefore inspect event.detail.nameOnBadge to identify the selected badge when the event is received. What Next? Now that both properties and events have been covered the next article in the series will complete the component picture by looking at methods. JET Custom Component Series If you've just started with Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path

Introduction In this article I'll be looking at both the built-in events supported by the Custom JET Component architecture and the way that you can add in events of your own on top of that. Build-In...

JET

JET Custom Components IV - Attributes, Properties and Data

Introduction In this article I'm going to drill down on all aspects of attributes and data in Custom JET  Components. In the initial tutorial article we just referenced the tag attributes directly in the HTML template via the $prop object. In this article I'll expand on that and look at a whole range of related topics including the following: How to access attribute values from within the component ViewModel Changing attribute values in an already rendered component Reacting to attribute value changes within the component Binding to data in an external viewModel The attribute definition metadata in detail And more besides. For illustration throughout, I'll be referring back to and extending the simple component developed in Article II in this series. If you want to follow along you might want to jump back and review that article if you've not already been through it. Terminology - Properties v's Attributes To clear up some nomenclature before we start, when I refer to attribute I mean the HTML element attribute on the custom component tag that a consumer will use within their views to embed the component. This attribute will map directly to a component property which we have pre-defined in the component metadata (component.json file). So largely the two terms can be used interchangeably, however, as we'll discuss the name of the attribute does not always match the name of the corresponding property. Additionally it is possible for a custom component to define internal properties which are not surfaced to the consumer as writable tag attributes. Accessing Component Property Values With any component, an obvious requirement is to be able to somehow pass data into the component and to do that in a structured way that defines the API of the component itself. The JSON metadata file associated with the component (see component.json in Article II in this series) defines the component API and as part of that declares the properties which will be exposed as attributes on the component tag. So how do we utilize these attribute values from within the component? Directly in the Component View As we saw in the basic tutorial outlined in Article II of the series, the simplest way to access the attributes passed to the component tag is via the $props object. This can be used directly in the HTML of the view template used by the component, for example: <oj-bind-text value="[[$props.propertyname"> or <oj-bind-text value="[[$props['propertyname']]]"> The latter form being for when the actual name of the property as defined within the component metadata is not a valid identifier for use with dot notation, for example it contains a dash/hyphen. So the use of $props gives us a direct passthrough for the UI and because the $props object internally is backed by observables, any changes made to it will be automatically be propagated. Inside of the Component ViewModel What if you need to access the value of an attribute/property from within the component viewModel? This is a pretty common case as well, so let's examine that. At this point we encounter the Custom JET Component lifecycle for the first time. I'll be covering the entire lifecycle in a later article, and for now we'll just look at the basic approach of getting access to the attribute values when the component has been provided with a component viewModel constructor during registration1 - This was the approach that I took in Article II. When a component is registered with a constructor function as the viewModel (as opposed to being passed an object instance), the framework will automatically call this constructor to create a viewModel for the instance of the component being created. At this stage,  go back to the viewModel.js file from that sample, and have a careful look. When the new instance of the component viewModel is created, this constructor is used, but it is also passed a context object which contains information that we will need in order to access the passed attributes as properties. (I've deleted the commented out methods that we don't need for clarity): define( ['ojs/ojcore', 'knockout', 'jquery'], function (oj, ko, $) { 'use strict'; function CCDemoNameBadgeComponentModel(context) { var self = this; self.composite = context.element; context.props.then(function (propertyMap) { //Store a reference to the properties for any later use self.properties = propertyMap; //Parse your component properties here }); }; return CCDemoNameBadgeComponentModel; }); So the constructor function receives a context object. For the purposes of this article we only care about one of the properties of this context object: props - a promise which returns a map of the attributes passed to the component As you can see, the ojet-cli has handily generated a little stub of code (context.props.then) for you that accesses this property object already. Lets make a slight change to do something with that where the generated code tells us to parse our custom properties. function CCDemoNameBadgeComponentModel(context) { var self = this; self.composite = context.element; context.props.then(function (propertyMap) { //Store a reference to the properties for any later use self.properties = propertyMap; //Extract the value passed in via the badge-name attribute var badgeNameAttr = propertyMap.badgeName; } } Of course in this example, I'm not doing anything useful with the badgeNameAttr value I'll do that next. Note as a matter of course, once the propertyMap is resolved I store that for later reference from elsewhere in the component. Component Data that is Not Mapped to Attributes / Properties Whilst we're considering component data in terms of values passed in through attributes, we should also acknowledge that in a lot of cases, data used within the component may be derived in some other manner. Often the data will be associated with some external service or simply generated within the component itself. In this respect, Custom JET Components are just like a JET module. The viewModel for your component view is, of course, the same component ViewModel that we've used above. As such, any properties (e.g. observables) defined in the component model are available for reference inside of your template HTML. To illustrate this, let's make a simple change to the ccdemo-name-badge component where we add a property within the component ViewModel that massages the supplied badge-name attribute to create an uppercase version of the first segment of the name. This results in an updated component that looks like this: Doing this will require us to access the badgeName property as we did above and assign that to another variable which is private to the component model called uppercaseFirstName. This involves a minor change to the code we already have, I'll just show the promise then clause for brevity2: context.props.then(function(propertyMap){ //Save the resolved properties for later access self.properties = propertyMap; //Extract the badge-name value var badgeNameAttr = propertyMap.badgeName; //Do something with the badge name self.upperFirstName = badgeNameAttr.split(' ')[0].toUpperCase(); }; Then the new upperFirstName value can be used  in the usual way. Here's the updated version of the view for the composite component where the upperFirstName value on the component model is used directly (no reference to $props). <div class="badge-face"> <img class="badge-image" data-bind="attr:{src: $props.badgeImage, alt: $props.badgeName}"/> <h2><oj-bind-text value="[[upperFirstName]]"></oj-bind-text></h2> <h3><oj-bind-text value="[[$props.badgeName]]"><oj-bind-text></h3> </div> Traversing the Knockout Binding Hierarchy A note of caution. If you are an advanced Knockout user you might be accustomed to walking up the binding hierarchy using data-bind expressions that refer to sources such as $root or $parents[n] and so forth. Now these expressions will still have a place in your code when working in the context of say a foreach and other structures nested within the scope of the component. However, what you should try to avoid is any case where you are reaching out from the component into the ViewModel hierarchy of the view that is consuming the component. By doing so, you would be making assumptions about the environment in which the component is being consumed. This effectively introduces invisible dependencies on consuming applications adding to the burden of documentation and consumption of the component. Binding Data by Reference In the example that we've been looking at so far, the attribute values being used by the component have been effectively hardcoded into the tag in the consuming view. e.g. <ccdemo-name-badge badge-name="Duke Mascot" badge-image="/images/duke.png"> What we might want to do, however, is to make it a two-way street and not only pass values into the component, but to allow the component to change that value and pass it back to the consuming view. Having this functionality makes a component much more useful as you can start to use it in editing environments such as forms or editable tables. The good news is that the underlying JET  Architecture supports this out of the box with only a small amount of configuration required in the definition of the component properties. Before we look at the metadata let's look at the syntax from the perspective of the consuming view that is using the custom component. The consuming view can pass a reference to a property within it's viewModel by enclosing the property name in double braces {{...}} for a read-write reference and square brackets [[...]] for a read only reference3. Seem familiar? Of course it is, is exactly the same syntax that the JET core components use!  To see this in action, I'll amend my sample to first of all add the name and image information that I need to the viewModel of the generated app which is the appController.js file:   define(['ojs/ojcore', 'knockout', 'jquery','jet-composites/ccdemo-name-badge/loader'], function(oj, ko) { function ControllerViewModel() { var self = this; self.personName = ko.observable('Duke Mascot'); self.personImageURL = ko.observable('/images/duke.png'); ... Now the view (index.html in this case) can use the reference syntax instead of hardcoding, I'll pass the personName in as a writable value and the personImageURL as read-only using those two variations on the syntax: <div> <h2>Test Composite</h2> <ccdemo-name-badge badge-name="{{personName}}" badge-image="[[personImageURL]]"/> <:/div> So now, without any change, the Composite Component is now being fed with dynamic, rather than hardcoded data. One nice feature of this automatic binding is that the framework will handle the conversion of the data from and to the observable for you automatically. So a change of the observable value in the consuming viewModel will be automatically reflected into your component  $props values as well without you needing to write any code (and visa-versa). Note, however, that changes to an externally supplied reference values like this, will not kill your existing component instance, create a new one and then re-run the component lifecycle anew. So, should you have your own internal mechanisms within the component that need to react in real time to the value change in an attribute value.  You will also need to handle this through a computed observable or through property change listeners which is something that I'll cover in the next article in this series. Attribute Metadata in Detail Next, let's look at the Custom JET Component metadata that is used to specify the properties (and therefore tag attributes) of the component. So far, we've seen a very simple definition where only the property name and the datatype was supplied. However, there are a few more options that are supported. Let's go through the full list: { "properties": { "your-property-name": { "description" : "Some descriptive text", "type": "string | boolean | number | Array | Object | function ", "value" : some value as per the selected type, "readOnly" : true | false, "writeback" : true | false, "enumValues" : array of valid string values } } } A Note on Property Name Before diving into the attributes of the property definition itself, I just wanted to remind you about the effect that the name that you actually select for your property can have. This is covered in detail in Article III in this series (Conventions and Standards). The point to remember is that if you use camel-case in the name that you choose for your property in the metadata, this will be mapped to an attribute with a slightly transformed name to allow it to work in an HTML document. Thus a property defined in the metadata with the name myProperty would actually be used/set in the document tag as the tag attribute my-property The description Property The description, as the name suggests, provides you with a place to add some textual documentation about the purpose of the component property. This information is currently for documentation purposes only and has no impact at runtime. It is therefore not required although of course it's use would be recommended. Design time tooling that exposes Custom JET Components will be able to use the description to improve the design time experience. The type Property Type is of course the key property for the definition. If the user supplies a value in the tag attribute that does not match the declared type then the framework will log an error message in the form: Unable to parse value <supplied-value> for property <your-property-name> with type <defined-type>. In this case, the property will remain as un-set (i.e. undefined in the property map that is passed via a promise to the component componentModel instance). Additionally note that: If the offending property had a defined default value, this will not be set in this case. The other properties of the component will be processed normally Apart from the logged message on the console, the framework will take no remedial or "stopping" action. The lifecycle of the component will proceed as normal Thus it is your responsibility to always check each Composite property that you use in an appropriate manner when the promise is resolved. The common primitive types that you would use for your properties are: string number boolean The framework will attempt to coerce any type supplied directly in the tag to these types for you. You can also specify non-primitive types for example: { "properties": { "namesArray": { "type": "Array", } } } Which could be used either with a binding to pass the array, or handily the framework will also resolve this well formed JSON string into a array of size 4 in the property value: <my-tag names-array='["John","Paul","George","Ringo"]'> Likewise you can define a general object type: { "properties": { "personObject": { "type": "Object", } } } And pass a JSON string: <my-tag person-object='{"name":"Fred Flintstone","age":31}'> Note that in both the array and object case we have to use double quotes within the attribute value to enclose any string values, so the tag attribute as a whole must use single quotes if values are being passed in-line in this fashion. You can also refine your metadata from a documentation perspective by being more  precise about the complex types that you expect. For example we could re-write the previous definition as: { "properties": { "personObject": { "type": "{name:string,age:number}" } } } Note this does not imply that the framework will attempt to validate the structure of any supplied object against this specification, rather it helps inform the user of the shape that they should supply. When using these non-primitive types you would generally not be expecting the user to enter JSON strings directly into the tag attribute. In most cases the values will be passed in from the enclosing viewModel (e.g. using the {{...}} or [[...]] notation as discussed). However, the onus will be on you to validate the property values provided just in case the consumer has entered a JSON string manually and made a mistake. Function Callbacks The final type you can see in the metadata illustration above is function. As the name suggests this allows you to pass a function reference / callback from the consuming viewModel. Such callbacks will allow you to achieve a much smoother integration with the calling application. You might, for example, use this to carry out lazy loading or other integration tasks which need to take place in the context of the caller rather than the component. Function references are passed to the component via the tag attribute, using the {{...}} notation4 e.g. <my-component scroll-next={{moreRowsCallback}} /> Obviously before using such callback functions you will want to be careful about documenting exactly what the shape of the callback function should be. You can in fact be more precise in your type definition about that shape of the function for documentation purposes. So for example you could define it thus type="function(string, string, number):boolean" This implies that a callback function with three arguments of type string, string and number respectively is required and that it returns a boolean. The value Property The value property of the property definition provides a default value for that property should the consumer not provide the value via the tag attribute. One slight catch to watch out for here concerns types. If the type of this default value does not match the declared type of the property as a whole it will still "win" if the attribute is not supplied via the tag markup. Thus in the case: { "properties": { "doSomething": { "type": "boolean", "value" : "true" } } } If the do-something attribute is not supplied by the consumer then the property will be made available with the default value as part of the properties map, but as a string value not the expected boolean. The readOnly Property The readOnly property is a boolean attribute which, if set to true, prevents the property from being mapped from the tag attributes. This then provides a convenient way to create an internal property for the component that can still be manipulated from within the component itself, but which cannot be set directly by the consumer. If a default value is set for the property in question, it will be respected. If the consumer tries to supply the value as part of the component tag it will simply be ignored. The writeback Property Writeback is specifically used in cases where you wish to allow the custom component to be able to consume a binding via the {{...}} syntax and to make it a two way conversation. If writeback is set to true, the observable that was passed into the component will automatically be kept updated with any changes made to the associated property within the component. This means that you don't have to write any plumbing code to keep the consuming page in step with the composite. If writeback is false then changes made within the compenent will not be propagated back. The enumValues Property The enumValues property will be ignored in versions of Jet prior to 3.0, although you can use it for documentation-only purposes before then. As the name suggests, when used with a string type of property, enumValues will allow you to restrict the valid values that can be supplied. Updating Properties Finally for this article let's look at updating properties. Although the properties are initially populated from the tag attributes they are not read-only. You are able to store the reference to the properties map once the initial promise has been resolved, this is what I have been doing in the code samples above by assigning to self.properties. Then you can just update the values as required. If the property that you change the value of is associated with a bound value from the consuming view, and the writeback property is set then the framework will automatically synchronize the consuming view attribute with the new property value that you have stored. This also true if you simply have an input bound to the attribute via the $props reference e.g. <oj-input-text value="{{$props.inputValue}}"> An Important Note About Complex Objects When a binding reference is passed to your component, any auto-propagation of changes between the component and source of the binding are based on object identity. When you bind a complex object type via {{...}} or [[...]] notation is it possible to update a child property of that object without effecting the top level object identity. The effect of this is that it is possible for a component to actually update a property of such a complex object even when writeback is set to false or the object was passed with [[...]] notation. In order to prevent this from happening if it is a problem for you, you will have to clone the incoming object when you parse your properties. Such a clone would be fully decoupled from the source object. What's Next?  Hopefully that's a good primer on component Properties. In the next article, I'll be looking at component events. JET Custom Component Series If you've just arrived at Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Components Learning Path 1 Actually here's where things get a little complicated. In reality, there are two ways that the component can get initialized and the properties read. Either as part of the object constructor function as I've shown here or using the initialize() lifecycle method which will be called when an object instance was passed to the component registration. 2 Generally in these code samples I'm trying to keep things simple and compact, as such I'm also going to omit error checking logging and all that other good stuff you would have in a real application. 3 The [[...]] binding notation implies read-only with respect to the data origin. It is possible to change the property value but that change is kept private to the Composite Component and not written back to the source observable. (Not withstanding the note about complex objects). 4 Actually you can use either {{...}} or [[...]] notation to point to the function reference, however, given the implicit meaning of a function callback the curly brace notation seems to be more correct as the one to standardize on.

Introduction In this article I'm going to drill down on all aspects of attributes and data in Custom JET  Components. In the initial tutorial article we just referenced the tag attributes directly...

JET

JET Custom Components III - Conventions and Standards

Introduction Now that we've covered the very basics of Custom JET Component creation, I wanted to step back and help you make sure that you get your standards set up correctly before you get any further and start to build your own. Here I'll cover five fundamental topics: Component Scope Component Naming CSS Styles Code Organization Required Metadata   Component Scope A key decision to make when thinking about your use of custom components is exactly what constitutes a good scope for a reusable component. What I mean by that, is the task of finding the correct balance for your application in terms of how many components you need to express the required functionality and how complex each is. With any reuse mechanism such as JET Components, there is an initial temptation to go overboard and define everything as a separate component. For example given the design goal of "We want to standardize how all our toolbars look"; should that be interpreted to mean I should have a single component to represent a standard toolbar? Well possibly, but does it also mean that I should have one component for an Insert toolbar icon, a second component for a "Delete" toolbar icon and so forth? Probably not... When considering how to effectively use custom components you'll have to balance the costs (both in development and runtime terms) verses the benefits. Each component has a cost, even just in terms of the contributing files that need to be loaded to create it. So, creating for example, a whole set of separate toolbar button specific components would really be less than wise in most scenarios. Of course, in some cases, you will have an obvious re-use target in mind, for example, using this component as a plugin in a SaaS application, so that's really going to guide you well with respect to the scope of the thing. However, within the context of a normal application, you may have alternative mechanisms which may be more suitable as a vehicle for re-use. Examples of this may be the use of ojModule or even something as simple as Knockout templates if all you need is reusable UI. When thinking about a candidate for a custom component you should always try and evaluate if this use case is a good one and that can generally be judged by positive answers to questions such as: Will I re-use this thing in lots of places? Will a componentized version of this be easier to use? Will this component encapsulate behavior as well as attributes The last of these is particularly important. If all you are doing is encapsulating some attributes and presenting them without events or custom methods then really a Knockout template will do the job just fine, you don't need the full power and cost of a custom component. Given this set of criteria, my simple example given in Part II of this blog series fails to pass the last test. However, I'm sure that you'll forgive me for trying to keep things simple for illustrative purposes at the beginning. Another good case for using a Custom JET Component is of course when it is a self contained component that takes care of managing particular set of data that is not directly sourced from the consuming application. An example of this might be something like a chat client that plugs into your app but which handles all of it's own server access and so forth. This is not a must-have feature though, there are many cases where a component will rely solely on data passed into it from the consuming application.   Naming and your Components First of all let's think about the actual tag and attribute names. Here we have some guidance as part of the Web Components specification. The standard here is simple and designed to reduce the chance of future name collision. Your HTML tag should contain at least a dash/hyphen (-) character. Hence <acme-coyote-tracker> would be a good name for a Composite Component tag, however, <CoyoteTracker> would not. The same would be true of attributes as well e.g. character-name rather than say just name although it is not required by the standard. I'd also advise that you embed your organization name in some way into the name, for example as a prefix followed by a dash. In the world of WebComponents there is no governing body or fixed naming structure, and so this is a good precaution against name collisions with components from elsewhere. A Note About Standard Element Attributes etc. When a composite Component is created, it extends the base HTMLElement type, as a consequence, every component already inherits a defined set of attributes, methods and events including the id and title attributes. Checklist of Naming Standards I'd suggest that you follow the following guidelines: Your tag should include a dash/hyphen character as defined by the Web Component Standard. Name your tag in a way that assigns some kind of namespace to it. For example, if your project or company is called "Acme" then use that as as prefix (acme-...). The aim here is to reduce the chance of naming collisions with other Web Components that you do not control. For tags, case has to be ignored as users are free to use any case in their document when referencing a tag, so stick to lower case in your definition to prevent confusion. Properties in the JSON metadata that define tag attributes can either use camel-case (preferred) or the dash/hyphen character in the name of property to increase the expressiveness of the names whilst reducing the risk of collision with existing inherited attribute names. Note see Camel Case Properties below Be cautious about overloading the standard HTML attributes. For example you could use the value supplied by the standard title attribute as meaning something special to your component but that might end up confusing the user as it's not acting in the same way as other HTML elements. If in doubt, see rule 4.   Camel Case Properties You may notice a slight problem with the naming rules comparing tags and the tag attributes outlined above. I've said that case is ignored by the browser for tags, but then stated that you can use camel case for the properties - surely the same rules apply? Well yes, and here's where things can get a little confusing if you're not paying attention. The tag name is supplied as the first argument to the oj.composite.register() API and that must certainly be lower case with hyphens as a matter of course. The tag attribute names, however, are not actually directly defined for the component. Instead they are derived from the properties object that you define within the component metadata. The core rule for the actual tag attributes that are derived from these property definitions is the same as for the tag, i.e. they should be case insensitive, so the framework will do some mapping for you when the property information is read. If you define your property as being all lowercase (with or without a dash/hyphen) then the property name will be used directly as the attribute name. If, however, your name your property in mixed case e.g.: { "properties":{ "coyoteName" : { "type" : "string" } } } Then the tag attribute that you would use to populate that when using the component would be called coyote-name. The attribute name is derived by breaking the string at the camel-case segments, inserting a dash/hyphen and converting all to lowercase. The framework will then manage the mapping between the hyphenated version and the defined property name that the Custom JET  Component uses internally. Thus, the component consumer may use component like this: <acme-coyote-tracker coyote-name="Wile E. Coyote"/> But then internally in code, or in its HTML template the component can use the camel-case reference and get the supplied value. e.g. <h2 data-bind="text:$props.coyoteName"/> The reason that you might want to use this approach is that if you defined the in-metadata property as "coyote-name" rather than "coyoteName" in the first place, then you would have to use the slightly more cumbersome property access syntax within your component: <h2 data-bind="text:$props['coyote-name']"/> Although both approaches to naming work, the camel-case convention is preferred as this makes access to the properties much easier in your code. File Naming As we saw in Part II, we will generally have up to five standard files involved in each custom component: The bootstrap / loader JavaScript The metadata JSON The HTML view template file A CSS file The component viewModel JavaScript The convention here is that the first of these is called loader.js. You should stick to this name to ensure maximum compatibility with any code that is trying to bootstrap your component at runtime. Likewise, the metadata file should always be called component.json. The remaining files for the custom component can follow one of two standard patterns: Pattern A  This is the pattern that I have used throughout these articles for clarity in the text. Files should share the same file name prefix as the associated tag, e.g. acme-coyote-tracker with the extension that represents their function: acme-coyote-tracker-view.html acme-coyote-tracker-styles.css acme-coyote-tracker-viewModel.js Pattern B  Files should use a file name that reflects their purpose: view.html styles.css viewModel.js Pattern B means that if you copy an existing CCA to create a new one you have less re-naming to do!  That being said either pattern is acceptable. You may of course have additional scripts and resources as well which can be named as required or even organised into sub-folders. Class Naming Finally, for consistency you should think about how you refer to the Composite Component ViewModel throughout your code. This is in no way critical, but given that some standard is better than no-standard when it comes to helping others understand what your code is doing, it's a good idea to pick a naming convention and stick with it. My preferred convention is to derive the name for the mode class from the name of the component, with the dashes stripped and converted to camel case, with ComponentModel appended to the end. Thus for our acme-coyote-tracker component we use AcmeCoyoteTrackerComponentModel: define(['ojs/ojcore','knockout','jquery'], function (oj, ko, $) { 'use strict'; function AcmeCoyoteTrackerComponentModel() { var self = this; ... }; return AcmeCoyoteTrackerComponentModel; }); Styles In the basic sample shown in Part II of the series I discussed how you should at least define a simple class selector that suppresses the visibility of your Composite Component until the framework has completed it's processing. You should always include this as a matter of course as your default CSS. acme-coyote-tracker:not(.oj-complete){ visibility: hidden; } acme-coyote-tracker{ display : ...; } That aside, the core concern with any styles that your component requires will be the usual one of managing style conflicts. As such you should ensure the isolation of any classes that you define in this CSS by defining them in the context of the component: acme-coyote-tracker .desert-background{ background-image: url('images/paintedDesert.png');; } CSS Resource Loading In the example above, I'm using the url() directive to assign a background image to the desert-background styleclass. Note here that the location of these resources will be relative to the root directory for the component. Thus the paintedDesert.png will be, in this example, physically located in an images sub-directory which is a peer of the actual CSS file. Code Organization In terms of a single application where you put code for your components is not critical it just needs to be consistent and of course easy to map in your requireJS configuration. If you are using a standard JET project layout, as generated by the ojet command line  scaffolding, I'd recommend that you standardize on a location such as /js/jet-composites/, or similar, as the root for all your custom components, then you can place each individual custom component in its own subdirectory that shares the name of the component. Thereafter all the files that compose the component are referenced from this root. /js /jet-composites /acme-coyote-tracker loader.js component.json acme-coyote-tracker.html acme-coyote-tracker.css acme-coyote-tracker.js /images paintedDesert.png This latter point is important because you always want to load the resources required for the component from a location relative to the bootstrap script (./*)1: define( ['ojs/ojcore', './acme-coyote-tracker', 'text!./acme-coyote-tracker.html', 'text!./component.json', 'css!./acme-coyote-tracker', 'ojs/ojcomposite'], function (oj, viewModel, view, metadata, css) { 'use strict'; oj.Composite.register('acme-coyote-tracker', { metadata: {inline: JSON.parse(metadata)}, viewModel: {inline: viewModel}, view: {inline: view}, css: {inline: css} }); } ); You will note that in this case we're making the assumption that whatever JET application is consuming this component has the ojs path in its requireJS definition. This of course is a fairly safe bet, however, in general you are going to have to consider how to document a particular components dependencies particularly if non-JET shipped libraries are required. Metadata Over the course of the next few articles in this series I'll be discussing properties, events and so forth, along with the metadata that defines them within the component.json file. Much of this metadata is purely optional and not required for the component to actually run.  However, the metadata goes provide you with an opportunity to document your component for your consumers, and over time, may also be leveraged by component registries or design time tooling such as Visual Builder Cloud Service.  Therefore it's really a good idea to be as expressive with the metadata as you can. I'll cover the metadata specifics of each focus area in the relevant articles. However, concentrating on the component as a whole, there is some information that you should always provide at the root of the metadata .json: { "name" : "acme-coyote-tracker", "version" : "1.0.0", "jetVersion" : ">=2.2.0" "properties":{ "coyoteName" : { "type" : "string" } } } The name property documents the actual name of the tag that will surface this component. This of course should match the value that you define in the oj.composite.register() API call in your loader. The version property, of course, defines the version of your component. This becomes useful when coupled with the optional compositeDependencies property (not shown in this example) which allows you to declare inter-component dependencies. You should adopt Semantic Versioning for your component to ensure that the meaning of the version string ranges that you might use are totally clear. Finally the jetVersion property documents what version of Jet the component is compatible with. Note how these version references can specifiy a minimum version as opposed to a fixed version. What's Next? In the next article I'll be diving into Custom JET Components in more detail and specifically looking at properties.    JET Custom Component Series If you've just arrived at JET composite components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path 1 In a future article I will cover the nuances of loading components from outside of your application.

Introduction Now that we've covered the very basics of Custom JET Component creation, I wanted to step back and help you make sure that you get your standards set up correctly before you get any...

JET

JET Custom Components II - The Basics

Last Updated Dec 2018 for JET 6 Introduction In this primer article on Custom JET Web Components (aka JET Composites or CCA), I'll just be looking at the basic tasks involved in creating a simple custom component. Think of this as a "hello world" tutorial equivalent. In later articles I'll be expanding on many of the topics that are only touched on here, so if you work through the articles in sequence everything will make sense as a whole and you'll get a good grounding in this feature. Note that this article, and in fact this entire series, has been upgraded over time and so, as such, you need to be using at least JET 4.0 to follow along. In places where there are differences between the latest version of JET and older versions I'll call those out, so pay attention to the versions mentioned at the top of this article and the version you are actually using.  Preparation Throughout this series of articles I'll be building up some example components that you can follow along with should you wish. So to start off, I'll just create a new JET Application as a workspace for the subsequent code to live in: ojet create myfirstcomponent --template=basic Setting up the JET Application to use Custom JET Components RequireJS Configuration  The first thing that should be on your checklist when consuming Custom JET Components into an application is to make sure that both the text and css requireJS plugins are configured up. If you create an application using the ojet command line tool (ojet-cli), (or using the Yeoman scaffold in versions of JET prior to 4.0.0),  this will be done for you. However, if you are working in really old versions of JET (prior to 2.3.0), you will have the text plugin defined already, but not the css plugin. To either check this, or indeed carry out the task of configuration, locate your requirejs.config{}. This configuration will usually be found in js/main.js if you have used the ojet-cli or scaffolds, but this may differ of course if you have hand crafted your application, or perhaps if you have more than one configuration (e.g. for unit-testing). Your basic requireJS configuration should look a little like this (notwithstanding additional paths and configurations that you may have added): requirejs.config({ baseUrl: 'js', // Path mappings for the logical module names paths: //injector:mainReleasePaths {     'knockout': 'libs/knockout/knockout-3.4.2.debug',     'jquery': 'libs/jquery/jquery-3.3.1',     'jqueryui-amd': 'libs/jquery/jqueryui-amd-1.12.1',     'promise': 'libs/es6-promise/es6-promise',     'hammerjs': 'libs/hammer/hammer-2.0.8',     'ojdnd': 'libs/dnd-polyfill/dnd-polyfill-1.0.0',     'ojs': 'libs/oj/v6.0.0/debug',     'ojL10n': 'libs/oj/v6.0.0/ojL10n',     'ojtranslations': 'libs/oj/v6.0.0/resources',     'text': 'libs/require/text',     'signals': 'libs/js-signals/signals',     'customElements': 'libs/webcomponents/custom-elements.min',     'proj4': 'libs/proj4js/dist/proj4-src',     'css': 'libs/require-css/css',   'touchr': 'libs/touchr/touchr' } //endinjector }); In the above1 path configuration you can see both the text and ccs plugins are defined as we require. When you are consuming Custom JET Components from outside of your codebase, you may be asked to add additional library paths to this configuration as well, just consult the supplied documentation for the Component. ojknockout Dependency Custom components do depend on the ojs/ojknockout module being loaded and bindings applied.  When you create a JET application using the ojet-cli, or one of the Yeoman scaffolds, this will automatically be done for you via the require([...]) in the generated main.js, which also calls ko.applyBindings().  So this will only be an issue for you if you hand-craft a JET project from scratch. The symptom of not applying bindings would be that your custom component viewModel code will get executed but you'll just not see anything in the page as the view part will not be rendered.  On to Creating a Custom Component... In this first example, I'm going to walk through the task of creating a very basic component that displays an image and a name which will be passed in as parameters to the component2. I'll call the component ccdemo-name-badge. Our aim here is to create something a little like (but simpler than) the basic Composite Component demo in the cookbook. Note: In this basic article I'll be leaving a lot of detail out, but rest assured each topic of interest will be covered in much more detail later. If you are in JET 4.0.0 or above, you can use the ojet command line interface to quickly scaffold up a new component with all the basic parts described here. See this article for details. cd myfirstcomposite ojet create component ccdemo-name-badge And you are done! Testing the generated Custom JET Component After using the ojet-cli we can actually run the component to check that it works - it won't really do much yet, but it proves that the basic generation step was OK. To do this, edit the myfirstcomponent/js/appController.js file in your preferred editor and change the define() block to the following: JET 5.2.0 and Above define(['ojs/ojcore', 'knockout', 'ojs/ojknockout','ccdemo-name-badge/loader'], JET 5.1.0 and Earlier define(['ojs/ojcore', 'knockout', 'ojs/ojknockout','jet-composites/ccdemo-name-badge/loader'], Just like any normal JET component you need to tell the viewModel to require (i.e. load) the component before you use it and that's exactly what the reference to the ccdemo-name-badge/loader file above is doing. The difference between the two versions shown above is that in JET 5.2.0 we introduced the automatic creation of a requireJS path with the same name as the component which makes loading it a little easier and more reliable. Next, edit the index.html in the root of the myfirstcomponent application source directory. Look for a div element with role="main" and inside of it put the Custom JET Component tag: <ccdemo-name-badge></ccdemo-name-badge> Save everything, and run the application using the ojet serve command. The page will load in the browser and the component will simply show as a string on the screen "Hello from Example Component". Great now we know the generated component is basically working, albeit not doing much yet. Configuring the generated Custom JET Component We've shown that the ojet-cli has created all of the basic artefacts of a custom component for you, but you'll now need to go and configure those to add the extra functionality we need. Step 1 - Define The Custom JET Component Metadata The JSON format metadata file is a key part of your component. It provides a declarative definition of the component in terms of the properties, the methods and any events that it supports i.e. its API. In this first simple example we're only going to worry about a couple of attributes. Methods and events will be covered in detail later in this series. The ojet-cli has pre-created a JSON file called component.json which you will find in the  js/jet-composites/ccdemo-name-badge directory, go ahead and edit that file. In this example component we just want to define two properties badgeImage and badgeName. To do this the JSON file needs to define a definition of a properties object, which in turn contains the definition of each of the above. Harder to say than actually do, here's what it would look like: { "name": "ccdemo-name-badge", "displayName": "ccdemo-name-badge", "description": "Describe your component here", "version": "1.0.0", "jetVersion": "6.0.0", "properties":{ "badgeName" : { "type" : "string" }, "badgeImage" : { "type" : "string" } } } And that's it, both properties will be strings as the type attribute indicates. You can ignore or delete the methods and slots attributes, we'll cover those in later articles. Step 2 - Define the Template HTML In some cases the HTML template may be totally dynamic and impossible to define ahead of time. In our simple example, however, that's not the case. We have a well defined structure which we can create as an HTML template for the layout for the component. The ojet-cli has pre-created a starter HTML template for us called view.html, also in the js/jet-composites/ccdemo-name-badge directory. Edit this file and replace the generated contents with the following: <div class="badge-face"> <img class="badge-image" data-bind="attr:{src: $properties.badgeImage, alt: $properties.badgeName}">   <h3><oj-bind-text value="[[$properties.badgeName]]"></oj-bind-text></h3> </div> So in this template you will notice the the knockout data-bind attribute is being used to define the attributes for the IMG and the <oj-bind-text> tab in the H3. We are then binding to the $properties object which the framework provides to give you direct access to the configured properties of the Custom JET Component tag, in this case the badgeName and badgeImage attributes. In later articles I'll show how you can bind to values other than just the properties via $properties in this way. Step 3 - Define the Component CSS In nearly every case you will have some style information associated with your component. As a standard you should always include a style for the component as a whole which will suppress the display of the component until everything is ready to go. The framework will automatically set the .oj-complete class onto the component to trigger the display when everything is ready. In this simple example, we supply this standard base class for the component as a whole that will control this visibility. Aside of that, there will be an additional badge-face class to style the actual badges and a further class for the badge image. The generated CSS file is called styles.css and is also placed in the js/jet-composites/ccdemo-name-badge directory, the first bit will have been generated for you: ccdemo-name-badge:not(.oj-complete){ visibility: hidden; } ccdemo-name-badge{ display : block; width : 200px; height: 300px; margin : 10px; } ccdemo-name-badge .badge-face { height : 100%; width : 100%; background-color : #80C3C8; border-radius: 5px; text-align: center; padding-top: 30px; } ccdemo-name-badge .badge-image { height : 100px; width : 100px; border-radius: 50%; border:3px solid white; } Step 4 - Define the Component ViewModel In the long run, all Custom JET Components are going to exhibit some sort of behavior (if not then you should probably not be using a component in the first place). As such, we'll need somewhere - a ViewModel JavaScript file - to act as the home for that behavior code. In this first simple example, we can just use the basic ViewModel.js that was generated for us by the ojet-cli. The file is of course in the js/jet-composites/ccdemo-name-badge directory and will look like this in JET 6 (there may be minor differences if you are using an earlier version but just go with the flow if that's the case): 'use strict'; define( ['knockout', 'jquery', 'ojL10n!./resources/nls/ccdemo-name-badge-strings'], function (ko, $, componentStrings) { function ExampleComponentModel(context) { var self = this; //At the start of your viewModel constructor var busyContext = oj.Context.getContext(context.element).getBusyContext(); var options = {"description": "CCA Startup - Waiting for data"}; self.busyResolve = busyContext.addBusyState(options); self.composite = context.element; //Example observable self.messageText = ko.observable('Hello from Example Component'); self.properties = context.properties; self.res = componentStrings['ccdemo-name-badge']; // Example for parsing context properties // if (context.properties.name) { // parse the context properties here // } //Once all startup and async activities have finished, relocate if there are any async activities self.busyResolve(); }; //Lifecycle methods - uncomment and implement if necessary //ExampleComponentModel.prototype.activated = function(context){ //}; //ExampleComponentModel.prototype.connected = function(context){ //}; //ExampleComponentModel.prototype.bindingsApplied = function(context){ //}; //ExampleComponentModel.prototype.disconnect = function(context){ //}; //ExampleComponentModel.prototype.propertyChanged = function(context){ //}; return ExampleComponentModel; }); You can see the variable that is supplying the default "Hello" message here, but you can delete that, everything else is just boilerplate and can be left for now. For neatness you may want to change the name of the object defined here from "ExampleComponentModel" to a more descriptive name such as "CCDemoNameBadgeComponentModel" Note that the return statement for the component viewModel is not creating an instance of the model, but rather is returning the constructor function itself. Taking this approach, each instance of the Composite Component that is used will have it's own distinct component viewModel. This is what you want in most cases. Step 5 - Examine the Component Bootstrap Script The final piece of the component creation puzzle is the bootstrap file used to register the Custom JET Component. This little script pulls together all of the artifacts that we have already referenced and uses them to register the component with the framework. Without this script, nothing would happen! You've seen this already, it's that loader reference that you added to the appController.js to test the component. Have a look at it now, again it can be found in the js/jet-composites/ccdemo-name-badge directory and will look like this (Again if you use older versions this may look slightly different but just go with what is generated for you): define(['ojs/ojcomposite',   'text!./ccdemo-name-badge-view.html',   './ccdemo-name-badge-viewModel',   'text!./component.json',   'css!./ccdemo-name-badge-styles'], function(Composite, view, viewModel, metadata) { Composite.register('ccdemo-name-badge', { view: view, viewModel: viewModel, metadata: JSON.parse(metadata) }); } ); Because this script is so important to the functioning of the Custom JET Component, it's worth examining it in a little more depth. Looking at the define block first of all, you can see that it defines a requirement for each of the four previous files: 'text!./ccdemo-name-badge-view.html' → the HTML template loaded using the requireJS text plugin './ccdemo-name-badge-viewModel' → viewModel.js which defines the component model 'text!./component.json' → the component metadata file, also loaded using the requireJS text plugin 'css!./ccdemo-name-badge-styles' → the styles.css file loaded using the requireJS css plugin You can see from the above why it is so important to ensure that you have the text and css plugins defined for requireJS at the very start. These scripts and streams are injected into the bootstrap function as view, viewModel and metadata respectively (the css file is actually loaded by the css! plugin so we don't need to do anything further with that). You are free to change the names of these function arguments of course, but using these names makes it pretty clear what each one will do. Within the bootstrap function, the code makes the all important call to Composite.register(). (or oj.Composite.register on versions prior to JET 6). This function does all the actual work of registering the Custom JET Web Component with the framework. The first argument to the register function is name name that you want to assign to the tag - in this case ccdemo-name-badge. This name does not have to really match the name of the directory we have created as a home for the component or indeed the names we have used for the various files. However, it keeps everything much more organized and understandable if your component name matches the directory name that defines it, so there is no reason not to stick to this standard. The second argument to the register function takes an object which as we see here has four attributes: metadata viewModel view css (deprecated in JET 4.1.0 - not needed) Each of these is mapped to the corresponding objects passed into the main bootstrap function. Note how the metadata value is mapped through JSON.parse(). This is because the requireJS text plugin has just been used to read this file and we need to convert from text stream that that produced back into a JS object. In version of JET prior to JET 5.0 you may also note that each of the above attributes are passed the injected file contents as an object with an attribute name of inline e.g. viewModel: {inline: viewModel}, This is simply telling the component registration process that the passed object is the actual value that it should use for that attribute. In that older version it was  possible to pass a promise rather than the object directly, however, that is a legacy option and should not be used. There is more that can happen as part of the registration process, but really, this simple version is all that most Custom JET Components will need, so I'll leave it there. Testing the Updated Component So now that our ccdemo-name-badge is "complete" we can test it again in the application. All we need to do is to set the two new properties on the tag: <ccdemo-name-badge badge-name="Duke Mascot" badge-image="/images/duke.png"> </ccdemo-name-badge> Note: You'll notice here how the tag attributes are different from the defined property name. I explain this more in later articles, but the basic rule is that camel-case property names are converted into case-insensitive HTML element attributes with hyphens at the camel-case break point of the original name. Thus badgeName gets mapped to an HTML element attribute called badge-name. Now run the application again using ojet serve, and this is what you would see: What Next? Now that you've seen how to create a basic Custom JET Component we can start to drill down and explore various sub-topics in more detail. The next article in this series spends a little time on establishing your standards and conventions for creating components. JET Custom Component Series If you've just started with Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path 1 The version numbers shown in the fragment above are reflective of the Oracle JET 6.0.0 release and may well be different if you are consuming a different version. 2 This component is not intended to be actually useful, just to show the basics.

Last Updated Dec 2018 for JET 6 Introduction In this primer article on Custom JET Web Components (aka JET Composites or CCA), I'll just be looking at the basic tasks involved in creating a simple custom...

JET

JET Custom Components I - Backgrounder

Last Updated Dec 2018 for JET 6 Over the following series of articles I'll be describing the Custom JET Component Architecture, showing how you can create your own components to boost re-use and generally streamline your code-base. However, before we dive into the technicalities I think that it would be a good idea to set the scene a little and provide you with some background. What's The Point Of A Component Model? Before we even start, it's worth asking this question, after all, we're already dealing with a nicely structured and standardized language in the form of HTML markup. Isn't adding our own components kinda going against the whole idea and a retrograde (and therefore bad) step? Simply put no. The need for a custom component model within HTML is well established and as such is the subject of a W3C initiative under the umbrella of Web Components. However, as is often the way of these things, the specifications are as yet (at the time of writing), not fully complete and ratified and we're in a situation where browser support is incomplete as a result (see here). If you want to learn about Web Components in a slightly more accessible way than W3C Specifications then there are plenty of good sites out there. A good place to start, however, is webcomponents.org. OK But I Still Don't Get Why I Might Find It Useful... Fair enough, why is it useful? Well it's all to do, with the original intended use for HTML verses what we actually use it for. HTML was designed to markup text documents that deliver content and images for consumption and provides all of the useful semantic tags to do document-y stuff like defining headings at various levels, paragraphs, footers navigation to other documents and so on. However we're mostly not using it for that, at least, not in the context of a typical JET application, we're generally building interactive Applications not just authoring content to read. We'll still use many of those tags but the core of our code is going to be a whole set of nested <div> elements with various classes applied to lay things out and apply a certain UX over the top. An example of what I mean here can be seen in the JET Cookbook. If you take the simple case of the input field and it's associated label from the particular cookbook demo that I've pointed at, you can see that this is defined as follows: <div class="oj-flex"> <div class="oj-flex-item"> <label for="control1">row 1</label> </div> <div class="oj-flex-item"> <oj-input-text id="control1" value="{{somevalue}}" required="true"></oj-input-text> </div> </div> In this example, although we're using the standard HTML elements for providing a label and an input field we've got no less that three <div> elements cluttering up the markup just to perform the layout housekeeping. Now this of course is a very simple example and in reality, the number of housekeeping / control divs in your view can easily creep up into the hundreds. Frankly it's just hard for us to read and mentally parse. Imagine instead the same content in our view was represented as something like the following: <my-input input-value="{{someValue}}" input-label="row 1" required="true"/> I think that we can all agree that this is really much easier to understand when you just read the page! Of course componentization is not just about making the elements in your views easier to read. It provides the mechanisms for enforcing standardization of UI and behavior, reducing the complexity of your day to day development efforts (build and test once, use many times) and of course you have the ability to change the component in one place and have that change automatically reflected by all the consuming pages. A final key point about the importance of Custom JET Components in particular is that they are positioned as the standard mechanism for plugging into the Oracle ecosystem. Once you have created a component, not only will you be able to use it directly in your JET applications, but also in our low-code development tool, Visual Builder Cloud Service, and use them to extend our SaaS applications. (usual caveats apply with respect to the truthfullness and timing of this statement). As such, mastery of Custom JET Component creation will be a key skill-set for Oracle UI developers and partners going forward. What Next? So now that we've established that there is some value in introducing some sort of componentization into our developments we can proceed, in subsequent articles, with learning how to do this using JET . To get you started, go and have a look at the demos in the cookbook for this feature area. These, along with the JS doc provide some great examples of composite components in action, starting with basic demo. Figure 1: A screenshot from the Basic Composite Component Demo in the JET Cookbook If that all looks a little scary and confusing though, don't worry, in the following series of articles I'll be taking you through Custom JET Components step by step, from the very basic, almost code-less components to advanced usages, exploration of the nuances of lifecycle and more. A Summary of What Custom JET Components Give You As you progress through this series you will pick all this up, but to summarize for you now, JET Custom Components give you: A way to define custom HTML elements for use in your application, providing: Custom attributes for the element Custom methods on the element Custom events emitted from the element Function callbacks An encapsulation of all the resources needed to create this tag / element: Template HTML markup JavaScript to drive the component Styles to configure the UX Support for nesting of components Support for injection of application markup into the component (a feature called slotting which I'll discuss in detail in a later article) Lifecycle methods to control the component But Before You Start... Throughout this series of articles I'll be assuming a certain baseline skillset, mainly, but not restricted to, RequireJS and JavaScript promises. So if you've not mastered those concepts yet, you would be best to hold off diving into creating components until you are comfortable with those pieces. I'll also assume that you're familiar with using JET itself of course. With that, if you are ready then proceed to Part II to look at some of the basics. JET Custom Component Series If you've just started with Custom JET Components and would like to learn more, then you can access the whole series of articles on the topic from the Custom JET Component Learning Path

Last Updated Dec 2018 for JET 6 Over the following series of articles I'll be describing the Custom JET Component Architecture, showing how you can create your own components to boost re-use and...

ADF Faces and UI

Method References and <af:declaritiveComponent>

The <af:declarativeComponent> tag, for those of you not familiar with it, is a super convenient way of defining a reusable component for your ADF UIs. In principle, it's very similar to the template tag in that it allows you to define named attributes and facets for the component you are assembling and then you just build a .jsff fragment in your project which contains the implementation that you want for the component.  Note that this tag is different from the kind of declarative component that  you get when you choose ADF Declarative Component from the JSF/Facelets section of the new gallery. With that option you will be creating a tag of your own in a new namespace, which is all a bit more work, although more flexible for all that.  Now although once you get down to it the creation of both types of component are broadly similar, there are two core differences between <af:declarativeComponent> and the custom component approach: With a custom component you can implement a Java class to help in the operation of the component With a custom component you can define methods on the tag you are generating as well as attributes and facets  This means that often, for a really well-formed and functional custom declarative component, you have to go for the more complex solution to get the functionality needed.   The good news is, however, that there is a sneaky way of overcoming difference (2) at least - defining a method for the component. Thanks and all credit to Andy Schwartz from the JSF team for this hint.  The core thing to understand is that the <af:declaritiveComponent> tag is just a wrapper and any attributes that you set on the tag will be available to the embedded components within the tag via the "#(attrs.} EL root. What Andy pointed out that, although you can't formally define a listener method as part of the <af:declarativeComponent> API, what you can do is pass in the reference to the managed bean that hosts a listener and the name of the listener or action method itself in as normal "properties" to the component. Thus you could do this: <af:declarativeComponent id="dc1" viewId="/mycomponent.jsff" methodBean="#{myBeanWithMethod}" actionMethod="handleSave"/> Then inside the body of the  "/mycomponent.jsff" implementation you could bind a control listener or action thus: <af:button id="cb1" text="Save" action="#{attrs.methodBean[attrs.actionMethod]}" />  And the EL assigned to the action property in this case will magically resolve to a methodExpression. And as long as the method name that you supply maps to the correct signature you can use this for any listener type as well as just action properties. Neat!

The <af:declarativeComponent> tag, for those of you not familiar with it, is a super convenient way of defining a reusable component for your ADF UIs. In principle, it's very similar to the template...

ADF Faces and UI

Pattern For Obtaining ADF Component ID for JavaScript

The following article outlines a technique that I use and has been buried in various code samples in the past.  However, in light of the explicit how-to being asked a couple of times recently, it seems sensible to pull it out into a explicit article.  Now the scenario here is when you have a piece of JavaScript that needs to operate on a specific client side component. Now in many cases, you will be able to obtain the component that you need by simply calling the getSource() function on the event object that is passed to the function invoked by your <af:clientListener>. In other cases, given that same component reference you can walk up or down the component tree to find the component you need.  However, there are certainly circumstances where you need to grab a component which is kinda outside of the context and it would be much easier if you could just pass in the ID of the component and use the findComponent JS APIs to grab it. The problem is of course that the ID you use for say a button (let's work with "b1" as an example) is of course not the real ID that would be used on the client to identify the component.  The full ID is going to depend on the various JSF naming containers that the component is nested within.  So our button b1 may end up being identified by something like "tmplt1:r1:b1".  So the question is, how can you easily obtain that full contextual calculated ID in a just-in-time manner so that your JavaScript can call the AdfPage.PAGE.findComponentByAbsoluteId() function to get its client side handle? The pattern for doing this is pretty simple - you need to do just 5 things: Step 1 On the component that  needs to be referenced from JS, remember to set clientComponent="true" You'd be amazed how often this is forgotten and leads to much hair pulling out as you just *know* that the client ID is correct but it's not being found! Step 2 Likewise on the same tag you need to set the binding property so that you can obtain the reference to the component. So for example let's assume we create a backing bean class and set that up. e.g. <af:button id="b1" clientComponent="true" binding="#{backingBeanScope.examplePage.clientButton}"> This would then correspond to the following the backing bean class:  private ComponentReference clientButton; public void setClientButton(RichButton clientButton){ this.clientButton = ComponentReference.newUIComponentReference(clientButton); } public RichButton getClientButton(){ if (clientButton != null){ return (RichButton)clientButton.getComponent(); } else{ return null; } } Step 3 Create a new function in the same backing bean that calls the getClientId() function on the Java reference to the button.  This returns us the full calculated id, including the path defined by any templates, regions or other naming containers.   public String getClientButtonClientId(){    FacesContext ctx = FacesContext.getCurrentInstance();    return this.getClientButton().getClientId(ctx);  } Step 4 Now we have a way of getting the correct clientId it needs to be made available to JavaScript, to do this we use an <af:clientAttribute> co-located with the <af:clientListener> that will be triggering the JS. So imagine in this case we have a second button that needs to reference our "b1" button: <af:button text="Invoke Client Operation" id="b2">  <af:clientListener method="doSomeClientOp" type="action"/>  <af:clientAttribute name="b1ClientId" value="#{backingBeanScope.examplePage.clientButtonClientId}"/></af:button>  So we are passing the full String representation of the client ID for b1 via the attribute called "b1ClientId". Step 5 All that remains is for the JavaScript function that is being called to get hold of this b1ClientId value that is being passed in (add error handling of course). function doSomeClientOp(actionEvent){  var actionComp = actionEvent.getSource();  var b1ClientId = actionComp.getProperty("b1ClientId");   var b1ComponentRef = AdfPage.PAGE.findComponentByAbsoluteId(b1ClientId);  ...}  Additional Thoughts In the steps here, I have used the pattern of utilizing the binding attribute on the component to provide the Java-side component handle.  However, there are of course other ways of getting hold of this reference (e.g. see my previous article Locating JSF components by ID).  The important thing here is the use of the getClientId() api to obtain the correct client ID encoding from the Java component and then making that available in JavaScript.

The following article outlines a technique that I use and has been buried in various code samples in the past.  However, in light of the explicit how-to being asked a couple of times recently, it...

ADF Faces and UI

Locating JSF components by ID

An occasional problem for developers using JSF is how to locate a component given just it's ID. Now if you have the complete ID, which includes the computed location, for example:Button B1 inside Region R1 inside page with template PT1 ==> PT1:R1:B1, you can hardcode that using the basic findComponent() API, or even better use the invokeOnComponent() API provided by the UIComponentBase (see the JavaDoc for more information).  However, what it you have no idea, at the time of writing the code, what the context is that the component that you want will be used in?  In that case, the only information that you might have is the basic ID of the component and you know nothing of the naming containers that contribute to the full unique ID.  In this scenario I've seen a lot of examples where developers fall back to recursion. i.e. They grab the viewRoot from the FacesContext, get it's children, check to see if any of those children has the correct ID, if not they then get the children of each of those and check those and so on.There is, however, a much neater, and more efficient way of doing this using the JSF 2.0 visitTree API. With the visitTree API, in a similar way to the invokeOnComponent() API, you provide a callback inner class which implements a visit() method. This method is processed for each component in the component tree. You then have the ability to control how the tree is traversed based on the return value that you provide from that visit method.The valid return values are: VisitResult.COMPLETE - stop the traversal all together VisitResult.ACCEPT - continue with the traversal VisitResult.REJECT - stop traversal for the current subtree, but continue with the rest So here's a simple example of a helper method to invoke a ActionEvent on a commandItem such as <af:button> given just the basic id of that button. This might be the kind of thing you would want to do in a serverListener callback being invoked from a client side customEvent. private static boolean queueActionOnCommandComponmentById(String commandId) { if (commandId != null && commandId.length() > 0) {  final String candidateId = commandId;    FacesContext ctx = FacesContext.getCurrentInstance();    VisitContext visitContext = VisitContext.createVisitContext(ctx);    return UIXComponent.visitTree(visitContext, ctx.getViewRoot(), new VisitCallback(){    public VisitResult visit(VisitContext context, UIComponent component) {      try {        if (component instanceof UIXCommand && component.getId().equals(candidateId)) {          ActionEvent cmdEvent = new ActionEvent(component);            cmdEvent.setPhaseId(PhaseId.INVOKE_APPLICATION);            cmdEvent.queue();            return VisitResult.COMPLETE;          }          return VisitResult.ACCEPT;        } catch (Exception e) {        e.printStackTrace();          return VisitResult.COMPLETE;        }      }    });  }        _logger.warning("Empty or null command component ID provided, no event queued");        return false;}  Of course this is a trivial example, and suffers like any of these techniques, from the risk that you might conceivably have more than one component with the same basic ID, so in this case I'd be sure that the ID assigned to the command button as already pretty unique. However, more complex uses of this traversal approach may be touching multiple components and that's where it really comes into it's own. Anyway, I hope you get the message, never use the getChildren() recursion technique, use visitTree() instead. 

An occasional problem for developers using JSF is how to locate a component given just it's ID. Now if you have the complete ID, which includes the computed location, for example:Button B1 inside...

ADF

Using a Translatable String as the Default Value for a Bind Variable

I've just been looking at a scenario where we needed to populate an ADFBC query bind variable using a predefined value. Now that in itself is not difficult - the bind variable definition takes a default value exactly for this, however, in this case the value supplied as the default needed to be read from the locale specific resource bundle. I wondered here if it would be possible to convert the default value for the bind to be an expression rather than a literal and use groovy to derive the translated string? Well it took a little bit of time to come up with the correct path, but indeed it turns out to be possible with one small constraint about the keys in the bundle that have to be used. So to start off, here's the groovy expression I use in the default value for the bind variable:  source.viewObject.getProperty('TRANSLATABLE_BINDVAR') That expression refers to a translatable property called TRANSLATABLE_BINDVAR defined in the relevant View Object as a custom property (General finger tab, Custom Properties section). this, in turn, maps to a resource in the bundle with a key generated from the full name of the View Object + property name + "_VALUE". e.g. in this case: oracle.adf.demo.model.ValueFromBIndVO.TRANSLATABLE_BINDVAR_VALUE This is the resource that you can then translate and the value of which will be used at runtime. An Explanation  So what does this all mean? Unfortunately there is no way (that I've found) in groovy to reach directly into the ui hints of the bind variable itself If you start the expression with adf.object to start from the variable itself you can't really get anywhere.  So instead, we have to walk up the component hierarchy to the View Object that owns the bind variable and then get the resource from there. Just asking for the value of the custom TRANSLATABLE_BINDVAR property.  By using a translatable custom property for this, the developer has an existing UI to use that will create the resource keys for them. Furthermore, because we use the getProperty() API on the View Object  as an indirect way of getting the value, rather than using ResourceBundle APIs, we don't have to worry about finding out what locale to use - that's all handled automatically.

I've just been looking at a scenario where we needed to populate an ADFBC query bind variable using a predefined value. Now that in itself is not difficult - the bind variable definition takes...

ADF

Showing Initial Selection in Your ListView

If you use a ListView or a Table component which enables selection by the user in a master detail view you may feel that there is a slight inconsistency of behaviour. When the user first enters the screen it may, by default, look something like this (in this example a ListView to the left and the "selected" department detail to the right in a form layout): Notice that the associated detail form is showing the first row in the collection as you would expect, but visually, the corresponding row in the ListView is not visually highlighted. Compare that with what happens when the user clicks on a row in the ListView to select another row: Now the selected row in the listView is highlighted with the skin's selection colour. So the question is, how can we show the page initially in a manner consistent with this?e.g. Well in fact the binding layer already has everything you need and it's a trivial thing to fix. All we have to do here is to set the selectedRowKeys attribute of the listView tag. So, assuming we have a listView showing departments the tag would look something like this: <af:listView value="#{bindings.DepartmentsView1.collectionModel}"              var="item"             selectedRowKeys="#{bindings.DepartmentsView1.collectionModel.selectedRow}"              selection="single"              selectionListener="#{bindings.DepartmentsView1.collectionModel.makeCurrent}"             emptyText="#{bindings.DepartmentsView1.viewable ? 'No data to display.' : 'Access Denied.'}"             fetchSize="#{bindings.DepartmentsView1.rangeSize}"              id="lv1"> Doing It From Scratch So this is an example where the binding layer does everything for you, great! However, what wanted to do this manually? I'm showing you this because it happens to illustrate a few useful techniques and code snippets.  In general I'd stick with the simple approach above though!  Setting this up requires some simple steps and a small amount of code, so let's go. Step 1: Defining the Selected Row Keys The core mechanism of this solution is to pre-seed the selectedRowKeys property of the listView component with the row key of whichever row is current in the underlying collection.  So the first step is to define somewhere to hold that row key set. So we start by defining a ViewScope managed bean (called lvState in this example) and within that, we just define a variable to hold a RowKeySet reference. So we start with the Java class: package oracle.adf.demo;import org.apache.myfaces.trinidad.model.RowKeySet;public class ListViewState { RowKeySet _selectedRowKeys; public void setSelectedRowKeys(RowKeySet rks) { this._selectedRowKeys; = rks; } public RowKeySet getSelectedRowKeys()  { return _selectedRowKeys; }} And define that as a managed bean in the relevant task flow definition: <managed-bean>   <managed-bean-name>lvState</managed-bean-name>   <managed-bean-class>oracle.adf.demo.ListViewState</managed-bean-class>   <managed-bean-scope>view</managed-bean-scope></managed-bean> Once that's defined you can update your <af:listView> tag to reference it: <af:listView value="#{bindings.DepartmentsView1.collectionModel}"              var="item"             selectedRowKeys="#{viewScope.lvState.selectedRowKeys}"              selection="single"              selectionListener="#{bindings.DepartmentsView1.collectionModel.makeCurrent}"             emptyText="#{bindings.DepartmentsView1.viewable ? 'No data to display.' : 'Access Denied.'}"             fetchSize="#{bindings.DepartmentsView1.rangeSize}"             id="lv1">  Step 2: Pre-Seeding the Row Key Set  As defined, the row key set picked up by the listView will of course be null until the user physically makes a selection - we're no better off than before. So we now have to work out a way of taking the current selection from the model / binding layer, obtaining it's key and then setting up the row key set before the listView is rendered. The simplest way of doing this is to utilise the capability of JSF 2 to simply define events to be executed as the page is being set up for rendering. In this case we use the postAddToView event inside of the listView to execute the setup code: <af:listView ...>  <f:event type="postAddToView" listener="#{lvEvents.setupListViewSelection}"/>  <af:listItem ...> The event tag points at a request scope managed bean called lvEvents.  This bean needs access to the lvState managed bean that we defined in the first step: <managed-bean>  <managed-bean-name>lvEvents</managed-bean-name>  <managed-bean-class>oracle.adf.demo.ListViewEventManager</managed-bean-class>  <managed-bean-scope>view</managed-bean-scope>  <managed-property>    <property-name>state</property-name>    <property-class>oracle.adf.demo.ListViewState</property-class>    <value>#{lvState}</value>  </managed-property></managed-bean> The ListViewEventManager class should therefore have a variable to hold the state with the appropriate getter and setter: public class ListViewEventManager {  ListViewState _state;    public void setState(ListViewState _state) {        this._state = _state;    }    public ListViewState getState() {        return _state;    }    ... Finally, the implementation of the listener defined in the <f:event> tag needs to be added to the class: public void setupListViewSelection(ComponentSystemEvent componentSystemEvent) {  if (getState().getRks() == null) {     BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();     DCIteratorBinding iterBind =                ((DCBindingContainer)bindings).findIteratorBinding("DepartmentsView1Iterator");            Key key = iterBind.getCurrentRow().getKey();            RowKeySet rks = new RowKeySetImpl();            rks.add(Collections.singletonList(key));            getState().setRks(rks);        }}     So now, when the page renders, if the selection row key set has not been setup due to user interaction we will go ahead and create it, seeding the rowkey of whatever row the model considers to be current.

If you use a ListView or a Table component which enables selection by the user in a master detail view you may feel that there is a slight inconsistency of behaviour. When the user first enters the...

ADF

Ensuring High Availability in ADF Task Flows

Just a quick article today on ADF Controller Scopes and specifically ensuring that your application is correctly propagating state stored in PageFlow and View Scope across the cluster. This information can be found in the product doc and in Jobinesh Purushothaman's excellent book (Chapter 12 - Ensuring High Availability), however, more references means more eyes and fewer mistakes!   Some Background When you store state in a managed bean scope how long does it live and where does it live?  Well hopefully you already know the basic answers here, and for scopes such as Session and Request we're just dealing with very standard stuff. One thing that might be less obvious though, is how PageFlow and View Scope are handled.  Now these scopes persist (generally) for more than one request, so there is obviously the possibility that you might get a fail-over between two of those requests.  A Java EE server of whatever flavour doesn't know anything about these extra ADF memory scopes so it can't be automatically managing the propagation of their contents can it?  Well the answer is yes and no.  These "scopes" that we reference from the ADF world are ultimately stored on the Session (albeit with a managed lifetime by the framework), so you'd think that everything should be OK and no further work is going to be needed to ensure that any state in these scopes is propagated - right?  Well no, not quite, it turns out that several key tasks are often missed out. So let's look at those. First of All -  Vanilla Session Replication Assuming that WebLogic is all configured, this bit at least is all automatic right? Well no. In order to "know" that an object in the session needs to be replicated WebLogic relies on the HttpSession.setAttribute() API being used to put it onto the session. Now if you instanciate a managed bean in SessionScope through standard JSF mechanisms then this will be done and you're golden.  Likewise if you grab the Faces ExternalContext and grab the Session throught that (e.g. using the getSession() API), then call the setAttribute() API on HttpSession, you've correctly informed WebLogic of the new object to propagate. You might already see though, that there is a potential problem in the case where the object stored in the session is a bean and you're changing one of its properties. Just calling an attribute setter on an object stored on the session will not be a sufficient trigger to have that updated object re-propagated, so the version of the object elsewhere will be stale.  So when you update a bean on the session in this way, and want to ensure that the change is propagated, then re-call the setAttribute() API.    Got it? OK, on to the ADF scopes: Five Steps to Success For the ADF Scopes  The View and PageFlow scopes are, as I mentioned, ultimately stored on the session.  Just as in the case of any other object stored in that way,  changing an internal detail of those representaive objects would not trigger replication. So, we need some extra steps and of course we need to observe some key design principles whilst we're at it: Observe the UI Manager Pattern and only store state in View and PageFlow scope that is actually needed and is allowed (see 2) As for any replicatable Session scoped bean, any bean in View or PageFlow scope must be serializable (there are audits in JDeveloper to gently remind you of this). Only mark for storage that which cannot be re-constructed. Again a general principle; we wish to replicate as little as possible, so use the transient marker in your beans to exclude anything that you could possibly reconstruct over on the other side (so to speak).  In the setters of any attributes in these beans (that are not transient) call the ControllerContext markScopeDirty(scope) API. e.g. ControllerContext.getInstance().markScopeDirty(AdfFacesContext.getCurrentInstance().getViewScope());   This does the actual work of making sure that the server knows to refresh this state across the cluster Finally, set the HA flag for the controller scopes in the .adf/META-INF/adf-config file. This corresponds to the following section inside of the file: <adf-controller-config xmlns="http://xmlns.oracle.com/adf/controller/config">  <adf-scope-ha-support>true</adf-scope-ha-support></adf-controller-config>  If this flag is not set, the aforementioned markScopeDirty() API will be a no-op. So this flag provides a master switch to throw when you need HA support and to avoid the cost when you do not.  So if you've not done so already, take a moment to review your managed beans and check that you are really all doing this correctly. Even if you don't need to support HA today you might tomorrow... 

Just a quick article today on ADF Controller Scopes and specifically ensuring that your application is correctly propagating state stored in PageFlow and View Scope across the cluster. This...

ADF

Maven and ADFBC Unit Tests in 12.1.3

An issue that has come up recently has revolved around setting your Maven POM up in 12.1.3 such that you can run ADF BC JUnit Tests successfully both interactively in the IDE and headless through Maven maybe in your Hudson Jobs.  Out of the box, the default POM that you will end up with will be missing a couple of vital bits of information and need a little extra configuration. Here are the steps you'll need to take: Step 1: Use The Correct JUnit Dependency Once you have created some unit tests JDeveloper will have added dependencies for JUnit from the JDeveloper JUnit extensions, something like this: <dependency> <groupId>com.oracle.adf.library</groupId>  <artifactId>JUnit-4-Runtime</artifactId>  <version>12.1.3-0-0</version>  <type>pom</type>  <scope>test</scope></dependency><dependency>  <groupId>com.oracle.adf.library</groupId>  <artifactId>JUnit-Runtime</artifactId>  <version>12.1.3-0-0</version>  <type>pom</type>  <scope>test</scope></dependency>  Delete both of these entries, if they exist, and drop in a dependency to the vanilla JUnit 4.11 library instead: <dependency> <groupId>junit</groupId>  <artifactId>junit</artifactId>  <version>4.11</version>  <type>jar</type>  <scope>test</scope></dependency>  Failing to make this change will result in the following error: java.lang.NoClassDefFoundError: org/junit/runner/notification/RunListener  Step 2: Configure the Surefire Plugin to Select the Correct JUnit Version This is probably not needed but it ensures that Surefire is left in no doubt about what version of JUnit it shoudl be working with (in this case a version of 4.7 or higher): <plugin> <groupId>org.apache.maven.plugins</groupId>  <artifactId>maven-surefire-plugin</artifactId>  <version>2.17</version>  <dependencies>  <dependency>    <groupId>org.apache.maven.surefire</groupId>      <artifactId>surefire-junit47</artifactId>      <version>2.17</version>    </dependency>  </dependencies></plugin> Step 3 : Identifying Your connections.xml File  When running outside of JDeveloper we need to set things up so that  the unit tests can actually find the connection information that defines the datasource that your Application Modules are using.  To do this, we need to add a configuration section to the  Surefire plugin to add the location into the classpath.  Add the collowing configuration into the Surefire plugin, after the <dependencies>  section: <configuration> <additionalClasspathElements>  <additionalClasspathElement>    ${basedir}/../.adf    </additionalClasspathElement>  </additionalClasspathElements></configuration>  This will ensure that the connection information can be found.  If you forget this step you'll get a stack trace including the message: MDS-00013: no metadata found for metadata object "/META-INF/connections.xml"  Step 4 - Supply the Missing JPS Library Finally we need to supply the location of one extra required library.  This requirement will hopefully be resolved in the next release, but for now add it.  Again this is added to the Surefire plugin configuration <additionalClasspathElements>  <additionalClasspathElement> ${oracleHome}/oracle_common/modules/oracle.jps_12.1.3/jps-manifest.jar</additionalClasspathElement>  Omitting this will result in the error: WARNING: No credential could be loaded for Reference = Reference Class Name: oracle.jdeveloper.db.adapter.DatabaseProvider For reference here's the complete Surefire plugin definition  <plugin> <groupId>org.apache.maven.plugins</groupId>  <artifactId>maven-surefire-plugin</artifactId>  <version>2.17</version>  <dependencies>  <dependency>    <groupId>org.apache.maven.surefire</groupId>      <artifactId>surefire-junit47</artifactId>      <version>2.17</version>    </dependency>  </dependencies>  <configuration>  <additionalClasspathElements>    <additionalClasspathElement>      ${basedir}/../.adf      </additionalClasspathElement>      <additionalClasspathElement>        ${oracleHome}/oracle_common/modules/oracle.jps_12.1.3/jps-manifest.jar      </additionalClasspathElement>    </additionalClasspathElements>  </configuration></plugin> 

An issue that has come up recently has revolved around setting your Maven POM up in 12.1.3 such that you can run ADF BC JUnit Tests successfully both interactively in the IDE and headless through...

ADF

Per-Component Instance Skinning

A question that comes up from time to time happened to be raised twice three times this week, so I though it would be good to write the answer down.  The question is this; How can I override the visual properties of a single instance of a component?  Now in many cases you can simply use inlineStyle or, (better) assign a styleClass to the component instance and associate a CSS file with the page using <af:resource>.  This will work in the simple case where, for example, it's a basic component such as an <af:spacer> or <af:panelGroupLayout layout="vertical">.  However, in the case of a more complex component you may not get the fidelity through inlineStyle, styleClass or even contentStyle.  In these cases you will need to extend the skin to create a instance selector for the component type.  This will allow you to change any skinning slector, but rather than doing so for every instance of the component, you will end up with a sub-type that can be applied to just those instances that require it. All you have to do here is to extend the skin as per normal (just create a new skin in 12.1.3 and all the metadata will be set up for you in the trinidad-skins.xml file). In the skin you define a custom style class and then append the selector that you want to change.  So for example, here's a custom version of one of the commandMenuItem selectors that sets a specific background: .saveMenu af|commandMenuItem::menu-item-icon-style {    background-image:url("images/save.png");    background-repeat:no-repeat;} And that's then applied to the menu item in question: <af:commandmenuitem text="save" styleclass="saveMenu"> That's it, pretty simple but can be useful

A question that comes up from time to time happened to be raised twice three times this week, so I though it would be good to write the answer down.  The question is this; How can I override the...

ADF

Customizing the Axis Labels in ADF Graphs

The various data visualization (DVT) graphs provided as part of the ADF Faces component set provide a very rich and comprehensive set of visualizations for representing your data.  One of the issues with them, that some folks struggle with however, is the fact that not all the features are controlled in an a completely declarative manner.  In this article I want to concentrate on labeling capabilities for a graph axis, looking first of all that the declarative approaches, but then following that up with the more advanced programmatic option.  Managing Labels Declaratively  Control over the labels on the axis tick points is a good example of making the simple things declarative and the advanced things possible.  For basic numeric formatting you can do everything with tags - for example formatting as currency, percentage or with a certain precision.     This is a default (bar)graph plotting employee salary against name, notice how the Y1 Axis has defaulted to a fairly sensible representation of the salary data using 0-14K: I can change that default scaling by setting the scaling attribute in the <dvt:y1TickLabel> tag. This allows scaling at the level of none | thousand | million | billion | trillion | quadrillion (enough to show national debt then!): <dvt:y1TickLabel id="y1TickLabel1" scaling="none"/> Changes the graph to: We can then further change the pattern of the numbers themselves by embedding <af:convertNumber> inside of the <dvt:y1TickLabel> tag. e.g. <dvt:y1TickLabel id="y1TickLabel1" scaling="none"> <af:convertNumber type="currency" currencyCode="USD"/></dvt:y1TickLabel>  Adds currency formatting: And using the <dvt:graphFont> we can change colors and style: <dvt:y1TickLabel id="y1TickLabel1" scaling="none">  <dvt:graphFont name="SansSerif" size="8" color="#FF0000" bold="true" italic="true" /> <af:convertNumber type="currency" currencyCode="USD"/></dvt:y1TickLabel>  Giving: Need More Control?  Using the TickLabelCallback... So we can achieve quite a lot by simply using the tags.  However, what about a more complex requirement such as replacing a numerical value on an axis with a totally different string e.g. converting to a Roman Numeral (I, IV XII etc.) or maybe converting a millisecond value to a formatted date string?  To do this, ADF provides a simple callback that you can implement to map a value to whatever string you need.  Here's a simple case where I've plotted the salaries in department 100 of the standard HR EMPLOYEES demo table against the HireDate on a scatter plot.  For the sake of illustration I've actually converted the HireDate to it's time value (e.g. a long value representing the number of milliseconds since 01/01/1970) .  In a real graph I'd use the proper support that we have for representing time and date and just map a date object. Then you get to use the timeSelector and can directly set the formatting, however, bear with me because I'm just illustrating the point here. Here's the default output with the millisecond version of the date, as you can see the millisecond value gets automatically scaled to the billions level. To override the default representation of the millisecond value we will need to create a java class that implements the oracle.dss.graph.TickLabelCallback interface.  Here's the simple example I'll use in this case: import java.text.SimpleDateFormat;import oracle.dss.graph.DataTickLabelInfo;import oracle.dss.graph.GraphConstants;import oracle.dss.graph.TickLabelCallback;import oracle.dss.graph.TickLabelInfo;public class MSToDateFormatLabelCallback implements TickLabelCallback, Serializable {  @Override  public String getTickLabel(TickLabelInfo tickLabelInfo, int axisID) { String label = null;   if (axisID == GraphConstants.X1TICKLABEL) {    long timeInMillis = (long) ((DataTickLabelInfo) tickLabelInfo).getValue();      SimpleDateFormat fmt = new SimpleDateFormat("MM/yy");      label = fmt.format(timeInMillis);    } else {      label = "" + ((DataTickLabelInfo) tickLabelInfo).getValue();    }    return label;  }}  As you can see the formatting  is applied only to the specified axis and we have to upcast the tickLabelInfo argument to a DataTickLabelInfo in order to gain access to the value that is being applied. Note that the callback class must also be Serializable.  Once you have this class, then you need to apply it to the chart instance by calling the relevant set*TickLabelCallback. So for example I might set this in the backing bean for a page in the setter used by the binding attribute on the dvt graph component public class GraphPageHandler {    private UIGraph scatterPlot;    public void setScatterPlot(UIGraph scatterPlot) {        this.scatterPlot = scatterPlot;        scatterPlot.setX1TickLabelCallback(new MSToDateFormatLabelCallback());    }  Now with the callback in place and the addition of: Using  the axisMinValue attribute along with axisMinAutoScaled="false" on the <dvt:x1Axis>  to reset the start date for the plot to the year 2000 rather than the default 1970 Some of the currency formatting that we've already looked at to format the Y axis Here's the result:

The various data visualization (DVT) graphs provided as part of the ADF Faces component set provide a very rich and comprehensive set of visualizations for representing your data.  One of the issues...

ADF

Programmatic UI Scrolling in ADF Faces

I've been dealing with a use case recently where we needed to synchronize two panels in a user interface, where (in the simple version) selecting an object on one side of the screen would also select a corresponding object in a scrolling area on the other side of the screen and scroll in into view.  the scrolling panel in this case being a panelGroupLayout / scroll, not a table. Declarative  scrolling is really simple, you can drop a UI element such as commandButton onto the page and then nest, within that, the behavior tag <af:scrollComponentIntoViewBehavior>. This tag is great if you have a long page and want to provide the users with a way to navigate to different sections, however, it needs to be wired to a command component and the user needs to physically invoke the operation. In this case, everything needed to happen in reaction to a series of complex programmatic events and so, the use of the behavior tag did not cut it.  So I did a small amount of testing to see if it was possible to achieve the same result in a hands off fashion from within java code. It turns out to be pretty simple to do, but there are different approaches depending on your version: Programatic Scrolling in 11.1.2.n and 12c In the newer versions of ADF this issue is addressed head on with a new API on the AdfFacesContext -> scrollComponentIntoView(component, focus);  This API takes a UIComponent reference for the component to scroll to, and the second argument is a boolean flag to indicate if the component should take focus as well (for example if it was an input field).   Programatic Scrolling in 11.1.1.n  Prior to ADF Faces 11.1.2 the handy  scrollComponentIntoView() api does not exist, however, we can acheive the same effect using some JavaScript. (Note if you are on a version of ADF that does support the scrollComponentIntoView() Java API then use that, not this.) As with the behavior tag, you need to do two things. The target component has to have clientComponent="true" as this scrolling operation all takes place on the client You need the full id of the target component.  This should include any naming containers such as templates and regions.  The safest way to do this is to call getClientId() on the java component itself.   Then you can just invoke this little function.  Note that the code does not have any error handling if you get the component ID wrong so feel free to improve it to make it more robust: import org.apache.myfaces.trinidad.render.ExtendedRenderKitService;import org.apache.myfaces.trinidad.util.Service; private void scrollIntoView(String componentId){ StringBuilder builder = new StringBuilder();  builder.append("var c = AdfPage.PAGE.findComponent('");  builder.append(componentId);  builder.append("'); c.scrollIntoView(true,null);");          FacesContext fctx = FacesContext.getCurrentInstance();  ExtendedRenderKitService erks =    Service.getRenderKitService(fctx, ExtendedRenderKitService.class);  erks.addScript(fctx, builder.toString());        }  If you use this function an it appears not to work you may be hitting a timing issue where the framework is, in turn, resetting the focus after you have set it.  If that seems to be happening in your case, then the solution is to re-write the above JavaScript slightly to execute the scrollIntoView() after a short delay.  You can use a JavaScript  setTimeout() function on the window object to do this.  Delaying the scroll call for about 10ms should be sufficient.

I've been dealing with a use case recently where we needed to synchronize two panels in a user interface, where (in the simple version) selecting an object on one side of the screen would also select...

JDeveloper

JAX-RS 2.0 MessageBodyReader not found error

From time to time we all make silly mistakes which lead to much head scratching and time being wasted. This is a short missive about just such a mistake that I made yesterday which then had me totally stumped (for a a few minutes at least!) this morning. So, here's the story.  I was taking a long flight back to the UK from California yesterday and had wanted to keep working on a client UI for a RESTful service provided by our build infrastructure.  As you can imagine, it's not going to work very well to access those services in flight, so I spent the wait time in the lounge building out a quick mock implementation of the data structure using the same POJOs so I could switch to that and continue with the UI development offline. As part of this I thoughtlessly added a new constructor into my main POJO that the REST service JSON structure mapped in to.  All was well. This morning I'm back online, so I switch the implementation of my UI data provider back to the real service to see what the UI now looks like with more data - it fails? Huh? OK back to the test client - it also fails: Exception in thread "main" org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=class com.groundside.model.Orchestration, genericType=class com.groundside.model.Orchestration. at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:207) at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:139) at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1109) at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:853) at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:785) at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:267) at org.glassfish.jersey.client.InboundJaxrsResponse$1.call(InboundJaxrsResponse.java:111) at org.glassfish.jersey.internal.Errors.process(Errors.java:315) at org.glassfish.jersey.internal.Errors.process(Errors.java:297) at org.glassfish.jersey.internal.Errors.process(Errors.java:228) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:397) at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:108)  So now I spin round and make all the checks I can think of.  The libraries are all unchanged, perhaps the shape of the service has been changed overnight? - nope, every thing is the same.  The mime type coming from the service is still application/json as well.  So I'm pretty confused. Back to first principles though. Has really nothing changed? Well in fact yes there was a change - just one little, tiny thing, that new constructor.  Of course that was it.  One of the requirements for the JAX-RS unmarshalling is that the entity class should have an empty constructor.  Before it was implicit, but now I'd added that new constructor for the mocking which included arguments and that replaced the implicit empty constructor and broke the above requirement to boot.  So it was simple to fix in the end just annoying. Hey ho...

From time to time we all make silly mistakes which lead to much head scratching and time being wasted. This is a short missive about just such a mistake that I made yesterday which then had me totally...

ADF

Click History in ADF 12c

In previous posts (see here) I've covered various aspects of logging in ADF and in conjunction with a presentation delivered at the UK Oracle Users Group, I'm continuing the trend with an article on the new Click History functionality within 12c.  So What is Click History?  Basically the feature relates to instrumentation that is built into the ADF framework which, when switched on, continuously reports the actions that users have taken within the UI.  This mostly relates to physical clicks on UI elements such as buttons and tabs, but it also reports scrolling events, graph draws and more.  Why is it useful?  Well the point is that it can help answer that particular question - "What did you do before you got the error?" You can see how you could leverage this in a feedback or error reporting function in a UI where the information is extracted and automatically bundled with other useful information for the Support staff to have a look at.  Each Click History record provides information about the  component, region and view that reported the event, along with key information about the application,  the user and the DSID (Diagnostic Session ID). Here's a screen shot from some in-application diagnostics that I've developed as an small example.  In this case the history is being dumped and read into the actual application UI.  This is something I'll cover doing in a follow up article.  Enabling Click History  As I mentioned Click History is part of the framework in 12c, however, it's not switched on for every application by default.  There will be a performance overhead for any kind of tracing like this so we want to be explicit about choosing to use it.  In your application itself you need to make 2 small changes: Create a new web.xml context parameter with the name oracle.adf.view.faces.context.ENABLE_ADF_EXECUTION_CONTEXT_PROVIDER and set the value to true. Add an extra library reference to your /WEB-INF/ weblogic.xml file (create this if you don't have one already).  Here's the reference you need: <library-ref> <library-name>odl.clickhistory.webapp</library-name> </library-ref>  Assuming that you have a correctly configured Weblogic domain that has been extended with JRF this library will already be defined for you.   So in your application, that's basically it. However, we then need to do a little work on the server to configure the server side parameters for this, specifically how much space should be devoted to the Click History buffer.  To explain, Click History has a logical circular buffer of a specified size. As the buffer fills up then new records will be written from the start again and the older records discarded. When you want to look at the history, then you have to dump this buffer, but we'll come to that later.  Server Side Configuration of Click History  Switching Click History On or Off  Although individual applications enable Click History, the server also has to be told to pay attention.  This is very simple to do as it is controlled by switching a particular logger (oracle.clickhistory.EUM) to the NOTIFICATION level. This can be done from Enterprise Manager, or from the Weblogic scripting tool, WLST. Here, I'll show you how to do it from the command line using WLST, I think you can probably work out how to do it though EM yourself.  So, with WLST running: wlst> connect()wlst> getLogLevel(logger='oracle.clickhistory.EUM')INCIDENT_ERROR:1 The value of INCIDENT_ERROR indicates that the facility is OFF, so we can set it on with the following command: wlst> setLogLevel(logger="oracle.clickhistory.EUM", target="AdminServer",level="INFO", persist="1") If you've not encountered the setLogLevel command in WLST before, just issue help('setLogLevel') from the WLST command line to view the options and what they mean.  Viewing the Click History Buffer Unlike a normal logging message we can't view the Click History output directly in EM, instead we need to explicitly dump the buffer to the console, or more usually a file.  As I mentioned we can also do this in code which is something I'll cover in another article. So for now, let's look at how to do that from WLST: wlst>executeDump(name="odl.quicktrace",                  outputFile="/home/oracle/ch_dump.out") Again you can issue the help() command in WLST for more information about the options on executeDump(), but in this case I'm just taking the simple option of dumping the data to a file.. Inside the file you'll see the output containing all of the lines of  Click History information like this: [2013-11-20T09:08:53.332+00:00] [AdminServer] [NOTIFICATION] [] [oracle.clickhistory.EUM] [tid: 120][userId: alice] [ecid: 67ea61aa-dde8-4e35-afa2-a75a24c8a820-00001769,0] [CLICK_COMPTYPE: oracle.adf.RichShowDetailItem] [APP: SummitProductionDeploy] [DSID: 0000K9ohwuNFw000jzwkno1IYTfR00000X] [CLICK_VIEWID: /index] [CLICK_REGIONVIEWID: /customer-task-flow-definition/Customers] [CLICK_STARTTIME: 1384938532808] [CLICK_RENDERTYPE: oracle.adf.rich.Item] [CLICK_TYPE: disclosure] [CLICK_COMPCLIENTID: pt1:r1:0:sdi2] [CLICK_WINDOWID: w0] [CLICK_REGIONVIEWNAME: ] [CLICK_COMPDISPLAYNAME: Orders Dashboard]   It's pretty easy to parse this by eye... Configuring the Click History Buffer Size  You can view the initial size of the circular buffer by issuing the following WLST command: wlst> listLogHandlers(name="apps-clickhistory-handler") This will return a chunk of information, including the all important buffer size. (some information omitted here for space reasons): Handler Name: apps-clickhistory-handlertype:         oracle.core.ojdl.logging.QuickTraceHandlerFactoryuseLoggingContext: trueencoding: UTF-8bufferSize: 880640…flushOnDump: false To change the buffer size from the value of 880640bytes it's another WLST command: wlst> configureLogHandler(name="apps-clickhistory-handler", propertyName="bufferSize", propertyValue="1048576") So that's the basics of Click History - enjoy. 

In previous posts (see here) I've covered various aspects of logging in ADF and in conjunction with a presentation delivered at the UK Oracle Users Group, I'm continuing the trend with an article on...

ADF

Basic WebLogic Deployment Plans for your ADF Application

In my recent article Dealing with ADF_FACES-30214 I alluded to the fact that you could automate the (re)setting of web.xml parameters using a deployment plan.  This is particularly useful to ensure that all of those development-time switches are toggled off when deploying the application into a UAT or production environment.  At this stage you could head off and just research deployment plans for WebLogic in the main WebLogic server documentation.. However, I wanted to show you how easy it is to create and use a deployment plan from within JDeveloper and to embed it into a deployment profile that can be used either from the IDE or via OJDeploy  in your build system. To help illustrate this I\ve created a simple application which echos the values of the oracle.adf.view.rich.versionString.HIDDEN and javax.faces.PROJECT_STAGE context params onto the screen using EL. This is a 12c application, however, the same approach can be taken with JDeveloper 11g as well : So the aim here is to update those values to their production-ready settings ("true" and "Production" respectively) using a deployment plan.  For convenience, I'm going to define it as part of the project contents, although strictly speaking where you put it is up to you, you'll just need to make sure that it's not packaged up inside of your deployment  artifacts (e.g. the WAR file) as it's only needed at deploy time. Create the file from the New Gallery: Deployment Descriptors > WebLogic Deployment Descriptor and choose plan.xml in the Create WebLogic  Deployment Descriptor wizard - Step 1, as shown here: On the next step of the wizard you can name the new file, I've called mine dpdProductionModePlan.xml. Step through the rest of the wizard accepting the defaults. Once the wizard has run you'll find the new file in your META-INF directory.  It's not too exciting: <?xml version = '1.0' encoding = 'US-ASCII'?><deployment-plan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"                 xsi:schemaLocation="http://xmlns.oracle.com/weblogic/deployment-plan http://xmlns.oracle.com/weblogic/deployment-plan/1.0/deployment-plan.xsd"                 xmlns="http://xmlns.oracle.com/weblogic/deployment-plan">    <application-name>DeploymentPlan</application-name></deployment-plan> The key task that we accomplish in a deployment plan, and the thing we actually need to do in this case, is value substitution and we can do that in a variety of deployment descriptors, including web.xml, the target here.  Logically here's what happens.  The deployment plan defines one or more overrides for a particular descriptor (e.g. web.xml). It locates an element in the XML file using an XPath expression and replaces the target with the value of a named variable that is defined in the plan. So let's start off with a variable definition, here's the variable that will be used to define the new value for PROJECT_STAGE <variable-definition> <variable>  <name>projectStageProduction</name>    <value>Production</value>  </variable></variable-definition> So that's easy enough. Now we need to locate what descriptor file to override and the XPath expression that will identify the XML change to make.  Before starting this you will need to look at the deployment profile for your Web project (Project Properties > Deployment > Edit the profile you are using).  Grab the name of the WAR file as defined in the profile. Here's mine for my little demo app - the WAR file is called DeploymentPlanWebapp.war: Once we have that information we can create the override section in the plan file where we locate the correct parameter in the web.xml, and substitute in the new value: <module-override> <module-name>DeploymentPlanWebapp.war</module-name>  <module-type>war</module-type>  <module-descriptor external="false">  <root-element>web-app</root-element>  <uri>WEB-INF/web.xml</uri>  <variable-assignment>  <name>projectStageProduction</name>    <xpath>/web-app/context-param/[param-name="javax.faces.PROJECT_STAGE"]/param-value</xpath>    <operation>replace</operation>  </variable-assignment>  </module-descriptor></module-override> You can see  the <variable-assignment> section and the XPath expression within that which is locating the correct context-param element from the collection of parameters based on the param-name value. The param-value is then replaced with the contents of the variable we defined before. Once the  plan is complete we need to tell JDeveloper (or OJDeploy) to use it (Note that we can also use the same deployment plan when uploading an EAR file from the WebLogic console or using the web logic.Deployer task) .   To set JDeveloper up, you just need to edit your Application (EAR) deployment profile (Application > Application Properties > Deployment > Edit Your Deployment Profile), then in the general section of the deployment profile property tree you can browse for and select the plan file you've just created: Now it's simply a matter of deploying that application using the updated profile. Here I've deployed onto my standalone 12c WebLogic installation's managed server.  For completeness I've updated the plan to also replace the value for the oracle.adf.view.rich.versionString.HIDDEN value as well as the PROJECT_STAGE: And here's the full plan file for reference: <?xml version = '1.0' encoding = 'US-ASCII'?><deployment-plan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/weblogic/deployment-plan http://xmlns.oracle.com/weblogic/deployment-plan/1.0/deployment-plan.xsd" xmlns="http://xmlns.oracle.com/weblogic/deployment-plan">  <application-name>DeploymentPlan</application-name>  <variable-definition>  <variable>    <name>projectStageProduction</name>      <value>Production</value>    </variable>    <variable>    <name>devModeVersionDisplayOff</name>      <value>true</value>    </variable>          </variable-definition>  <module-override>  <module-name>DeploymentPlanWebapp.war</module-name>    <module-type>war</module-type>    <module-descriptor external="false">    <root-element>web-app</root-element>      <uri>WEB-INF/web.xml</uri>      <variable-assignment>      <name>projectStageProduction</name>        <xpath> /web-app/context-param/[param-name="javax.faces.PROJECT_STAGE"]/param-value </xpath>        <operation>replace</operation>      </variable-assignment>      <variable-assignment>       <name>devModeVersionDisplayOff</name>        <xpath> /web-app/context-param/[param-name="oracle.adf.view.rich.versionString.HIDDEN"]/param-value </xpath>        <operation>replace</operation>      </variable-assignment>    </module-descriptor>  </module-override></deployment-plan> Of course there is more that you can do with deployment plans, now you have the basics have a read of the WebLogic documentation on the subject (12c link) You can download the sample application that I used to illustrate this entry along with the deployment plan from the ADF EMG Samples Repository - download workspace.

In my recent article Dealing with ADF_FACES-30214 I alluded to the fact that you could automate the (re)setting of web.xml parameters using a deployment plan.  This is particularly useful to ensure...

ADF

Dealing with ADF_FACES-30214

Whilst doing some work on a separate blog entry using the demo Summit application in 12c I noticed a message repeated again and again in the WebLogic log in the console. Nothing annoys me more that constantly repeating messages that obscure the stuff I really want to see (I've wrapped the message to fit here) :  <Warning> <oracle.adfinternal.view.faces.renderkit.rich.DocumentRenderer> <ADF_FACES-30214> <The setting to enable version display will be ignored because the application is running in production mode.> Switching this message off is super easy, as we'll see, but what does it relate to? Well, this is all to do with the following context parameter defined in your web.xml file <context-param> <description>Whether the 'Generated by...' comment at the bottom of ADF Faces HTML pages should contain version number information.</description> <param-name>oracle.adf.view.rich.versionString.HIDDEN</param-name> <param-value>false</param-value> </context-param> This parameter defines if the generated page output contains detailed information about the ADF version. This information is useful in development and QA evironments but is not something that you want in a production environment as it is of potential use to a Hacker. So, to see the version information we need to explicitly include this context paramter and set the value to false so as not to hide the version info. Now in JSF 2 we have an additional factor come into play to complicate matters, which is the Project Stage (there are several articles on Project Stage that you can find with your favorite search engine, but this one covers the basics). Basically Project Stage is a way that you can define an application as being in Development, Test or Production mode and effect changes accordingly (both in the declarative sense as we have an example of here, but also in terms of code and behaviors).  Now the problem that all this relates to, the unwanted log message, is a reflection of the fact that if the Project Stage is not explicitly defined then it's going to default to Production mode (hopefully the message begins to make sense now?) . So we kind of have two mutually exclusive settings in this app.  On one hand I'm asking for Development time version information, and on the other hand the app thinks it's in production mode. The result is this message, and, if you look at the actual source of the page in the browser you'll see this: <!--Created by Oracle ADF (Version information hidden), accessibility (mode:null, contrast:standard, size:medium), skin:skyros-v1.desktop (skyros)--> The fix?  Well I do want to see the version information so I need to tell the application that it's in Development mode, not Production mode. To do this I just have to add a Project Stage entry into web.xml:   <context-param>    <param-name>javax.faces.PROJECT_STAGE</param-name>        <param-value>Development</param-value>  </context-param>  (Note the value is capitalized "Development")   Now when the application is re-deployed, the pesky message has gone and the page source contains oodles of version information: <!--Created by Oracle ADF (ADF RichClient API - ABRAMS (custom: 12.1.2.0.40.66.68)  / ADF RichClient Impl - ABRAMS (custom: 12.1.2.0.40.66.68) / ADF-Controller{Oracle-BuildSystem=Linux - java - 1.7.0_10-b18, Oracle-Label-JDEVADF=JDEVADF_12.1.2.0.0_GENERIC_130608.2330.6668, Oracle-Version=12.1.2.0.40.66.68, Created-By=23.6-b04 (Oracle Corporation), Oracle-Builder=Official Builder, Oracle-Label=JDEVADF_12.1.2.0.0_GENERIC_130608.2330.6668, Oracle-BuildTimestamp=2013-06-09 02:39:02 -0700} ADF-Model{Oracle-BuildSystem=Linux - java - 1.7.0_10-b18, Oracle-Label-JDEVADF=JDEVADF_12.1.2.0.0_GENERIC_130608.2330.6668, Oracle-Version=12.1.2.0.40.66.68, Created-By=23.6-b04 (Oracle Corporation), Oracle-Builder=Official Builder, Oracle-Label=JDEVADF_12.1.2.0.0_GENERIC_130608.2330.6668, Oracle-BuildTimestamp=2013-06-09 01:58:04 -0700} ADF-Share{Oracle-BuildSystem=Linux - java - 1.7.0_10-b18, Oracle-Label-JDEVADF=JDEVADF_12.1.2.0.0_GENERIC_130608.2330.6668, Oracle-Version=12.1.2.0.40.66.68, Created-By=23.6-b04 (Oracle Corporation), Oracle-Builder=Official Builder, Oracle-Label=JDEVADF_12.1.2.0.0_GENERIC_130608.2330.6668, Oracle-BuildTimestamp=2013-06-09 12:47:43 -0700}  / powered by JavaServer Faces - 1.0.0.0_2-1-20), accessibility (mode:null, contrast:standard, size:medium), skin:skyros-v1.desktop (skyros)-->  Next time I show how you can use a WebLogic Deployment Plan to update the Project Stage as you deploy your application 

Whilst doing some work on a separate blog entry using the demo Summit application in 12c I noticed a message repeated again and again in the WebLogic log in the console. Nothing annoys me more that...

ADF

(Adventures in) ADF Logging in 12c

An offline conversation with Andrejus Baranovskis the other day alerted me to a difference in behavior with the ADF Logger in 12.1.2. It seems that the logging output is not being output to the console as it was in 11g, although it's certainly being written to the log file OK. I did a little testing and digging on this, and the issue it turns out is pretty simple. The root cause is in the default definition of the console hander in the logging.xml file. In 11g, this handler is configured to let everything through level="ALL".  In 12c the default configuration is only to pass more significant issues through to the console level="WARNING:32".  The reason for this change is, I'm guessing to reduce the amount of general noise that you see when WebLogic is started.  So it's trivial to switch back to the verboseness of 11g if you'd like to: From the console choose Actions --> Configure Oracle Diagnostic Logging to open the logging.xml view Switch to source view and locate the <log_handler name='console-handler' ... entry Change the WARNING:32 value to ALL If you are feeling more creative, and want the best of both worlds, you can of course define a second handler for the console with this more permissive value and assign that explicitly to just your loggers - then you can get the verbose output for your logging without everything else.   For example; 1. Define a custom handler  <log_handler name='demo-console-handler'  class='oracle.core.ojdl.logging.ConsoleHandler' formatter='oracle.core.ojdl.weblogic.ConsoleFormatter'            level="ALL"/>  2. Use the custom handler for your root logger: <logger name="oracle.demo" level="FINEST" useParentHandlers='false'>  <handler name='odl-handler'/>  <handler name='wls-domain'/>  <handler name='demo-console-handler'/>  </logger> 

An offline conversation with Andrejus Baranovskis the other day alerted me to a difference in behavior with the ADF Logger in 12.1.2. It seems that the logging output is not being output to the...

ADF

Setting up a standalone WebLogic 12c install for ADF Without a Database

Important This article only applies to 12.1.* of Fusion Middleware.  If you are on 12.2+ then there is a straightforward way of creating the domain without the need for a database. Set the following environment variable: CONFIG_JVM_ARGS to -Dcom.oracle.cie.config.showProfile=true See the Fusion Middleware Documentation and search for "Compact Domain" for more information If you are on 12.1.* then read on... One change that many folks have encountered with the 12c (12.1.2) release of WebLogic and ADF concerns the setup of stand-alone WebLogic instances extended with JRF for ADF Application deployment.  The main problem comes when creating the JRF extended domain.  On page 6 of the config process screen you are confronted by the following:   Note here that you need to provide information for the database that OPSS should use.  Now this connection has a real purpose, the Oracle Platform security infrastructure for 12c needs to store it's information within a proper database so as to correctly (and supportably) manage itself across multiple servers in a cluster.  However, if like me, you just wanted to stand up a single unclustered ADF enabled WebLogic for testing deployments etc. This could be a bit of a pain, particularly in my case as the database version I'm currently running is not of the correct version.  So here I'm documenting the steps for avoiding this requirement on a single standalone server, although I stress, as far as I am aware, this is not a supported configuration for production usage. The Steps to Install Without Needing a Database    First of all install WebLogic (wls_121200.jar) and the ADF runtime (fmw_infra_121200.jar) into the same 12c Oracle Home using their respective installers. At the end of each of the WebLogic install make sure you uncheck the Configuration Wizard launch option as we'll be doing that manually later.  Start a shell / command prompt in $MW_HOME/wlserver/common/bin Set the environment variable QS_TEMPLATES to point to $MW_HOME/wlserver/common/templates/wls/wls_jrf.jar Run qs_config.sh and define the name of the domain that you want to create (e.g. add_domain) along with the usual WebLogic passwords and ports that you require. Finish the Quick Start wizard without starting the new domain.  Now run the conventional config.sh and on the first page choose "Update an Existing Domain" rather than "Create a new domain". The new domain (e.g. adf_domain) should now be listed for selection. On the second screen choose the templates that you wish to apply, e.g. Oracle JRF, Oracle Enterprise Manager etc.  and move on through the wizard.  On the Database Configuration Type screen this time you will see an extra option where Embedded Database (JavaDB) is offered and pre-selected. Select that and continue with the domain setup as usual with whatever managed servers you need.     Again to re-iterate this is only a setup that I would recommend for a development / testing environment and of course you should not take this approach if you're setting up any kind of clustered environment, even for testing, as the shared database has a real purpose in that case. Also consider that if your application uses MDS then you'll most likely need an database repository anyway, so again, in that instance don't use this technique.   The fact that the normal install for the ADF Web Runtime does not offer this non-database option should be taken a a strong hint as to how supported you will be running with this configuration in a production environment.  Don't ask me for certification or support guidance, please contact Oracle Support for that information.   Further Reading The use of an external RDBMS Security Store for WebLogic (the configuration that  this article bypasses) is discussed in the WebLogic Documentation:   Administering Security for Oracle WebLogic Server --> Chapter 9: Managing the RDBMS Security Store   Read that chapter for a better understanding of why the default JRF install asks you to define a database connection for this purpose and why I talk about only using the technique that I've outlined here for development purposes.     

Important This article only applies to 12.1.* of Fusion Middleware.  If you are on 12.2+ then there is a straightforward way of creating the domain without the need for a database. Set the following...

ADF

Adaptive Connections For ADFBC

Some time ago I wrote an article on Adaptive Bindings showing how the pageDef for a an ADF UI does not have to be wedded to a fixed data control or collection / View Object. This article has proved pretty popular, so as a follow up I wanted to cover another "Adaptive" feature of your ADF applications, the ability to make multiple different connections from an Application Module, at runtime. Now, I'm sure you'll be aware that if you define your application to use a data-source rather than a hard-coded JDBC connection string, then you have the ability to change the target of that data-source after deployment to point to a different database. So that's great, but the reality of that is that this single connection is effectively fixed within the application right?  Well no, this it turns out is a common misconception. To be clear, yes a single instance of an ADF Application Module is associated with a single connection but there is nothing to stop you from creating multiple instances of the same Application Module within the application, all pointing at different connections.  If fact this has been possible for a long time using a custom extension point with code that which extends oracle.jbo.http.HttpSessionCookieFactory. This approach, however, involves writing code and no-one likes to write any more code than they need to, so, is there an easier way? Yes indeed.  It is in fact  a little publicized feature that's available in all versions of 11g, the ELEnvInfoProvider. What Does it Do?  The ELEnvInfoProvider  is  a pre-existing class (the full path is  oracle.jbo.client.ELEnvInfoProvider) which you can plug into your ApplicationModule configuration using the jbo.envinfoprovider property. Visuallty you can set this in the editor, or you can also set it directly in the bc4j.xcfg (see below for an example) . Once you have plugged in this envinfoprovider, here's the fun bit, rather than defining the hard-coded name of a datasource instead you can plug in a EL expression for the connection to use.  So what's the benefit of that? Well it allows you to defer the selection of a connection until the point in time that you instantiate the AM. To define the expression itself you'll need to do a couple of things: First of all you'll need a managed bean of some sort – e.g. a sessionScoped bean defined in your ViewController project. This will need a getter method that returns the name of the connection. Now this connection itself needs to be defined in your Application Server, and can be managed through Enterprise Manager, WLST or through MBeans. (You may need to read the documentation [http://docs.oracle.com/cd/E28280_01/web.1111/b31974/deployment_topics.htm#CHDJGBDD] here on how to configure connections at runtime if you're not familiar with this)   The EL expression (e.g. ${connectionManager.connection} is then defined in the configuration by editing the bc4j.xcfg file (there is a hyperlink directly to this file on the configuration editing screen in the Application Module editor). You simply replace the hardcoded JDBCName value with the expression.  So your cfg file would end up looking something like this (notice the reference to the ELEnvInfoProvider that I talked about earlier) <BC4JConfig version="11.1" xmlns="http://xmlns.oracle.com/bc4j/configuration">  <AppModuleConfigBag ApplicationName="oracle.demo.model.TargetAppModule">  <AppModuleConfig DeployPlatform="LOCAL" JDBCName="${connectionManager.connection}" jbo.project="oracle.demo.model.Model" name="TargetAppModuleLocal" ApplicationName="oracle.demo.model.TargetAppModule"> <AM-Pooling jbo.doconnectionpooling="true"/> <Database jbo.locking.mode="optimistic">      <Security AppModuleJndiName="oracle.demo.model.TargetAppModule"/>    <Custom jbo.envinfoprovider="oracle.jbo.client.ELEnvInfoProvider"/> </AppModuleConfig> </AppModuleConfigBag></BC4JConfig> Still Don't Quite Get It? So far you might be thinking, well that's fine but what difference does it make if the connection is resolved "just in time" rather than up front and changed as required through Enterprise Manager? Well a trivial example would be where you have a single application deployed to your application server, but for different users you want to connect to different databases. Because, the evaluation of the connection is deferred until you first reference the AM you have a decision point that can take the user identity into account. However, think about it for a second.  Under what circumstances does a new AM get instantiated? Well at the first reference of the AM within the application yes, but also whenever a Task Flow is entered -  if the data control scope for the Task Flow is ISOLATED.  So the reality is, that on a single screen you can embed multiple Task Flows, all of which are pointing at different database connections concurrently. Hopefully you'll find this feature useful, let me know... 

Some time ago I wrote an article on Adaptive Bindings showing how the pageDef for a an ADF UI does not have to be wedded to a fixed data control or collection / View Object. This article has proved...

ADF Faces and UI

Prioritizing your messages

I've just uploaded a small sample onto the ADF EMG Samples site which demonstrates how you can make the <af:messages> component behave differently based on the messages that are in the queue.  The use case here was within a system where we wanted to use in-line messages for those run-of-th-mill type messages that should not really interrupt the flow of the user's activity (informational messages such as "Record Saved") , however, if something goes wrong then we wanted a popup to get in the users face, so to speak.  The mode of display within the messages tag is controlled by the inline property, so in the sample application, rather than hardcoding this instead I evaluate an EL expression that returns a boolean.  Here's the code that implements the method I call: public boolean isInlineMessage(){ boolean lowPriorityMessage = true;  Iterator<FacesMessage> iter = FacesContext.getCurrentInstance().getMessages();  while (iter.hasNext()){  FacesMessage msg = iter.next();    if (msg.getSeverity() == FacesMessage.SEVERITY_ERROR ||  msg.getSeverity() == FacesMessage.SEVERITY_FATAL){    lowPriorityMessage = false;      break;    }  } return lowPriorityMessage;} In this code I simple iterate through the message stack and check to see if there are any messages at the ERROR or FATAL level. If that is the case I return false rather than true for the method result. The only twist here is to ensure that your partialTriggers are set up correctly so that the <af:messages> tag is re-evaluated. Anyway, the demo code is available here.  Enjoy. Note: The demo will only run in 11.1.1.7  and 11.1.2..3 + but the message checking code part will run in earlier versions as well.  It's just that the demo screen uses the new panelGridLayout. 

I've just uploaded a small sample onto the ADF EMG Samples site which demonstrates how you can make the <af:messages> component behave differently based on the messages that are in the queue.  The use...

JDeveloper

Launching JConsole as an External Tool From JDeveloper

I find JConsole to be a useful tool, particularly for MBean browsing, but frankly getting the correct command line arguments to get it to connect correctly to my WebLogic instances is a bit of a pain. I always have to go and look it up. - generally from here. However, setting all those paths is tedious. Given that I'm usually working in an environment where my JDeveloper, and the WebLogic servers I'm using JConsole on, are matched from a version perspective I can get JDeveloper's external tools capability to do the lifting. Very simple this. Just choose Tools > External Tools from the menu and press New.  Then run through the wizard: Type is External Program Program Options > Program Executable = jconsole  Program Options > Arguments =  (All on one line of course, reformatted here for readability)  -J-Djava.class.path=${java.path}/lib/jconsole.jar: ${java.path}/lib/tools.jar: ${prop:name=weblogic.home}/lib/wljmxclient.jar  -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote  And that's it.  JDeveloper helpfully substitutes both the Java location and the WebLogic location for us saving all that hunting around.  Tip Thanks to Torsten Kleiber who discovered and followed up on the twist of ${java.path} not expanding correctly (or rather expanding to null). Before running the tool command with the macro make sure that you have a project open and selected as the actual java path is obtained in the context of the JRE version used by the selected project. (Project Properties > Libraries and Classpath > Java SE Version)

I find JConsole to be a useful tool, particularly for MBean browsing, but frankly getting the correct command line arguments to get it to connect correctly to my WebLogic instances is a bit of a pain....

ADF Faces and UI

Conveyor Visualization for Tabs in ADF

If you look carefully at the online demos for panelTabbed in 11.1.1.7 you may notice that the tabs are sporting a slightly changed UI for situations where the number of tabs can't fit into the available horizontal space.  Here's the situation with the default representation of a tab-set when it overflows. The chevron  on the right of the tab-set can be clicked to display a drop-down list of the remaining tabs.  In 11.1.1.7 we now have an alternative visualization where the hidden tabs are available on a conveyor belt and the user can scroll along the belt rather than having to use the pull-down list. Enabling this feature This visualization is not controlled by any property on the component but rather is switched on through the skin being used in the application. As such, all tab-sets within the application will gain the visualization if it is switched on.  To enable it you will need to create a custom skin, if you are not familiar with  process then there are plenty of articles and documentation out there to help you, or you can download the demo that I've created to go along with this article. Basically I've created a custom skin that extends the new Skyros skin that 11.1.1.7 uses by default, and plugged that in to replace Skyros. Within the skin file there is a single entry to make for panelTabbed (and a similar one for navigationPane):  af|panelTabbed {    -tr-layout-type:conveyor; } And that's it, as simple as that.  As I mentioned you can download a simple sample (DRM009) which shows this in action from the ADF EMG Demos Site

If you look carefully at the online demos for panelTabbed in 11.1.1.7 you may notice that the tabs are sporting a slightly changed UI for situations where the number of tabs can't fit into the...

ADF Faces and UI

Slide, Charlie Brown! Slide!

Following on from an earlier article(Using inputNumberSlider with Dates) where I showed you how you could use an <af:inputNumberSlider> to display formatted date strings rather than numbers, I've been expanding into other uses for the slider components.  Specifically the most recent use case  was to represent text labels for the number "stops" on the slider so that it could be used as a way of filtering datasets. So this is what it looks like: So, no problem you say, the previous article shows pretty much how to do that - why a new one?   Well the twist here is in the form of tables. What if I want to use the slider in a table, and I want to have different slider labels for different rows, like this: Well that's a bit more of a problem.  Why you ask?  It's because of the way that tables work.  When you define a table, each row is stamped out from the same set of components.  So If I have one converter that say converts numbers to  Domain, Kingdom, Phylum etc. associated with the slider then that's the converter that I'm going to use for every row as it's stamped out. I can't use a different converter per row. (Well OK I could use EL to specify a different converter value for each but then I'd need to define as many converters as I have value lists and plus I would have to know in advance what all the possible lists of filter values are.  In this case, the reality is that the values shown in the sliders come from user configuration rather than being baked into the application anyway, so a hardcoded solution is out) .  So my aim here was to build a converter that could be used generically with as many different lists as required. You can download the resulting code from here. If you take a look at the demo you will see that the converter is defined by name in the faces-config.xml  and then associated with the inputSlider <af:inputNumberSlider value="..." minimum="0" maximum="3" minorIncrement="1"  converter="ismsConverter"><f:attribute name="imsConverterMeasureElements" value="John,Paul,Ringo,George"/></af:inputNumberSlider>  The actual list of elements which will be displayed as labels for each slider stop are then passed as a comma delimited string using the <f:attribute> tag. This version of the converter always assumes a zero indexed list and the labels are assigned in order from zero. So selecting George in the slider above will translate into a value of 3. It would be perfectly possible to adapt the code to allow specific mapping between a number and the label, e.g. if you wanted a 1 based list you might pass a definition string like this: "1:John,2:Paul,3:Ringo,4:George" You'd just need to do a little more parsing in the converter itself to make this work though. Even with no change you can use the converter out of the box with <af:inputRangeSlider>. Here's a version with Roman numerals:  Finally on the matter of datatypes there is a slight twist when using a model attribute of type oracle.job.domain.Number.  The ismsConverter will handle the basic Java types, float, int, long double etc. and then there us a second converter called ismsJboConverter that handles the JBO Number type.  All of this is shown in the demo.

Following on from an earlier article(Using inputNumberSlider with Dates) where I showed you how you could use an <af:inputNumberSlider> to display formatted date strings rather than numbers, I've been...

ADF Faces and UI

New Table Sorting Capability in Patchset 6

With every new release you can trawl through the release notes and fine some handy new features to play with, however, sometimes there is even more to discover hidden away. One such feature, which I think is actually pretty exciting, has crept into the 11.1.1.7.0 release of JDeveloper / ADF.  This is a new feature which adds case insensitive sorting to the table.  Previously we have had to resort to tricks such as defining transient attributes where all attributes are converted to a particular case in order to create this transient attribute. It would then be used as the sortProperty on the <af:column> that houses the column that you wanted to sort in a case insensitive way.  Not too difficult to do, but it means adding stuff to your model to satisfy a UI need. Now there is a cleaner way. So to replace this technique, we now have a new property on <af:column> called sortStrength. This new property takes one of four values which allow you some degree of control as to how the sorting takes place. The resulting sorts are locale specific.  This is probably best illustrated with a table: Identical (default)  This is the default value and reflects the traditional behavior where the sort is very sensitive. i.e AA != aa and aa != áá Primary  Only the primary difference is observed i.e. the underlying letter. So a != b of course but AA == aa == áá == Äæ  for the purposes of sort. You can think of this as the most promiscuous sort    Secondary Secondary is still case insensitive. A secondary difference is something like an accented version of a character. So in this case AA == aa, however, aa != áá.   Tertiary  Returns us to the world of case sensitivity, so AA != Aa != áá != ÁÁ.  There are some subtle locale specific differences between Identical and Tertiary but for most purposes they will have the same effect  So you can see that for day-to-day case insensitive table sorting you should use the Primary or Secondary values depending on how you want to treat accented characters.  If you are wondering where the weird Primary, Secondary, Tertiary thing came from, head over to the JavaDoc for the java.text.Collator class which is the mechanism underlying all of this. 

With every new release you can trawl through the release notes and fine some handy new features to play with, however, sometimes there is even more to discover hidden away. One such feature, which I...

ADF

Lions and Tigers and RangeSize, Oh My!

One of the most common mistakes I see made in ADF Business Components based applications is a failure to tune the View Objects, and specifically to tune the in Batches of parameter in the VO tuning section. This setting defaults to 1, which does not always meet the needs of the consuming UI or service interface and should generally be changed.  This is a topic that I and others have covered before. Now certainly the batch fetch size is a crucial tuning parameter as it controls how many times the framework has to hit the database to get the rows needed to service a particular function.  However, in this posting I wanted to turn my attention to another factor which can also have a significant effect - the iterator RangeSize. The background to this was some recent detective work on an application where the time taken to display one particular screen was suspiciously long.  The page in question had a tabular display of data, but an inspection of the VO tuning parameters showed that a reasonable Batch size of 51 was being used. What's more the As Needed switch rather than the All at Once option in the VO tuning was being used. So the developer had done totally the right things there. Running a SQL Trace on the page revealed an interesting thing though.  Because the batch size was pretty high we'd expect that the framework would have to only do one or at most two fetches from the cursor to satisfy the needs of that table.  However The TKProf output showed that in fact over 150 fetches took place retrieving over 8000 rows! My thought processes in diagnosing this were to look in the following places: Are there alternative VO Instances defined on the AM where the tuning parameters are different (e.g. ALL_ROWS was specified)? We know the base definition is OK but it could be overridden.   Any programmatic calls to change the Batch Size or fetch node in the VO? Any programatic calls to last() on the rowset or iterations through the rowset?  Check for a RangeSize of -1 on the iterator definition in the pageDef files. All of these drew a blank.  The last one in particular felt like the problem but a search for the value of -1 in the pageDefs of the UI project only turned up legitimate usages of the -1 value.  Hold on I don't Understand This RangeSize? Maybe I should take a quick step back and explain the iterator RangeSize.  So, as we've seen, the tuning options in the view Object will control how often the VO has to go back to the database to get a specific number of rows. The iterator rangeSize is defined in the pageDef file for a particular page, fragment or method activity and it defines how many rows the UI layer should ask the service layer (in this case the VO) for.  Here's a typical definition that you'll see in the pageDef: <iterator Binds="EmployeesView1"           RangeSize="25"           DataControl="HRServiceAMDataControl"           id="EmployeesView1Iterator"          ChangeEventPolicy="ppr"/> You'll see that the rangeSize here is set to 25 which just happens to be the value that is defaulted in when you drag and drop a binding into the page.  However, it turns out that 25 is not the default value, something which has a bearing later in this investigation as we'll see. So in this default case when the iterator is asked for data, it in turn will ask the VO for 25 rows, and if the VO does not already have that many rows in the cache it will have to go back to the database as many times, as determined by the batch-size, as it needs to get enough data. Back to the Problem page  As it happens the pageDef for the table displaying the problem VO was indeed the defacto default of 25, so, sad to say, it was not the obvious suspect at fault, more investigation was needed. At this stage the investigation splits into a couple of parallel efforts, manual code inspection, and tracing using the ADF Logging capability to try and work out what interactions were happening with the problem VO. Welcome to the Internet, Please Tread with Care What can we trust? Well in the world of ADF Blogs in the wild there are some great bloggers, but that does not mean that you can just copy without thinking.  It turned out that one of the problems with this application was to fall foul of copy-without-thinking syndrome. The code in question seems innocent enough, it's published out there on the internet as a way of refreshing an iterator: //Please, Please Don't do this! (My comment)DCIteratorBinding iterBind= (DCIteratorBinding)dc.get("<your iterator name>");  iterBind.refresh(DCIteratorBinding.RANGESIZE_UNLIMITED);   Two facts to discuss in relation to this code snippet: Read the JavaDoc for DCIteratorBinding - the refresh() method is very clearly marked as Internal only, applications should not use. That's what we call "a hint" in the trade, you can choose to ignore it but don't come crying...Look at that parameter being passed to the refresh method DCIteratorBinding.RANGESIZE_UNLIMITED - can you guess what that does? Yes it does the same as setting the RangeSize to -1 and will cause the VO to be asked for all of the data for that query. You can see how bad that could be if the VO has the potential to return a lot of rows. So something to put right already.  But Wait, There's more! Although the call to refresh was a great catch and the application will be better without it, it turned out not to be the cause - darn.  However, the parellel effort to run some more tracing found the smoking gun.  The ADF Log trace showed a double execute on the iterator for the VO in question, or to be more precise, executes on two different iterators bound to the same VO from different regions on the page.  A useful diagnostic here was then to set a breakpoint in the setRangeSize() of oracle.adf.model.binding.DCIteratorBinding.  Doing this we could see that the first iterator execution was actually responsible for setting the RangeSize to -1 and the second to the value we where expecting for that table based on the pageDef.  All credit to the development team I was working with here who ferreted out the actual problem, it was finally down to one of omission.  Recall I made the statement earlier about 25 being the defacto default for the RangeSize? Very true, when you create a binding, that's what the IDE puts in for you.  But what's the actual default? Well that turns out to be -1.  So if you omit the RangeSize from the iterator definition by intent, or mistake, you're going to have a potential side effect you may not have expected!  That was exactly the problem in this case  - no RangeSize. Specifically the problem was caused by a method binding in one of the bounded task flows in the page. The pageDef for this method activity included and iterator defined for the problem VO but without a RangeSize defined.   Lessons to Learn For each peice of UI that is bound to data understand how the user is going to use that screen - will they view just one record, will they scroll through several or a lot, will they only scroll downwards and process one record at a time and so on. You can't effectivly tune a page until you understand how it will be used.Always tune your VO definitions or instances to the requirements of each endpoint.  If this means having multiple VO definitions or multiple VO instances with different tuning parameters then do it.If you have consciously set your Batch size in the VO tuning parameters to a small number because that's all you see on the page at once then also tune the pageDef iterator RangeSize. Otherwise that defacto 25 RangeSize could generate a bunch of unnecessary calls back to the database. Think about it, if you have a single record form and you've not tuned the VO Batch size and you've not tuned the iterator RangeSize, you could be doing 25 roundtrips to the database just to see one record.  Great way to please your DBA!Use a RangeSize of -1 with caution.  It has its place for iterators that serve short lists used for lookups and menus but anything else is an exception.Don't blindly copy everything you see in the blog-o-sphere. If you don't recognize an API call then look it up.  If something says it's for internal use only, then guess what, don't use it.Never ever, define an iterator in your pageDef without an explicit rangeSize. If you need to see all rows, say so with the -1 value, otherwise use a positive integer. We all go home older and wiser...

One of the most common mistakes I see made in ADF Business Components based applications is a failure to tune the View Objects, and specifically to tune the in Batches of parameter in the VO tuning...

ADF Faces and UI

Building the revealPanel - Part 2

In the first part of this series I described the basic physical makeup of the revealPanel and described a simple server side approach to the display and hide of the information panel and indicator triangle.   In this posting I want to look at an alternative approach that uses the same physical components in the UI, but rather than handling the reveal with a roundtrip to the server, does it all in the browser itself using JavaScript. The sample that you can download shows both approaches.  Changing the Configuration for JavaScript Use The JavaScript version of the component works in essentially the same way as the server side version that I talked about last time, that is, it simply sets the visible attribute of the panelGroupLayouts that contain the reveal information and the triangle. The good thing is at this is a property that we can set through the ADF Faces client component JavaScript API and we never really have to tell the server side what the state of the panels is as we'll always revert to the all-closed layout if anything like navigation away and back takes place.  So the definition of say the triangle PGL simply has the visible attribute set to a hardcoded value of false, with no need to refer to a managed bean. Of course we need to hold the information about which panels are expanded somewhere,  so that we can close one set as another is opened, or close a set if it is currently open. To do this I actually create a new JavaScript object at the page level called revealPanelGroupMap (if you want to read along open the revealPanel.js file in the demo).  This Object does not directly hold the information about the panel, it's a slightly more complex structure: revealPanelGroupMap is a Map (thinking in Java terms) of revealGroup Objects  Each RevealGroup contains an array of Topics and the currently selected Topic in the array Each Topic contains component references to the triangle PGL and the revealPanel PGL as well as the topic number The fact that revealPanelGroupMap can hold multiple revealGroups allows us to host multiple revealPanels on the same page as long as each is identified by a unique string which is used to key that revealPanelGroupMap. How are the Data Structures Created?  So this revealPanelGroupMap does not appear out of thin air, but neither in fact is it created in advance in any way. Because, for an individual page, you may have dynamic regions and suchlike, I wanted the revealPanels to be self registering and created on demand rather than pre-defined in some way.  The way that I ended up achieving this was to add a client attribute to each of the three important panelGroupLayouts (the topic, the triangle and the revealPanel). This locator is just a string consisting of 3 parts delimited by ":". The panelGroupId - e.g. "REVEAL1" The TopicID - zero indexed The SegmentID - each topic has three segments 0-2 where 0 is the topic, 1 is the triangle and 2 is the revealPanel So the client attribute definition in the page looks like this: <af:clientAttribute name="revealPanelLocator" value="REVEAL1:0:0"/> This indicates that this panel is the topic panel for the first topic in the REVEAL1 group.  When the first of the topics is clicked within a revealPanel, the click handler code grabs this locator and parses out the segments.  From the first segment it can tell if this group has been seen before, if it has then great, it can start to set visibility etc. If, however, the group is not present in the main map then we do a little self discovery to find out how many Topics there are in the revealPanel group as a whole and store the relevant component references. Walking the Tree So how to we self discover the group?  Well the first bit is easy.  Using the getParent() API  from the component that raised the click event we can get a reference to the hosting panelGridLayout.   I then use the visitChildren() api on the grid to visit each of its top level children. Each of these will actually be one of those segment panelGroupLayouts. So in a panelGrid with 9 children that will actually define 3 topics each consisting of three panels (topic, triangle, reveal) .  As each of those panels has an associated clientAttribute with it's locator we can add it to the correct place in the revealGroup control structure.  The visitChildren API actually defines a callback function that the framework will call for you, passing any context that you've defined and the child component it has found.  Note, it would be perfectly possible to alter the sample code to do away with the clientAttribute all together. I actually wrote it this way to allow for more than one revealPanel to be hosted within the same physical panelGrid. However, of that's not something you need then the page definition could be condensed down to simply the clientListener in the Topic panel.  Left as an exercise for the reader...  Acting on the Click Once the data structure is build for a particular revealPanel it will be caching the component references to the triangle and to the reveal PGL so you can simply call setVisible(true|false) to manage the hide and display. You've Noticed the Fatal Flaw? Well I hope so... If I'm storing the component references to the various panelGroupLayouts will they stay valid? Well certainly if I navigate off to another page no.  But that's OK, because if I navigate away then the document object in the DOM will have been destroyed, taking my data structures with it. So when I re-enter the page they just get re-built.  So no problems there.   However, if my page contains a region and one of the fragments on the region has a revealPanel then there is a problem.  Changing the view in the region will not effect the overall document so the control structures contain references to components that have been destroyed - if I go away and come back to a revealGroup on a fragment then the references will be bad.  However,  there is a simple solution to this.  The client side components have an isDead() API call which we can use to check to see if the reference held in the cache is still valid.  If it is then great. If not we assume that we need to rebuild the entire structure for that revealPanel. Adding Some Bling with Animations I promised some animation as part of this version and indeed it's in there.  So in fact, rather than simply setting the visible attribute when the topic is clicked I do that, but I also apply some CSS styles as well.   I'm essentially re-using some of the things I've discussed before in my postings on animations, using in this case Scale transforms for the main reveal panel and a color transform for the triangle. Here's the logical flow: Revealing a Topic Set the triangle to visible - it's initial style will define it as transparent Set the reveal panel as visible  - its initial style will define a scale of (1,0) with full width but no height Set the reveal panel style to revealPanelAnimated. This resets the scale to (1,1) - full size over about 200ms Register a listener on the animation When the animation is finished then reset the style on the triangle to restore its color. Note that I've used a scale transform here rather than actually trying to move the PGL <div> around the screen. Trying the latter could put you into conflict with the existing layout management and will certainly cause some problems with z-order in the DOM so it's better to avoid the issue by scaling in place.  It gives a pleasing effect.   The actual code and styles involved in all of this is a little too complex to reproduce here in the blog, so do be sure to check out the demo.  I've added plenty of comments to help you along.  

In the first part of this series I described the basic physical makeup of the revealPanel and described a simple server side approach to the display and hide of the information panel and...

ADF Faces and UI

Building the revealPanel - Part 1

Working with one of our internal teams the other day, a couple of interesting ideas came up for presenting information. One of these was a sort of twist on panelAccordion and it seems to be a nice usecase to work through to show how you can get creative with your UI without having to ask for and wait for new components.  The Brief As I said, the requirement here was to produce something like panelAccordion. However, rather than restricting the selection bar to just a single line of text an maybe an icon,  what if you wanted larger images or multiple lines?  Here's a mockup: Then like a panelAccordion, with discloseMany="false" and discloseNone="true" you want to be able to expand the details of up to one and only one of the selection panels (I'll call them "Topics" from now on). So if I click anywhere in the first topic bar in the above image then that topic will collapse, if I click on a different topic bar then the first will collapse and the new selection will expand. You'll notice the modernist conceit of the little triangle linking the revealed panel with it's topic. It's a small thing but that also helps to polish the look and make it feel current. The UI Elements So how would we build this? Well the answer is that the UI itself is surprisingly easy. That's all thanks to our new friend, the panelGridLayout  which hands us everything we need on a plate.  We can break down the mockup above into three sets of repeating units, remember I called them topics.  Each topic is identical, so let's just look at one. Logically the topic is composed of three vertically arranged areas: (1) The topic header itself         | (2) The little indicator triangle         | (3) The reveal panel area with the additional content  Area 1, the header is always displayed and areas 2 and 3 we need to reveal or hide dynamically when the user clicks anywhere on area 1. In panelGridLayout terms we can simply translate this into three grid rows, one for each area.  The key point here is that if you set the height attribute of a <af:gridRow> to the value "auto" the grid will automatically size that row to fit its children, so guess what: if we set visible="false" on the contents in areas 2 and 3 then the grid shrinks for free. I just love that this is so easy. So here's the outline component model for a revealPanel (Yes there is a full demo you can download - read on to the end) <panelGridLayout><!-- For Each Topic -->  <gridRow height="50px">    <gridCell columnSpan="3" halign="stretch">      <panelGroupLayout layout="vertical" styleClass="revealTopicPanel">      <!-- Topic header content will go here -->       <panelGroupLayout>    </gridCell>  </gridRow>  <gridRow height="auto">    <gridCell width="80px"/>    <gridCell width="10px" valign="bottom" >      <panelGroupLayout layout="vertical"                         styleClass="triangleMarker"/>    </gridCell>    <gridCell width="100%"/>  </gridRow>  <gridRow height="auto">    <gridCell columnSpan="3" halign="stretch">      <panelGroupLayout styleClass="revealPanel"      <!-- Revealed content will go here -->     </gridCell>  </gridRow></panelGridLayout> Let's look at the key points The first grid row representing the topic header can be fixed in size to make sure that the unexpanded list is regular. The first grid row just contains a single grid cell that streches across three logical cells using the columnSpan attribute. The reason for doing this will become clear when we look at the second area of the topic  We use halign="stretch" on that first area gridCell to fill it with its content. This is important to make the included component (e.g. panelGroupLayout in this case) fill the cell with its styling. Moving onto the second area of the topic than contains the little indicator triangle, here the row as it's height as auto so it will collapse when we hide the triangle. The triangle area row is divided into three cells. The center cell contains the actual triangle (see below) and the other two cells are used to position the triangle cell to a particular horizontal position. In this case I'm indenting the triangle by a fixed 80 pixels, however, if I adjusted the first and last cells to use width="50%" then the triangle would be centered to the width of the panel. The final area is again a grid row with height set to auto containing a single cell with columnSpan set to 3 and stretching it's content.  The Triangle The little triangle indicator could be done using an image file, however, here I'm just using a CSS style which is simpler and enables you to change the color as required. Here's the definition:  .triangleMarker {  width:0px;  height:0px;  border-left:8px solid transparent;  border-right:8px solid transparent;  border-bottom:8px solid rgb(247,255,214);  } This style is applied to the vertical panelGridLayout in the center area.  Vertical panelGrids become simple html <div> elements. Managing the Topic - The Server Side Version I'll cover a more advanced version of the component in my next posting which uses JavaScript to manage the hide and reveal of the panels, but in this post, let's look at the simple version.  As discussed, the paneLGridLayout actually does all of the UI resizing for us, so all we really need to do to manage the set of topics is two things: Introduce a management class that will tell the reveal panel and triangle panel if they should be visible or not A small amount of event code to translate a click anywhere on the topic panel into a change in the above management class.  The Management Class For the sake of the demo I've developed a very simple management class that does not attempt to do anything fancy such as handling multiple sets of revealPanels (that task is left for the JavaScript implementation). Here's the class: package oracle.demo.view;import java.util.ArrayList;import java.util.List;public class RevealPanelManager {    private int _panelCount = 10;    private int _toggleTarget = -1;    private List<Boolean> _revealedList;    /**     * Switches the state of the currently selected panel      */    public void toggleState() {        if (_toggleTarget >= 0 && _panelCount > 0) {            boolean currentState = false;            if (_revealedList != null){                currentState = _revealedList.get(_toggleTarget);            }            resetStates();            if (!currentState) {                _revealedList.set(_toggleTarget, true);            }            _toggleTarget = -1;        }    }    /**     * Used to inject a panelCount into the management structure. If not called then an array upper limit of      * 10 will be used     * @param panelCount     */    public void setPanelCount(Long panelCount) {        int candidateCount = panelCount.intValue();        if (candidateCount > 0) {            //reset the list & re-create in the new size            _revealedList = null;            _panelCount = candidateCount;            resetStates();            }    }    /**     * Invoked, probably from a setPropertyListener / setActionListener to set the id of the      * panel to act on.  This may disclose or hide depending on the current state of the selected     * panel     * @param toggleNo - index number of the panel     */    public void setToggleTarget(int toggleNo) {        this._toggleTarget = toggleNo;    }    /**     *Called by the panel to see if it should be visible or not     * @return List of Booleans indexed by panel number     */    public List<Boolean> getRevealed() {        return _revealedList;    }    /**     * Either creates or reinitializes the array to close all the      * panels     */    private void resetStates() {        if (_revealedList == null) {            _revealedList = new ArrayList<Boolean>(_panelCount);            for (int i=0; i < _panelCount; i++) {              _revealedList.add(i,false);            }        }        else{            for (int i = 0; i < _panelCount; i++) {                _revealedList.set(i, false);            }                    }    }    } As I said this class only manages a single set of topics in a single grid and it defined as a managed bean in your page flow definition for the relevant view something like this:   <managed-bean>    <managed-bean-name>revealManager</managed-bean-name>    <managed-bean-class>oracle.demo.view.RevealPanelManager</managed-bean-class>    <managed-bean-scope>view</managed-bean-scope>    <managed-property>      <property-name>panelCount</property-name>      <property-class>java.lang.Long</property-class>      <value>3</value>    </managed-property>  </managed-bean> Notice how the expected panel count (3) in this case  is injected into this bean. Once this management bean is defined then the content that we want to hide and display dynamically (e.g. the triangle panelGrouplayout and the revealPanel panelGrouplayout) and both use expression language to determine if they should be visible. e.g.  <af:panelGroupLayout layout="vertical"                      styleClass="triangleMarker"                     visible="#{viewScope.revealManager.revealed[0]}"/> Where the zero based index number is passed into the list evaluation.  The Click Event Handler The final thing we need to do is to find a way to call the toggleState() method in the revealManager. The only twist here is that we don't want to have a commandButton or link in the panel to click. We want to be able to click anywhere on the panel. This is a well established technique so you can look at the demo for the details of the code, but basically we define a small JavaScript function which is registered with the client side click. When the user clicks, this reads the numerical ID of the panel that was selected and makes a call back to the server to the handlePanelToggle() server listener method. That then talks to the revealManager, setting the id of the panel to toggle and invoking the toggle, finishing off with a partialUpdate to get the whole grid to re-draw. Have a look at the RevealRowComponentHandler.java class in the demo for the details.   And the Result Well here's the ADF implementation of the revealPanel. First closed: And now opened: The Demo I've uploaded a demo that shows the basic version of revealPanel discussed here and a more advanced version which is discussed in the next article.  You can download the sample from the ADF Code Samples RepositoryThis demo is not foolproof and at the moment the animations are restricted to Chrome and Safari (WebKit browsers) It also needs to check for older browser versions that do not support the animations and switch them off Note: The sample is written in 11.1.1.7 it will not work in 11.1.1.6 or older. Further Note: There seems to have been a slight change in the js API in 11.1.2.n which are breaking the code at the moment - working on that one

Working with one of our internal teams the other day, a couple of interesting ideas came up for presenting information. One of these was a sort of twist on panelAccordion and it seems to be a nice...

ADF Faces and UI

Get More From Your Messages

Within ADF Faces we take much goodness and added value for granted.  One such feature came to my attention just the other day. Had you noticed that when you have several errors outstanding on the screen the framework gives you a hyperlink to set focus to that field? See the error on commissionPct below and the hyperlink that you could click to move focus to it in the screen:  So that's neat and I must confess that although I must have stared this one in the face hundreds of times I never really groked how cool that was.  Anyway, as is usual, this was not just a random act of attention on my part but rather considering a couple of different user cases which both boiled down to the basic question.  Can we extend these error dialogs in some way to show more detail or carry out some other action in response to the error? So that's what I wanted to work through in this article, because the answer is (of course) yes! How to make the Messages Interactive? So let's take a look at how to do this. The clue is in the documentation for the tag which casually mentions that  you can include HTML into your Faces messages or message detail. and one of the examples is the embedding of an anchor tag to embed a hyperlink - something that could indeed be useful in a message.  So it occurred to me that this hyperlink provided the opportunity for  an actionable gesture that the user could make to do stuff within the actual application as well as jump off to another one. However, it's not all plain sailing, you can't just embed any old HTML markup into the messages (I did try!) So no embedding of buttons, and even for an <a> tag you can't wire in JavaScript with an onClick=, that all get stripped out. However, with a carefully shaped href attribute you can call JavaScript. So for example I've crafted the following message detail string: <html>Detail for errror <a href=javascript:errorDetailCallback('it1','d1');>here</a></html>  This renders the word "here" as a link in the message and then when the user clicks on that it calls a JavaScript errorDetailCallback() with a couple of arguments.  This function is included in a script linked onto the page using a standard <af:resource> tag. The script itself could do anything. In my sample I'm actually making it call back to the server (via an <af:serverListener> defined in the document. Here's the JavaScript function:  function errorDetailCallback(errorContext, documentComponentId){        var callbackComponent = AdfPage.PAGE.findComponentByAbsoluteId(documentComponentId);    if (callbackComponent != null) {        var serverEvent = new AdfCustomEvent(callbackComponent, "errorDetailEvent", {detailKey : errorContext}, true);        serverEvent.queue(true);    }    else{        AdfLogger.LOGGER.severe("errorDetailCallback: Error unable to locate document component: " + documentComponentId);    }  } The custom event is wired into the server via the <af:serverListener> tag: <af:serverListener type="errorDetailEvent"  method="#{indexPageBB.errorDrilldownHandler}"/>  The server side method (errorDrilldownHandler()) in my case gets the custom event and then shows a popup in response:  public void errorDrilldownHandler(ClientEvent clientEvent) {  Map params = clientEvent.getParameters();   String detailKey = (String)params.get("detailKey");   if (detailKey != null && _errorDetail.containsKey(detailKey)){    _lastErrorKey = detailKey;   }   else{     _lastErrorKey = "UNKNOWN";   }         //Now do what you want. In this case show a popup with a detail message   RichPopup.PopupHints hints = new RichPopup.PopupHints();   getDetailPopup().show(hints); } Note that in the above case, the _lastErrorKey  is simply a variable which is used by the getter that populates the text in the popup, it's used as a key into a Map with some further message details in it. However, what you do in this callback routine is of course up to you. 

Within ADF Faces we take much goodness and added value for granted.  One such feature came to my attention just the other day. Had you noticed that when you have several errors outstanding on the...

JDeveloper

Using JDeveloper 11.1.1.6 & 11.1.2.3 with Subversion 1.7

This issue has come up a couple of times this week and has also be raised on the OTN JDeveloper Forum, so it seemed to be worth a quick public-service announcement.   Subversion 1.7 introduces changes (AKA complete re-write) into the way that working copies are stored, the implication of this is that a 1.6 client and a 1.7 client cannot operate again the same working copy on a developer's workstation.  Current versions of JDeveloper's SVN support contain 1.6 client code, so if you are mixing and matching JDeveloper and SVN / Tortoise command line operations you will run into trouble.  e.g. The following sequence of operations will fail: Checkout working copy from the command line with the svn 1.7 client Make updates and attempt to checkin from JDeveloper  However, the following should work: Checkout working copy from JDeveloper  Make updates and checkin from JDeveloper  As will: Checkout working copy from the command line with the svn 1.7 client Disable the JDeveloper SVN plugin - (Versioning -> Configure -> Uncheck - Versioning Support for Subversion ) Make updates  to existing files only from JDeveloper Commit / Add / Delete operations from Command line svn 1.7 client.  Obviously, for convenience and because some operations such as refactoring need to issue SVN commands I'd recommend that, if using a 1.7 repository, you carry out all operations including the initial checkout from within the IDE.   As a general guidance if you are going to upgrade your repository (and my further advice would be not to upgrade at the moment if your primary client is JDeveloper) I'd recommend that you clean up any outstanding transactions before the upgrade, and then, once the server is up to 1.7, do a clean checkout from JDeveloper and stick to working within that environment.

This issue has come up a couple of times this week and has also be raised on the OTN JDeveloper Forum, so it seemed to be worth a quick public-service announcement.   Subversion 1.7 introduces changes...

ADF

MySQL & ADF Business Components - Enum types

Using ADF BC against MySQL is, I feel, a fairly under-explored area, and although there  are several articles which will help you with the basic setup, things start to fade out when you get into it.  I think that the key missing link is that of data type mapping so I'm intending to put together a series of articles that will explore some of these topics.  Here, I'll start with a pretty fundamental one. If you explore the MySQL World database (or indeed the Sakila database) you'll come across enum types. (If you want to follow along here you can head over to the MySQL Other Documentation page to get the World database to play with.) The World database contains a table called Country: +-----------------+| Tables_in_world |+-----------------+| City            || Country         || CountryLanguage |+-----------------+ And if we describe that, here is the definition: +----------------+---------------------------------------------------------------------------------------+------+-----+---------+-------+| Field          | Type                                                                                  | Null | Key | Default | Extra |+----------------+---------------------------------------------------------------------------------------+------+-----+---------+-------+| Code           | char(3)                                                                               | NO   | PRI |         |       || Name           | char(52)                                                                              | NO   |     |         |       || Continent      | enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') | NO   |     | Asia    |       || Region         | char(26)                                                                              | NO   |     |         |       || SurfaceArea    | float(10,2)                                                                           | NO   |     | 0.00    |       || IndepYear      | smallint(6)                                                                           | YES  |     | NULL    |       || Population     | int(11)                                                                               | NO   |     | 0       |       || LifeExpectancy | float(3,1)                                                                            | YES  |     | NULL    |       || GNP            | float(10,2)                                                                           | YES  |     | NULL    |       || GNPOld         | float(10,2)                                                                           | YES  |     | NULL    |       || LocalName      | char(45)                                                                              | NO   |     |         |       || GovernmentForm | char(45)                                                                              | NO   |     |         |       || HeadOfState    | char(60)                                                                              | YES  |     | NULL    |       || Capital        | int(11)                                                                               | YES  |     | NULL    |       || Code2          | char(2)                                                                               | NO   |     |         |       |+----------------+---------------------------------------------------------------------------------------+------+-----+---------+-------+ For now, let's concentrate on the Continent field, defined as enum('Asia','Europe',...) . Functionally this is similar, I guess to a varchar2 column in Oracle, with an  check constraint using an "in" with a static list.  So if we generate a BC Entity object from that table, what do we get for the Continent field, (this is using SQL92 mode and the Java type-map in 11.1.2.3 of JDeveloper):   <Attribute    Name="Continent"    IsNotNull="true"    ColumnName="Continent"    SQLType="$none$"    Domain="oracle.demo.mysql.model.eo.Enum"    Type="oracle.demo.mysql.model.eo.common.Enum"    ColumnType="ENUM"    TableName="world.Country"/> So you can see here that the Type seems to be something specific to my project, and indeed, the generation of the entity has not only generated the XML for the EO but also the XML and Java class for a new domain type called  oracle.demo.mysql.model.eo.common.Enum.  This generated class implements the oracle.jbo.domain.DomainInterface, and we'll have a look at it in a bit more detail in a second. Does it Work Though? So what if we stop right there and just run the ADF BC  tester, does the default EO/VO combo actually function? Well the answer to that is Yes (which is a relief!), however, if you change the value of the Continent field to an invalid value (i.e. not one of the values listed in the enum) then the default error message is a little sparse on the actual reason for the problem: JBO-26041: Failed to post data to database during "Update":  SQL Statement "UPDATE world.Country Country SET Continent=? WHERE Code=?". What's more, you don't see this error until the data is actually posted to the database and it would be nice to do this kind of validation up-front. A second, related problem is down to the way that enums are handled in MySQL.  If I update the field to a valid value, but use a different case from that declared in the enum() e.g. SOUTH America, then MySQL will nicely match this and convert it to "South America" in the database. However, that of course mutates the record as far as ADFBC is concerned and further updates will result in: JBO-25014: Another user has changed the row with primary key oracle.jbo.Key[... ]. So how can we improve things? So first of all, it's trivial to fix the locking problem (JBO-25014 error). For that we just need to update the properties of the attribute in the EO to refresh after insert and update: Next, how can we improve both the timing and the error message provided by the validation? Well in this case we need to fill in some blanks in the generated domain class.  If you have a look at it you'll see that there is a validate() method stub generated into the class.     /**     * Implements domain validation logic and throws a JboException on error.     */    protected void validate() {        //  ### Implement custom domain validation logic here. ###    }  Not surprisingly all we need to do there is implement some logic in that and throw a JboException with a more informative error message.  This will ensure that not only is the message better, but also validation will happen as soon as the field value is set in the EO, rather than being deferred and waiting for the database post. Before you implement the method though I'd recommend that you do some refactoring to change both the name of the Domain and Java class to  something a little more specific than "Enum".  To do this, simple select the top level Enum node in the navigator and use Refactor | Rename  from the menu bar. This will rename the Java class, the XML file and of course fix up the Country EO itself correctly. I've renamed mine to CountryContinentsEnum. Implement the Validation Logic   The logic we need in this case is to inspect the mData value inside of the validate() method and compare it to a list of the valid Continents (as defined by the MySQL column definition). The twist here is to remember that MySQL will in fact be happy with any case combination for the Enum value, so we need to carry out a case insensitive compare.  In my example this consists of three steps: 1) Define the list of Valid Values I actually use a HashMap here where the key of the map is the uppercase version of the Continent name and the value is the lower case value.  For the validation below we only need the uppercase version for the actual check, but it's nice to have the mixed case version for any exception messages that we raise. This list is stored in a static class variable: public static final Map<String, String> CONTINENT_ENUM = new HashMap<String, String>(7); 2) Populate the Valid Values Map I populate the Map in a static block in the class.  These values can be shared across all instances. static {   CONTINENT_ENUM.put("ASIA", "Asia");   CONTINENT_ENUM.put("EUROPE", "Europe");   CONTINENT_ENUM.put("NORTH AMERICA", "North America");   CONTINENT_ENUM.put("AFRICA", "Africa");   CONTINENT_ENUM.put("OCEANIA", "Oceania");   CONTINENT_ENUM.put("ANTARCTICA", "Antarctica");   CONTINENT_ENUM.put("SOUTH AMERICA", "South America");} Hint: Why not map the To-Uppercase keyboard shortcut in Tools | Preferences, it's not mapped by default but the function is there in the IDE! That will make it easier to create the uppercase version of the value.  3) Implement the validate() Method Finally the actual validate method.  Most of this is the error handling as the actual validation check itself is a simple (and quick) containsKey() call on the map. protected void validate() { // MySQL will convert the value to the expected case    if (!CONTINENT_ENUM.containsKey(mData.toUpperCase())) { //Construct a nice error to send to the client  boolean firstLoop = true;    StringBuilder errorMsg = new StringBuilder("Incorrect continent value suppied. Pick one from ");    for (Map.Entry<String, String> entry : CONTINENT_ENUM.entrySet() ){    if (!firstLoop){      errorMsg.append(", ");      }      errorMsg.append(entry.getValue());      firstLoop = false;    }    throw new JboException(errorMsg.toString());  }} Now to test that, here's the result when we put an invalid value into the BC Tester: Great, but look what happens when we have a Web UI bound to the same component and attempt to put an invalid value in: Whoops! So here's a slight problem, when run through the binding layer we're not seeing that well crafted error message, instead there is some data conversion error. What's more if I change to a valid value such as "Asia" I get the same error, so it's not my validate() method that's barfing here.  (in fact if you remove the validate method all together then you'll still get the error). What to Do? What's happening here is that the binding layer itself is sensibly doing a check on datatype and is not seeing how to do the conversion (even though ADF BC itself will handle an incoming string). So we need to give JSF a little help and specify a Converter.  A basic converter in JSF is very simple, it just has to implement two methods getAsString() and getAsObject() which convert from the Object Type to a String for HTTP to use and visa-versa. Here's the simple implementation in this case: package oracle.demo.mysql.view;import javax.faces.application.FacesMessage;import javax.faces.component.UIComponent;import javax.faces.context.FacesContext;import javax.faces.convert.Converter;import javax.faces.convert.ConverterException;import oracle.adf.share.logging.ADFLogger;import oracle.demo.mysql.model.eo.common.CountryContinentsEnum;import oracle.jbo.JboException;/** * Generic converter for MySQL the Continent Enum type that is just an enummeration of Strings * This simply wraps the real conversion which will happen at the ADF BC layer */public class ContinentEnumConverter implements Converter {        private static ADFLogger _logger = ADFLogger.createADFLogger(ContinentEnumConverter.class);        public ContinentEnumConverter() {        super();    }    /**     * Standard converter class method that converts the String form of the object sent with the HTTP request      * into the real object type that needs to be handed off to the model     * @param facesContext     * @param uIComponent     * @param stringValue      * @return CountryContinentsEnum created from stringValue     */    @Override    public Object getAsObject(FacesContext facesContext, UIComponent uIComponent, String stringValue) {        CountryContinentsEnum continent = null;        try {            continent = new CountryContinentsEnum(stringValue);            }        catch (JboException jboex){            //If the validate method is failed then this is the exception that we will get             reportConversionProblem(jboex.getMessage(),false);                    }        catch (Exception ex) {            //Others: just in case            reportConversionProblem("Error: Can't create instance of Continent " + ex,true);                    }                return continent;    }    /**     * Standard converter method that converts from the Object type to a String form suitable for HTTP      * @param facesContext     * @param uIComponent     * @param objectValue     * @return String value of objectValue     */    @Override    public String getAsString(FacesContext facesContext, UIComponent uIComponent, Object objectValue) {        return objectValue.toString();    }            /*     * Just queues up the conversion problem and optionally logs it as well       */    private void reportConversionProblem(String message, boolean logit){        if (logit){            _logger.severe("Error: " + message);         }        FacesMessage fmsg = new FacesMessage(null,message);        fmsg.setSeverity(FacesMessage.SEVERITY_ERROR);        throw new ConverterException(fmsg);    }}  Once you have a converter class it then has to be associated with the components that it will need to operate on in some way.  There are two options, firstly you can associate the converter with a specific class so that whenever JSF encounters a conversion using that class it will use the associated converter for that, or secondly you can create the converter with a specific ID and then associate that converter ID with individual components using the <f:converter converterId="..."> tag. In this case I'm using the former method so that I won't have to make any changes to the page, I just need this entry in my faces-config.xml file: <converter> <converter-for-class> oracle.demo.mysql.model.eo.common.CountryContinentsEnum </converter-for-class> <converter-class> oracle.demo.mysql.view.ContinentEnumConverter </converter-class></converter> Now when we induce an error, here's the result: An Easier Way? In this example, I've taken a very strictly typed approach to MySQL Enums where we're able to take advantage of the ADF BC domain capabilities to handle the type conversion. However, the fact remains that enums in MySQL are always lists of Strings, so another valid approach to the problem is to simply change the generated mapping from the enum type to String and then add on a validation in the ADF BC layer to restrict the valid values that can be squirted into MySQL.  You'll have to handle the fact that the case does not have to match exactly as part of this validation though. My preference though would be to stick to the explicit type conversion method I'm using here, but pair that with a list of values definition on the attribute so that the UI always presents the enumeration as a list in any case.

Using ADF BC against MySQL is, I feel, a fairly under-explored area, and although there  are several articles which will help you with the basic setup, things start to fade out when you get into it.  ...

ADF

Refresh Problems using Adaptive Bindings

In a previous article (Towards Ultra-Reusability for ADF - Adaptive Bindings)  I discussed how ADF Data Binding can be a lot more flexible that you would think due to the neat trick of being able to use expression language within the PageDef file to create bind sources that  can be switched at runtime.As it happens my good buddy Frank Nimphius picked up the technique to use on a particular  project and hit a slight problem. If you change the results of the EL used in the binding - for example, you switch the base VO from Departments to Employees, things don't get refreshed correctly.  In fact what you see is that any attribute names that happen to match between the old and the new source will be correctly populated with the new data but the actual list of attributes will not be refreshed. The effect is that if you were using one of these bindings to populate a table, the "shape" of the table, in terms of its columns, would not change. No worries though, given that Frank is a clever chap he worked out the correct way to address this which is to simply call clearForRecreate() on the iterator binding. BindingContext bctx = BindingContext.getCurrent(); BindingContainer bindings = bctx.getCurrentBindingsEntry(); DCIteratorBinding iter = (DCIteratorBinding) bindings.get("TableSourceIterator"); iter.clearForRecreate();Thanks Frank! 

In a previous article (Towards Ultra-Reusability for ADF - Adaptive Bindings)  I discussed how ADF Data Binding can be a lot more flexible that you would think due to the neat trick of being able to...

ADF Faces and UI

Dude, how big's my browser?

It's sometimes funny how the same question comes from several unrelated places at almost the same time. I've had just such a question from a couple of unrelated projects recently, the query being the simple one of "how big is my browser window"? Now in many cases this is a null question. With the correct use of layout containers (and testing) you can build layouts in ADF which adapt, flow and stretch well as the user re-sizes the browser. However, there are circumstances, as was the case here, where you want more drastic changes based in the amount of space you have to play with.  For example you may choose to hide a column in a table if the screen is below a certain size. Well this is certainly possible, but of course it comes at a price.  If you want to know when the browser window has been resized you have to tell the server, and that's a round trip. So to do this efficiently this is not totally trivial. However, to save you the trouble of thinking too hard, I've written a sample - it is Christmas after all and Christmas is all about giving.  The sample can be downloaded from the ADF Samples site on Java.net. ADFDetectWindowResize.zip It's all pretty well documented  so I won't explain the code line by line here, but needless to say there is a bit of JavaScript and a server side event handler to listen for events queued from that script. I use a configurable JavaScript timer to buffer the resize events and keep the number of notifications to the server to an acceptable level.  Once you have the  sizing information from the client, of course it's up to you to decide what to do with it! The sample is written in 11.1.1.6 and will work for 11.1.1.n and 11.1.2.n versions. 

It's sometimes funny how the same question comes from several unrelated places at almost the same time. I've had just such a question from a couple of unrelated projects recently, the query being the...

Misc

Selective Suppression of Log Messages

Those of you who regularly read this blog will probably have noticed that I have a strange predilection for logging related topics, so why break this habit I ask?  Anyway here's an issue which came up recently that I thought was a good one to mention in a brief post.  The scenario really applies to production applications where you are seeing entries in the log files which are harmless, you know why they are there and are happy to ignore them, but at the same time you either can't or don't want to risk changing the deployed code to "fix" it to remove the underlying cause. (I'm not judging here). The good news is that the logging mechanism provides a filtering capability which can be applied to a particular logger to selectively "let a message through" or suppress it. This is the technique outlined below. First Create Your Filter  You create a logging filter by implementing the java.util.logging.Filter interface. This is a very simple interface and basically defines one method isLoggable() which simply has to return a boolean value. A return of false will suppress that particular log message and not pass it onto the handler. The method is passed the log record of type java.util.logging.LogRecord which provides you with access to everything you need to decide if you want to let this log message pass through or not, for example  getLoggerName(), getMessage() and so on. So an example implementation might look like this if we wanted to filter out all the log messages that start with the string "DEBUG" when the logging level is not set to FINEST:  public class MyLoggingFilter implements Filter {    public boolean isLoggable(LogRecord record) {        if ( !record.getLevel().equals(Level.FINEST) && record.getMessage().startsWith("DEBUG")){         return false;           }        return true;    }} Deploying   This code needs to be put into a JAR and added to your WebLogic classpath.  It's too late to load it as part of an application, so instead you need to put the JAR file into the WebLogic classpath using a mechanism such as the PRE_CLASSPATH setting in your domain setDomainEnv script. Then restart WLS of course. Using The final piece if to actually assign the filter.  The simplest way to do this is to add the filter attribute to the logger definition in the logging.xml file. For example, you may choose to define a logger for a specific class that is raising these messages and only apply the filter in that case.  <logger name="some.vendor.adf.ClassICantChange"        filter="oracle.demo.MyLoggingFilter"/> You can also apply the filter using WLST if you want a more script-y solution.

Those of you who regularly read this blog will probably have noticed that I have a strange predilection for logging related topics, so why break this habit I ask?  Anyway here's an issue which came up...

ADF

Towards Ultra-Reusability for ADF - Adaptive Bindings

The task flow mechanism embodies one of the key value propositions of the ADF Framework, it's primary contribution being the componentization of your applications and implicitly the introduction of a re-use culture, particularly in large applications. However, what if we could do more? How could we make task flows even more re-usable than they are today? Well one great technique is to take advantage of a feature that is already present in the framework, a feature which I will call, for want of a better name, "adaptive bindings". What's an adaptive binding? well consider a simple use case.  I have several screens within my application which display tabular data which are all essentially identical, the only difference is that they happen to be based on different data collections (View Objects, Bean collections, whatever) , and have a different set of columns. Apart from that, however, they happen to be identical; same toolbar, same key functions and so on. So wouldn't it be nice if I could have a single parametrized task flow to represent that type of UI and reuse it? Hold on you say, great idea, however, to do that we'd run into problems. Each different collection that I want to display needs different entries in the pageDef file and: I want to continue to use the ADF Bindings mechanism rather than dropping back to passing the whole collection into the taskflow   If I do use bindings, there is no way I want to have to declare iterators and tree bindings for every possible collection that I might want the flow to handle  Ah, joy! I reply, no need to panic, you can just use adaptive bindings. Defining an Adaptive Binding  It's easiest to explain with a simple before and after use case.  Here's a basic pageDef definition for our familiar Departments table.  <executables> <iterator Binds="DepartmentsView1" DataControl="HRAppModuleDataControl" RangeSize="25"             id="DepartmentsView1Iterator"/></executables><bindings> <tree IterBinding="DepartmentsView1Iterator" id="DepartmentsView1">  <nodeDefinition DefName="oracle.demo.model.vo.DepartmentsView" Name="DepartmentsView10">    <AttrNames>      <Item Value="DepartmentId"/>        <Item Value="DepartmentName"/>        <Item Value="ManagerId"/>        <Item Value="LocationId"/>      </AttrNames>    </nodeDefinition> </tree></bindings>  Here's the adaptive version: <executables> <iterator Binds="${pageFlowScope.voName}" DataControl="HRAppModuleDataControl" RangeSize="25"             id="TableSourceIterator"/></executables><bindings> <tree IterBinding="TableSourceIterator" id="GenericView"> <nodeDefinition Name="GenericViewNode"/> </tree></bindings>  You'll notice three changes here.   Most importantly, you'll see that the hard-coded View Object name  that formally populated the iterator Binds attribute is gone and has been replaced by an expression (${pageFlowScope.voName}). This of course, is key, you can see that we can pass a parameter to the task flow, telling it exactly what VO to instantiate to populate this table! I've changed the IDs of the iterator and the tree binding, simply to reflect that they are now re-usable The tree binding itself has simplified and the node definition is now empty.  Now what this effectively means is that the #{node} map exposed through the tree binding will expose every attribute of the underlying iterator's collection - neat! (kudos to Eugene Fedorenko at this point who reminded me that this was even possible in his excellent "deep dive" session at OpenWorld  this year) Using the adaptive binding in the UI Now we have a parametrized  binding we have to make changes in the UI as well, first of all to reflect the new ID that we've assigned to the binding (of course) but also to change the column list from being a fixed known list to being a generic metadata driven set: <af:table value="#{bindings.GenericView.collectionModel}" rows="#{bindings.GenericView.rangeSize}"         fetchSize="#{bindings.GenericView.rangeSize}"          emptyText="#{bindings.GenericView.viewable ? 'No data to display.' : 'Access Denied.'}"          var="row" rowBandingInterval="0"           selectedRowKeys="#{bindings.GenericView.collectionModel.selectedRow}"          selectionListener="#{bindings.GenericView.collectionModel.makeCurrent}"          rowSelection="single" id="t1"> <af:forEach items="#{bindings.GenericView.attributeDefs}" var="def">  <af:column headerText="#{bindings.GenericView.labels[def.name]}" sortable="true"           sortProperty="#{def.name}" id="c1">    <af:outputText value="#{row.bindings[def.name].inputValue}" id="ot1"/>     </af:column>  </af:forEach></af:table> Of course you are not constrained to a simple read only table here.  It's a normal tree binding and iterator that you are using behind the scenes so you can do all the usual things, but you can see the value of using ADFBC as the back end model as you have the rich pantheon of UI hints to use to derive things like labels (and validators and converters...)  One Final Twist  To finish on a high note I wanted to point out that you can take this even further and achieve the ultra-reusability I promised. Here's the new version of the pageDef iterator, see if you can notice the subtle change? <iterator Binds="{pageFlowScope.voName}"  DataControl="${pageFlowScope.dataControlName}" RangeSize="25"           id="TableSourceIterator"/>  Yes, as well as parametrizing the collection (VO) name, we can also parametrize the name of the data control. So your task flow can graduate from being re-usable within an application to being truly generic. So if you have some really common patterns within your app you can wrap them up and reuse then across multiple developments without having to dictate data control names, or connection names. This also demonstrates the importance of interacting with data only via the binding layer APIs. If you keep any code in the task flow generic in that way you can deal with data from multiple types of data controls, not just one flavour. Enjoy! Update Read this post as well on overcoming possible refresh problems when changing the source on a single page. Further updateCheck out this article from Luc Bors on using similar ideas with Query Components / View Criteria.  

The task flow mechanism embodies one of the key value propositions of the ADF Framework, it's primary contribution being the componentization of your applications and implicitly the introduction of a...

ADF Faces and UI

Controlling the Sizing of the af:messages Dialog

Over the last day or so a small change in behaviour between 11.1.2.n releases of ADF and earlier versions has come to my attention. This has concerned the default sizing of the dialog that the framework automatically generates to handle the display of JSF messages being handled by the <af:messages> component. Unlike a normal popup, you don't have a physical <af:dialog> or <af:window> to set the sizing on in your page definition, so you're at the mercy of what the framework provides. In this case the framework now defines a fixed 250x250 pixel content area dialog for these messages, which can look a bit weird if the message is either very short, or very long. Unfortunately this is not something that you can control through the skin, instead you have to be a little more creative. Here's the solution I've come up with.  Unfortunately, I've not found a supportable way to reset the dialog so as to say  just size yourself based on your contents, it is actually possible to do this by tweaking the correct DOM objects, but I wanted to start with a mostly supportable solution that only uses the best practice of working through the ADF client side APIs. The Technique The basic approach I've taken is really very simple.  The af:messages dialog is just a normal richDialog object, it just happens to be one that is pre-defined for you with a particular known name "msgDlg" (which hopefully won't change). Knowing this, you can call the accepted APIs to control the content width and height of that dialog, as our meerkat friends would say, "simples" 1 The JavaScript For this example I've defined three JavaScript functions.   The first does all the hard work and is designed to be called from server side Java or from a page load event to set the default. The second is a utility function used by the first to validate the values you're about to use for height and width. The final function is one that can be called from the page load event to set an initial default sizing if that's all you need to do. Function resizeDefaultMessageDialog() /**  * Function that actually resets the default message dialog sizing.  * Note that the width and height supplied define the content area  * So the actual physical dialog size will be larger to account for  * the chrome containing the header / footer etc.  * @param docId Faces component id of the document  * @param contentWidth - new content width you need  * @param contentHeight - new content height  */ function resizeDefaultMessageDialog(docId, contentWidth, contentHeight) {   // Warning this value may change from release to release   var defMDName = "::msgDlg";   //Find the default messages dialog   msgDialogComponent = AdfPage.PAGE.findComponentByAbsoluteId(docId + defMDName); // In your version add a check here to ensure we've found the right object!   // Check the new width is supplied and is a positive number, if so apply it.   if (dimensionIsValid(contentWidth)){       msgDialogComponent.setContentWidth(contentWidth);   }   // Check the new height is supplied and is a positive number, if so apply it.   if (dimensionIsValid(contentHeight)){       msgDialogComponent.setContentHeight(contentHeight);   } }  Function dimensionIsValid()  /** * Simple function to check that sensible numeric values are  * being proposed for a dimension * @param sampleDimension  * @return booolean */function dimensionIsValid(sampleDimension){    return (!isNaN(sampleDimension) && sampleDimension > 0);} Function  initializeDefaultMessageDialogSize() /** * This function will re-define the default sizing applied by the framework  * in 11.1.2.n versions * It is designed to be called with the document onLoad event */function initializeDefaultMessageDialogSize(loadEvent){  //get the configuration information  var documentId = loadEvent.getSource().getProperty('documentId');  var newWidth = loadEvent.getSource().getProperty('defaultMessageDialogContentWidth');  var newHeight = loadEvent.getSource().getProperty('defaultMessageDialogContentHeight');  resizeDefaultMessageDialog(documentId, newWidth, newHeight);} Wiring in the Functions As usual, the first thing we need to do when using JavaScript with ADF is to define an af:resource  in the document metaContainer facet <af:document>   ....     <f:facet name="metaContainer">     <af:resource type="javascript" source="/resources/js/hackMessagedDialog.js"/>   </f:facet></af:document> This makes the script functions available to call.  Next if you want to use the option of defining an initial default size for the dialog you use a combination of <af:clientListener> and <af:clientAttribute> tags like this. <af:document title="MyApp" id="doc1">   <af:clientListener method="initializeDefaultMessageDialogSize" type="load"/>   <af:clientAttribute name="documentId" value="doc1"/>   <af:clientAttribute name="defaultMessageDialogContentWidth" value="400"/>   <af:clientAttribute name="defaultMessageDialogContentHeight" value="150"/> ...   Just in Time Dialog Sizing  So  what happens if you have a variety of messages that you might add and in some cases you need a small dialog and an other cases a large one? Well in that case you can re-size these dialogs just before you submit the message. Here's some example Java code: FacesContext ctx = FacesContext.getCurrentInstance();        //reset the default dialog size for this messageExtendedRenderKitService service =              Service.getRenderKitService(ctx, ExtendedRenderKitService.class);service.addScript(ctx, "resizeDefaultMessageDialog('doc1',100,50);");        FacesMessage msg = new FacesMessage("Short message");msg.setSeverity(FacesMessage.SEVERITY_ERROR);ctx.addMessage(null, msg);  So there you have it. This technique should, at least, allow you to control the dialog sizing just enough to stop really objectionable whitespace or scrollbars. 1 Don't worry if you don't get the reference, lest's just say my kids watch too many adverts.

Over the last day or so a small change in behaviour between 11.1.2.n releases of ADF and earlier versions has come to my attention. This has concerned the default sizing of the dialog that the...

ADF Faces and UI

Centered Content using panelGridLayout

A classic layout conundrum,  which I think pretty much every ADF developer may have faced at some time or other, is that of truly centered (centred) layout. Typically this requirement comes up in relation to say displaying a login type screen or similar. Superficially the  problem seems easy, but as my buddy Eduardo explained when discussing this subject a couple of years ago it's actually a little more complex than you might have thought. If fact, even the "solution" provided in that posting is not perfect and suffers from a several issues (not Eduardo's fault, just limitations of panelStretch!) The top, bottom, end and start facets all need something in them The percentages you apply to the topHeight, startWidth etc. are calculated as part of the whole width.  This means that you have to guestimate the correct percentage based on your typical screen size and the sizing of the centered content. So, at best, you will in fact only get approximate centering, and the more you tune that centering for a particular browser size the more it will fail if the user resizes. You can't attach styles to the panelStretchLayout facets so to provide things like background color or fixed sizing you need to embed another container that you can apply styles to, typically a panelgroupLayout For reference here's the code to print a simple 100px x 100px red centered square  using the panelStretchLayout solution, approximately tuned to a 1980 x 1080 maximized browser (IDs omitted for brevity): <af:panelStretchLayout startWidth="45%" endWidth="45%"                        topHeight="45%"  bottomHeight="45%" >  <f:facet name="center">    <af:panelGroupLayout inlineStyle="height:100px;width:100px;background-color:red;"                          layout="vertical"/>  </f:facet>  <f:facet name="top">    <af:spacer height="1" width="1"/>  </f:facet>  <f:facet name="bottom">    <af:spacer height="1" width="1"/>  </f:facet>  <f:facet name="start">    <af:spacer height="1" width="1"/>  </f:facet>  <f:facet name="end">    <af:spacer height="1" width="1"/>   </f:facet></af:panelStretchLayout>  And so to panelGridLayout  So here's the  good news, panelGridLayout makes this really easy and it works without the caveats above.  The key point is that percentages used in the grid definition are evaluated after the fixed sizes are taken into account, so rather than having to guestimate what percentage will "more, or less", center the content you can just say "allocate half of what's left" to the flexible content and you're done. Here's the same example using panelGridLayout: <af:panelGridLayout> <af:gridRow height="50%"/> <af:gridRow height="100px"> <af:gridCell width="50%" /> <af:gridCell width="100px" halign="stretch" valign="stretch"  inlineStyle="background-color:red;"> <af:spacer width="1" height="1"/> </af:gridCell> <af:gridCell width="50%" /> </af:gridRow> <af:gridRow height="50%"/></af:panelGridLayout>  So you can see that the amount of markup is somewhat smaller (as is, I should mention, the generated DOM structure in the browser), mainly because we don't need to introduce artificial components to ensure that facets are actually observed in the final result.  But the key thing here is that the centering is no longer approximate and it will work as expected as the user resizes the browser screen.  By far this is a more satisfactory solution and although it's only a simple example, it will hopefully open your eyes to the potential of panelGridLayout as your number one, go-to layout container.Just a reminder though, right now, panelGridLayout is only available in 11.1.2.2 and above.

A classic layout conundrum,  which I think pretty much every ADF developer may have faced at some time or other, is that of truly centered (centred) layout. Typically this requirement comes up in...

ADF

ADF Logging In Deployed Apps

Harking back to my series on using the ADF logger and the related  ADF Insider Video, I've had a couple of queries this week about using the logger from Enterprise Manager (EM). I've alluded in those previous materials to how EM can be used but it's evident that folks need a little help.  So in this article, I'll quickly look at how you can switch logging on from the EM console for an application and how you can view the output.  Before we start I'm assuming that you have EM up and running, in my case I have a small test install of Fusion Middleware Patchset 5 with an ADF application deployed to a managed server. Step 1 - Select your Application In the EM navigator select the app you're interested in: At this point you can actually bring up the context ( right mouse click) menu to jump to the logging, but let's do it another way.  Step 2 - Open the Application Deployment Menu At the top of the screen, underneath the application name, you'll find a drop down menu which will take you to the options to view log messages and configure logging, thus: Step 3 - Set your Logging Levels  Just like the log configuration within JDeveloper, we can set up transient or permanent (not recommended!) loggers here. In this case I've filtered the class list down to just oracle.demo, and set the log level to config. You can now go away and do stuff in the app to generate log entries. Step 4 - View the Output  Again from the Application Deployment menu we can jump to the log viewer screen and, as I have here, start to filter down the logging output to the stuff you're interested in.  In this case I've filtered by module name. You'll notice here that you can again look at related log messages. Importantly, you'll also see the name of the log file that holds this message, so it you'd rather analyse the log in more detail offline, through the ODL log analyser in JDeveloper, then you can see which log to download.

Harking back to my series on using the ADF logger and the related  ADF Insider Video, I've had a couple of queries this week about using the logger from Enterprise Manager (EM). I've alluded in those...

ADF

ADF - Now with Robots!

I mentioned this briefly in a tweet the other day, just before the full rush of OOW really kicked off, so I though it was worth re-visiting. Check out this video, and then read on: So why so interesting? Well - you probably guessed from the title, ADF is involved. Indeed this is as about as far from the traditional ADF data entry application as you can get. Instead of a database at the back-end there's basically a robot. That's right, this remarkable tape drive is controlled through an ADF using all your usual friends of ADF Faces, Controller and Binding (but no ADFBC for obvious reasons). ADF is used both on the touch screen you see on the front of the device in the video, and also for the remote management console which provides a visual representation of the slots and drives. The latter uses ADF's Active Data Framework to provide a real-time view of what's going on the rack. . What's even more interesting (for the techno-geeks) is the fact that all of this is running out of flash storage on a ridiculously small form factor with tiny processor - I probably shouldn't reveal the actual specs but take my word for it, don't complain about the capabilities of your laptop ever again! This is a project that I've been personally involved in and I'm pumped to see such a good result and,  I have to say, those hardware guys are great to work with (and have way better toys on their desks than we do). More info in the SL150 (should you feel the urge to own one) is here. 

I mentioned this briefly in a tweet the other day, just before the full rush of OOW really kicked off, so I though it was worth re-visiting. Check out this video, and then read on: So why so...

ADF Faces and UI

PanelGridLayout - A Layout Revolution

With the most recent 11.1.2 patchset (11.1.2.3) there has been a lot of excitement around ADF Essentials (and rightly so), however, in all the fuss I didn't want an even more significant change to get missed - yes you read that correctly, a more significant change! I'm talking about the new panelGridLayout component, I can confidently say that this one of the most revolutionary components that we've introduced in 11g, even though it sounds rather boring. To be totally accurate, panelGrid was introduced in 11.1.2.2 but without any presence in the component palette or other design time support, so it was largely missed unless you read the release notes. However in this latest patchset it's finally front and center. Its time to explore - we (really) need to talk about layout.  Let's face it,with ADF Faces rich client, layout is a rather arcane pursuit, once you are a layout master, all bow before you, but it's more of an art than a science, and it is often, in fact, way too difficult to achieve what should (apparently) be a pretty simple. Here's a great example, it's a homework assignment I set for folks I'm teaching this stuff to:  The requirements for this layout are: The header is 80px high, the footer is 30px. These are both fixed.  The first section of the header containing the logo is 180px wide The logo is centered within the top left hand corner of the header  The title text is start aligned in the center zone of the header and will wrap if the browser window is narrowed. It should be aligned in the center of the vertical space  The about link is anchored to the right hand side of the browser with a 20px gap and again is center aligned vertically. It will move as the browser window is reduced in width. The footer has a right aligned copyright statement, again middle aligned within a 30px high footer region and with a 20px buffer to the right hand edge. It will move as the browser window is reduced in width. All remaining space is given to a central zone, which, in this case contains a panelSplitter. Expect that at some point in time you'll need a separate messages line in the center of the footer.  In the homework assigment I set I also stipulate that no inlineStyles can be used to control alignment or margins and no use of other taglibs (e.g. JSF HTML or Trinidad HTML). So, if we take this purist approach, that basic page layout (in my stock solution) requires 3 panelStretchLayouts, 5 panelGroupLayouts and 4 spacers - not including the spacer I use for the logo and the contents of the central zone splitter - phew! The point is that even a seemingly simple layout needs a bit of thinking about, particulatly when you consider strechting and browser re-size behavior. In fact, this little sample actually teaches you much of what you need to know to become vaguely competant at layouts in the framework. The underlying result of "the way things are" is that most of us reach for panelStretchLayout before even finishing the first sip of coffee as we embark on a new page design. In fact most pages you will see in any moderately complex ADF page will basically be nested panelStretchLayouts and panelGroupLayouts, sometimes many, many levels deep. So this is a problem, we've known this for some time and now we have a good solution. (I should point out that the oft-used Trinidad trh tags are not a particularly good solution as you're tie-ing yourself to an HTML table based layout in that case with a host of attendent issues in resize and bi-di behavior, but I digress.) So, tadaaa, I give to you panelGridLayout. PanelGrid, as the name suggests takes a grid like (dare I say slightly gridbag-like) approach to layout, dividing your layout into rows and colums with margins, sizing, stretch behaviour, colspans and rowspans all rolled in, all without the use of inlineStyle. As such, it provides for a much more powerful and consise way of defining a layout such as the one above that is actually simpler and much more logical to design. The basic building blocks are the panelGridLayout itself, gridRow and gridCell. Your content sits inside the cells inside the rows, all helpfully allowing both streching, valign and halign definitions without the need to nest further panelGroupLayouts. So much simpler!  If I break down the homework example above my nested comglomorate of 12 containers and spacers can be condensed down into a single panelGrid with 3 rows and 5 cell definitions (39 lines of source reduced to 24 in the case of the sample). What's more, the actual runtime representation in the browser DOM is much, much simpler, and clean, with basically one DIV per cell (Note that just because the panelGridLayout semantics looks like an HTML table does not mean that it's rendered that way!) . Another hidden benefit is the runtime cost. Because we can use a single layout to achieve much more complex geometries the client side layout code inside the browser is having to work a lot less. This will be a real benefit if your application needs to run on lower powered clients such as netbooks or tablets. So, it's time, if you're on 11.1.2.2 or above, to smile warmly at your panelStretchLayouts, wrap the blanket around it's knees and wheel it off to the Sunset Retirement Home for a well deserved rest. There's a new kid on the block and it wants to be your friend. Update: panelGridLayout is also available in the 11.1.1.7 release as well as the 11.1.2.n series. 

With the most recent 11.1.2 patchset (11.1.2.3) there has been a lot of excitement around ADF Essentials (and rightly so), however, in all the fuss I didn't want an even more significant change to get...

ADF

forEach and Facelets - a bugfarm just waiting for harvest

An issue that I've encountered before and saw again today seems worthy of a little write-up. It's all to do with a subtle yet highly important difference in behaviour between JSF 2 running with JSP and running on Facelets (.jsf pages). The incident I saw today can be seen as a report on the ADF EMG bugzilla (Issue 53) and in a blog posting by Ulrich Gerkmann-Bartels who reported the issue to the EMG. Ulrich's issue nicely shows how tricky this particular gochya can be. On the surface, the problem is squarely the fault of MDS but underneath MDS is, in fact, innocent. To summarize the problem in a simpler testcase than Ulrich's example, here's a simple fragment of code: <af:forEach var="item" items="#{itemList.items}" varStatus="vs"> <af:commandLink id="cl1" text="#{item.label}" action="#{item.doAction}"  partialSubmit="true"/></af:forEach> Looks innocent enough right? We see a bunch of links printed out, great. The issue here though is the id attribute. Logically you can kind of see the problem. The forEach loop is creating (presumably) multiple instances of the commandLink, but only one id is specified - cl1. We know that IDs have to be unique within a JSF component tree, so that must be a bad thing?  The problem is that JSF under JSP implements some hacks when the component tree is generated to transparently fix this problem for you. Behind the scenes it ensures that each instance really does have a unique id. Really nice of it to do so, thank you very much. However, (you could see this coming), the same is not true when running with Facelets  (this is under 11.1.2.n)  in that case, what you put for the id is what you get, and JSF does not mess around in the background for you. So you end up with a component tree that contains duplicate ids which are only created at runtime.  So subtle chaos can ensue.  The symptoms are wide and varied, from something pretty obscure such as the combination Ulrich uncovered, to something as frustrating as your ActionListener just not being triggered. And yes I've wasted hours on just such an issue.  The Solution  Once you're aware of this one it's really simple to fix it, there are two options: Remove the id attribute on components that will cause some kind of submission within the forEach loop altogether and let JSF do the right thing in generating them. Then you'll be assured of uniqueness. Use the var attribute of the loop to generate a unique id for each child instance.  for example in the above case: <af:commandLink id="cl1_${vs.index}" ... />.  So one to watch out for in your upgrades to JSF 2 and one perhaps, for your coding standards today to prepare you for. For completeness, here's the reference to the underlying JSF issue that's at the heart of this: JAVASERVERFACES-1527

An issue that I've encountered before and saw again today seems worthy of a little write-up. It's all to do with a subtle yet highly important difference in behaviour between JSF 2 running with JSP...

ADF Controller / TaskFlows

Facelets and PanelDashboard Gotchya

An issue that came to light via the ADF Expert Methodology Group last week seemed to be an interesting one to write about. Olga had logged an issue in the EMG Issue Tracker which seemed to imply that there was a difference in behaviour between JSP and Facelets when  using the <af:panelDashboard> component.  Specifically, the problem seemed to be that when you made changes to the ordering of the panels within the dashboard, under JSP the order would be remembered, but the same page and code under Facelets (ADF 11.1.2.n)  the change would be ignored. This naturally piqued my interest and the detective work began. Running the test-case that Olga had thankfully supplied and then that our own Chris Muir had further simplified,  the problem certainly reproduced, so it seemed to be real, however, reading the code there was a clue to what was going on.  Olga had sensibly adapted the panelDashboard sample from the ADF Demo WAR file and the code in question that was called when the relevant operation took place contained an interesting comment. Here it is: // Apply the change to the component tree immediately:// Note that the ChangeManager.addComponentChange() is required here if using Facelets because the Facelets view// handler will discard the change in order when the next render phase is started.ComponentChange change = new ReorderChildrenComponentChange(reorderedIdList);RequestContext rc = RequestContext.getCurrentInstance();rc.getChangeManager().addComponentChange(FacesContext.getCurrentInstance(), dashboard, change);change.changeComponent(dashboard);... So there was an admission here that something slightly different was going on in the world of Facelets.  Furthermore, reading the tagdoc on panelDashboard gives a bit more information and a further clue: You may wish to use org.apache.myfaces.trinidad.change.ReorderChildrenComponentChange and ChangeManager().addComponentChange() if you wish to preserve a new ordering of the children. Ideally, you should use an MDS ChangeManager to persist the change longer than the user's session so that the use does not have to repeatedly make the same reorder gesture every time your application is used.  ChangeManager is the magic word here. Back to the testcase, and this time I ran it in debug with the specific aim of inspecting the change Manager instance returned by the  rc.getChangeManager() call above. Sure enough, there was the problem. In the testcase, the ChangeManager was an instance of org.apach.myfaces.trinidad.change.NullChangeManager. If you have a look at the source code for that you'll see that all the operations are No-Ops, so it's not surprising that the change was not persisted.  So the solution was then obvious, in the project properties, in the ADF View panel, check the Enable User Customizations box to configure a Change Manager (either Session or MDS) that actually does something and the problem is resolved.  The morals of this story are to read the doc and do not be afraid of debugging code. It will really help, of course, if you make sure you have the ADF Source Code installed (just ask Oracle Support). You can save a lot of time, frustration and needless SRs.

An issue that came to light via the ADF Expert Methodology Group last week seemed to be an interesting one to write about. Olga had logged an issue in the EMG Issue Tracker which seemed to imply that...

ADF Faces and UI

The ImageMap Pattern

In my last article, I alluded to the fact that the associated sample combined a bunch of existing patterns and techniques, and that I would progressively write those up.  In this article I'm going to talk about the first of these, the ImageMap pattern. What's the Use Case?  This pattern is all about solving a pretty common problem, I have, in my service model, some kind of codified value (e.g. a Type or a Status) which I want to reflect visually in my UI using an image. Now if you only have a couple of options to represent then you can use a simple ternary expression in the page, switching based on the value you're getting from the service.  However, once you get over three or four options the EL starts to get hard to read and maintain, and face it, sometimes you might not even notice that it's evaluating to the wrong thing if the expression is wrong.  So what are the options for approaching this?  Do the translation in the service layer and provide an attribute containing the correct image to display.  Manage some simple lookup into a shared UI level resource Option (1) just feels wrong because you'd be letting client side information, the names of image files in this case,  leak into the wrong layer, so the shared resource approach really looks like the way to go.  Implementation The approach that we take in this pattern is to exploit the ability of Expression Language to be able to refer to both arrays and maps using the "[<value>]" syntax. For example the expression mybean.image[1] can actually mean several things depending on what "image" is in this case. If the getImage() method in the underlying mybean returns a List then this would translate to pull out index 1 from that list. If on the other hand getImage() returns a Map then the get() method will be called on the map with a key of (in this case) "1". We can exploit this behavior, and particularly the understanding of the Map expressions to define a mapping between a piece of data from the model, such as a status code, and a particular image to use to represent that. To illustrate this let's take a simple example where we have some possible string status values in the datamodel and want to map that into different images, thus: Code from the Service Image To Use  TABLE  /images/table.png  VIEW  /images/view.png FUNCTION  /images/plsql_func.png  ...  .. Notice that the names of the images are not quite the same as the codification from the service layer so we can't get away with the simplier solution of: <af:image source="/images/#{bindings.ObjectType}.png" .../>  So instead, we have to work via an abstraction using a lookup map for the images  Step 1: Define your image map We can define the lookup map to work from either as an explicit managed bean, or even more easily as a stand-alone bean definition in the adfc-config.xml file. Conventionally we will store this bean on the application scope so that all users on the system share the same copy: <managed-bean>   <managed-bean-name>typeImages</managed-bean-name>   <managed-bean-class>java.util.HashMap</managed-bean-class>   <managed-bean-scope>application</managed-bean-scope>   <map-entries>     <map-entry>       <key>TABLE</key>       <value>/images/table.png</value>     </map-entry>     <map-entry>       <key>VIEW</key>       <value>/images/view.png</value>     </map-entry>     <map-entry>       <key>FUNCTION</key>       <value>/images/pls_func.png</value>     </map-entry>     ...    </map-entries></managed-bean>   Alternatively if the thing we wanted to key off was a simple numerical list then we could have a definition that used a simple array rather than a map; like this: <managed-bean>  <managed-bean-name>lifecycleImages</managed-bean-name>  <managed-bean-class>java.util.ArrayList</managed-bean-class>  <managed-bean-scope>application</managed-bean-scope>  <list-entries>    <value-class>java.lang.String</value-class>    <value>/images/new.png</value>    <value>/images/updated.png</value>    <value>/images/sclosed.png</value>  </list-entries></managed-bean>   In this latter case index lifecycleImages[0] would map to /images/new.png, lifecycleImages[1] to /images/updated.png etc. Step 2: using this bean in EL Now that the list or map has been defined we can use it thus: <af:image source="#{typeImages[bindings.ObjectType]}" Where the bindings.ObjectType attribute binding can be expected to turn one of the valid keys in the map (TABLE,VIEW etc.)  You can see an example of this version of the pattern inside the tile iterator in the home.jspx page in the sample: DRM004 - AutoReduce and Pagination screen Variations on the Theme  I'm always thinking about how to optimize performance, and one useful approach when it comes to images is to use the technique of using image sprites. This is where, instead of having lots of discrete images, you have a single image file, a little like a film-strip, containing all of the images. In this case, CSS is used to assign the filmstrip image as a background to a page element and then the CSS background-position is set to select a particular icon on the strip. This has the advantage of only needing a single round trip to grab all the images at once, having a positive effect on your page load time.  Using this idea we can take the Image Map Pattern approach, but rather than having the map entry value be the name of a discrete image, it can point to the name of the CSS style. This style can be applied in the styleClass attribute of an element to pull the required image from the film-strip. To save you having to create a bunch of extra styles to encode the positions, you could also just hold an offset in the film-strip as the lookup value.  This latter approach can also be seen in the  DRM004 - AutoReduce and Pagination screen sample, have a look at the managed bean definition for typeImageOffsets. This information is then used to define the images in the list view of the home.jspx page, thus: <af:spacer styleClass="iconStripBase" inlineStyle="background-position:#{typeImageOffsets[row.ObjectType]}px;"/>   Have a look at the sample to see it all in action. 

In my last article, I alluded to the fact that the associated sample combined a bunch of existing patterns and techniques, and that I would progressively write those up.  In this article I'm going...

ADF Faces and UI

Auto-Reduce Search Sample

For a while now I've been playing with techniques in ADF applications which will produce a user experience that is more webby (if I can use that term) and less business application like.  Some of this work can be seen if you look back on my postings on animation. A recent challenge, in this vein, from one of the internal teams within Oracle, was to provide a search facility that would auto-reduce the results list in situe without the user having to press a button or link to trigger the search. Now hopefully you're familiar with the component behaviour <af:autoSuggestBehavior> that will provide a drop down list below a test input that revises as you type. For example: But that's not what I wanted here. In this case, I wanted the main search results to update as I typed - a feature you will find on certain popular search engines. As part of the process of putting this together, I found myself combining code and patterns from other prototypes that I've worked on and came to the conclusion that I could wrap all of this into a nice little demo application that actually shows several interesting techniques and patterns as well as the aforementioned auto-reduce. Here's the screen, it's a simple search against ALL_OBJECTS in the database, and the features of it that I thought were interesting.  The screen uses a fixed width centered display area, a fairly popular layout pattern for a lot of sites, including this blog. The images displayed by each row use a technique called the ImageMap Pattern to derive the correct image to display. I'll be talking about two variants on this pattern, the more interesting one of which using image sprites as a way to reduce your network traffic. Typing in the search field will (after a configurable delay) cause the query to be re-executed and a revised list displayed. We have a dynamic record count which shows the records shown out of the total.  The list view here has a smart pagination bar which allows the user access to the start and end of the list without printing out every option in between. You can change how many records are displayed and hence the size of the pagination. Finally you can switch between row and icon views. This latter function is interesting because it's carried out client side to minimize the switch time. The results of typing into the search screen would look something like this:  As you type, not only will the list reduce, but of course the pagination bar etc. will be updated to reflect the current result set size. The icon view mentioned in (7) looks like this: Over the next couple of weeks I'll be writing detailed articles on these various features, but if you can't wait to get started, you can download the sample from the ADF Samples project on Java.net: DRM004 - AutoReduce and Pagination screen

For a while now I've been playing with techniques in ADF applications which will produce a user experience that is more webby (if I can use that term) and less business application like.  Some of this...

ADF

New Sample Demonstrating the Traversing of Tree Bindings

A technique that I seem to use a fair amount, particularlyin the construction of dynamic UIs is the use of a ADF Tree Binding to encode amulti-level master-detail relationshipwhich is then expressed in the UI in some kind of looping form – usually aseries of nested af:iterators, rather than the conventional tree or treetable.This technique exploits two features of the treebinding. First the fact that antreebinding can return both a collectionModel as well as a treeModel, thiscollectionModel can be used directly by an iterator. Secondly that the “rows”returned by the collectionModel themselves contain an attribute called .children.This attribute in turn gives access to a collection of all the children of thatnode which can also be iterated over. Putting this together you can represent the data encodedinto a tree binding in all sorts of ways. As an example I’ve put together a very simple sample basedon the HT schema and uploaded it to the ADF Sample project. It produces thisUI: The important code is shown here for a Region -> Country -> Location Hierachy: <af:iterator id="i1" value="#{bindings.AllRegions.collectionModel}" var="rgn"> <af:showDetailHeader text="#{rgn.RegionName}" disclosed="true" id="sdh1"> <af:iterator id="i2" value="#{rgn.children}" var="cnty">     <af:showDetailHeader text="#{cnty.CountryName}" disclosed="true" id="sdh2">       <af:iterator id="i3" value="#{cnty.children}" var="loc">         <af:panelList id="pl1">         <af:outputText value="#{loc.City}" id="ot3"/>          </af:panelList>        </af:iterator>      </af:showDetailHeader>    </af:iterator>  </af:showDetailHeader></af:iterator>  You can download the entire sample from here:

A technique that I seem to use a fair amount, particularly in the construction of dynamic UIs is the use of a ADF Tree Binding to encode a multi-level master-detail relationshipwhich is then expressed...

ADF Faces and UI

Making Those PanelBoxes Behave

I have a little problem to solve earlier this week - misbehaving <af:panelBox> components... What do I mean by that? Well here's the scenario, I have a page fragment containing a set of panelBoxes arranged vertically. As it happens, they are stamped out in a loop but that does not really matter. What I want to be able to do is to provide the user with a simple UI to close and open all of the panelBoxes in concert. This could also apply to showDetailHeader and similar items with a disclosed attrubute, but in this case it's good old panelBoxes.  Ok, so the basic solution to this should be self evident. I can set up a suitable scoped managed bean that the panelBoxes all refer to for their disclosed attribute state. Then the open all / close commandButtons in the UI can simply set the state of that bean for all the panelBoxes to pick up via EL on their disclosed attribute. Sound OK? Well that works basically without a hitch, but turns out that there is a slight problem and this is where the framework is attempting to be a little too helpful. The issue is that is the user manually discloses or hides a panelBox then that will override the value that the EL is setting. So for example. I start the page with all panelBoxes collapsed, all set by the EL state I'm storing on the session I manually disclose panelBox no 1. I press the Expand All button - all works as you would hope and all the panelBoxes are now disclosed, including of course panelBox 1 which I just expanded manually. Finally I press the Collapse All button and everything collapses except that first panelBox that I manually disclosed.  The problem is that the component remembers this manual disclosure and that overrides the value provided by the expression. If I change the viewId (navigate away and back) then the panelBox will start to behave again, until of course I touch it again! Now, the more astute amoungst you would think (as I did) Ah, sound like the MDS personalizaton stuff is getting in the way and the solution should simply be to set the dontPersist attribute to disclosed | ALL. Alas this does not fix the issue.  After a little noodling on the best way to approach this I came up with a solution that works well, although if you think of an alternative way do let me know. The principle is simple. In the disclosureListener for the panelBox I take a note of the clientID of the panelBox component that has been touched by the user along with the state. This all gets stored in a Map of Booleans in ViewScope which is keyed by clientID and stores the current disclosed state in the Boolean value.  The listener looks like this (it's held in a request scope backing bean for the page): public void handlePBDisclosureEvent(DisclosureEvent disclosureEvent) { String clientId = disclosureEvent.getComponent().getClientId(FacesContext.getCurrentInstance()); boolean state = disclosureEvent.isExpanded(); pbState.addTouchedPanelBox(clientId, state);} The pbState variable referenced here is a reference to the bean which will hold the state of the panelBoxes that lives in viewScope (recall that everything is re-set when the viewid is changed so keeping this in viewScope is just fine and cleans things up automatically). The addTouchedPanelBox() method looks like this: public void addTouchedPanelBox(String clientId, boolean state) { //create the cache if needed this is just a Map<String,Boolean> if (_touchedPanelBoxState == null) { _touchedPanelBoxState = new HashMap<String, Boolean>(); } // Simply put / replace _touchedPanelBoxState.put(clientId, state);} So that's the first part, we now have a record of every panelBox that the user has touched. So what do we do when the Collapse All or Expand All buttons are pressed? Here we do some JavaScript magic. Basically for each clientID that we have stored away, we issue a client side disclosure event from JavaScript - just as if the user had gone back and changed it manually. So here's the Collapse All button action: public String CloseAllAction() { submitDiscloseOverride(pbState.getTouchedClientIds(true), false); _uiManager.closeAllBoxes(); return null;}  The _uiManager.closeAllBoxes() method is just manipulating the master-state that all of the panelBoxes are bound to using EL. The interesting bit though is the line:  submitDiscloseOverride(pbState.getTouchedClientIds(true), false); To break that down, the first part is a call to that viewScoped state holder to ask for a list of clientIDs that need to be "tweaked": public String getTouchedClientIds(boolean targetState) { StringBuilder sb = new StringBuilder(); if (_touchedPanelBoxState != null && _touchedPanelBoxState.size() > 0) { for (Map.Entry<String, Boolean> entry : _touchedPanelBoxState.entrySet()) { if (entry.getValue() == targetState) { if (sb.length() > 0) { sb.append(','); } sb.append(entry.getKey()); } } } return sb.toString();} You'll notice that this method only processes those panelBoxes that will be in the wrong state and returns those as a comma separated list. This is then processed by the submitDiscloseOverride() method: private void submitDiscloseOverride(String clientIdList, boolean targetDisclosureState) { if (clientIdList != null && clientIdList.length() > 0) { FacesContext fctx = FacesContext.getCurrentInstance(); StringBuilder script = new StringBuilder(); script.append("overrideDiscloseHandler('"); script.append(clientIdList); script.append("',"); script.append(targetDisclosureState); script.append(");"); Service.getRenderKitService(fctx, ExtendedRenderKitService.class).addScript(fctx, script.toString()); }} This method constructs a JavaScript command to call a routine called overrideDiscloseHandler() in a script attached to the page (using the standard <af:resource> tag). That method parses out the list of clientIDs and sends the correct message to each one: function overrideDiscloseHandler(clientIdList, newState) { AdfLogger.LOGGER.logMessage(AdfLogger.INFO, "Disclosure Hander newState " + newState + " Called with: " + clientIdList); //Parse out the list of clientIds var clientIdArray = clientIdList.split(','); for (var i = 0; i < clientIdArray.length; i++){ var panelBox = flipPanel = AdfPage.PAGE.findComponentByAbsoluteId(clientIdArray[i]); if (panelBox.getComponentType() == "oracle.adf.RichPanelBox"){ panelBox.broadcast(new AdfDisclosureEvent(panelBox, newState)); } } }  So there you go. You can see how, with a few tweaks the same code could be used for other components with disclosure that might suffer from the same problem, although I'd point out that the behavior I'm working around here us usually desirable.You can download the running example (11.1.2.2) from here. 

I have a little problem to solve earlier this week - misbehaving <af:panelBox> components... What do I mean by that? Well here's the scenario, I have a page fragment containing a set of panelBoxes...

JDeveloper

Setting Up Embedded WLS for MySQL

For a while, on and off,  I've been playing with MySQL in various applications, to the extent that it made sense to work out how to specifically configure the domain so that the MySQL driver would always be available. The advice in the great googleblogosphere seems to be to drop the jar file in the DefaultDomain/lib directory and all will be well. But although you can then see the jar being loaded as WLS starts up, it certainly wasn't working for some of my pre-loading services within the container which could still not find the driver. (Although I'm not saying that this technique would not be OK for an ADF application that you deploy that uses MySQL)   In the end I thought that the simplest thing was to work out what we do with the Oracle driver and emulate that. Sure enough it's there in the /DefaultDomain/bin/setDomainEnv script (.cmd or .sh).  You'll find it in there in the PRE_CLASSPATH section. So my solution was to simply add the driver reference there (code below reformatted for clarity): if NOT "%PRE_CLASSPATH%"=="" ( set PRE_CLASSPATH=%COMMON_COMPONENTS_HOME%\modules\oracle.jdbc_11.1.1\ojdbc6dms.jar; d:\shared\mysql\mysql-connector-java-5.1.18-bin.jar;%PRE_CLASSPATH%) else ( set PRE_CLASSPATH=%COMMON_COMPONENTS_HOME%\modules\oracle.jdbc_11.1.1\ojdbc6dms.jar; d:\shared\mysql\mysql-connector-java-5.1.18-bin.jar) And that's certainly done the trick for me.  So I think I can guarantee that at least one of the two methods here will work for you... At some point I'll put together a proper MySQL Extension for JDev that creates a library, sets this up, and registers a custom type-map for ADFBC, but alas time is always at a premium... 

For a while, on and off,  I've been playing with MySQL in various applications, to the extent that it made sense to work out how to specifically configure the domain so that the MySQL driver would...

ADF Faces and UI

Placeholder Watermarks with ADF 11.1.2

I'm sure you're all familiar with the concept of watermarking an input field to provide the user with a greyed out hint as to what to do with it.  This is often used in search boxes or UIs where space is at a premium and you really don't have room for a label. Here's a small screenshot that shows what I mean: As you can see,  both the filter field and multi-line field have such text.  As soon as the user starts to enter values in these fields the watermark will disappear only to reappear if the user clears out the field.  In the past, there have been various JavaScript based solutions to this, but the HTML5 spec introduces a common way of doing this using an attribute on the <input> element called placeholder. Alas, only Chrome and FireFox have implemented this in their later versions, although it's on the list for IE 10.  Now I probably won't be giving too much away if I let slip that placeholder support might possibly be standard in a future version of ADF Faces, but for now, I'm working in 11.1.2.2, so here's a simple implementation in the form of a custom JSF clientBehavior that will do it.  For this, I actually took inspiration from a recent blog posting from Donatas Valys: Set Initial Focus component for Oracle ADF Faces.  He hit upon the smart idea of using a client behavior to mark a particular component as having initial focus, I've used essentially the same technique here, although extended a little bit because of the nature of the job I'm doing. Create your Tag Library So the first step will to create the tag (it will be called <afg:setWatermarkBehavior>) in your project.  Just select New > Web Tier > JSF/Facelets > Facelets Tag Library.  On the first page of the creation wizard, choose Deployable or Project Based, the choice is yours. For convenience I chose Project Based, then on Step 2 provide a file name and a namespace. I used adfglitz.taglib.xml and http://xmlns.oracle.com/adf/faces/glitz respectively, choose suitable values for your implementation. This step will do everything to register the Tag Library with the project (you'll see an entry is added to web.xml)  Define the Behavior Definition  Now you can edit the tag file and add the new behavior (or as I would have it "behaviour"). The taglib editor provides an overview view to make this simple: The important things to note here are: The namespace (http://xmlns.oracle.com/adf/faces/glitz), we'll need that when adding this tag to the page.  The name of the behavior tag - setWatermarkBehavior The ID of the behavior tag - oracle.demo.adfglitz.watermark - I'll use this to associate an implementation class with the tag The attributes.  Note that I've defined one attribute for the tag called value. I'll use this to pass the actual text that needs to be displayed in the placeholder. You can switch to the source view of the editor and provide more information such as a friendly description of the taglib and tag, but you don't actually need to.  Implement the Behavior  Next we need to actually create a class that provides the implementation of the behavior. This needs to extend javax.faces.component.behavior.ClientBehaviorBase and implement javax.faces.component.StateHolder. The latter interface implementation is to ensure that the String passed in as the value of the tag is persisted and will survive re-builds of the component tree.  The basic class definition therefore looks like this:  @FacesBehavior("oracle.demo.adfglitz.watermark")public class SetWatermarkBehavior extends ClientBehaviorBase implements StateHolder {...} Note that I use the FacesBehavior annotation  to do the wiring between this implementation class and the taglib using the ID attribute defined above. The other thing we need to implement the tag contract is the "value" that must be passed in as a  required attribute for the tag.  This is done with a simple member variable (String value;) and an associated public getter and setter pair on the class - getValue(), setValue() - standard stuff. We also have to manage the storage of this value by implementing the StateHolder interface. The code for that is not very interesting so I'll not reproduce it here, you can see it in the complete java class though. The core method within the behavoir class is the getScript() method. This is called to encode the JavaScript  to send down with the enclosing component, however, we're going to subvert it a little - let me explain why.  If you have a clientBehavior associated with an inputItem then any script that you return from the getScript() method will be associated with a value change listener on the component.  In this case, that's not what we want, rather than applying the watermark when the value of the input changes, we want to apply it at the point in time the component is rendered. So to achieve this we actually just use and abuse the getScript() call and use the Trinidad ExtendedRenderKitService to queue up execute the JavaScript we need in a just in timely way. Here's the implementation of the method: //Constants used by getScript() defined at class levelprivate static final String SCRIPT_PREFIX = "addWatermarkBehavior(\"";private static final String SCRIPT_ARG_SEPARATOR = "\",\""; private static final String SCRIPT_SUFFIX = "\");";  @Overridepublic String getScript(ClientBehaviorContext ctx) {  UIComponent component = ctx.getComponent();  //only contiune if the component is currently rendered  if (component.isRendered()) {    String componentType = deduceDOMElementType(component);   //Only continue if the component is a valid type    if (!componentType.equals(UNSUPPORTED_ELEMENT)) {      String wmText = (getValue() == null) ? EMPTY_DEFAULT : getValue();      StringBuilder script = new StringBuilder(SCRIPT_PREFIX);      script.append(ctx.getSourceId());    script.append(SCRIPT_ARG_SEPARATOR);      script.append(componentType);      script.append(SCRIPT_ARG_SEPARATOR);      script.append(wmText);      script.append(SCRIPT_SUFFIX);    //We don't have an init event, just valueChange so push the code this way      FacesContext fctx = ctx.getFacesContext();      ExtendedRenderKitService extendedRenderKitService =              Service.getRenderKitService(fctx, ExtendedRenderKitService.class);      extendedRenderKitService.addScript(fctx, script.toString());    }  } //And return nothing as we don't need a valuechangeListener  return "";} Things to note here.  We could of course encode the entire JavaScript  function within the script string generated above. However, given that in my case, I have several uses of the behavior in the app it makes sense to shove the detail of that code into a common .js file. I already have this available on the page and call a simple function - addWatermarkBehavior(), passing the relevant component ID, type and placeholder value.  That JavaScript can be seen below. Another point is that getScript() uses the convenience method deduceDOMElementType() which, from the component and its attributes works out: First of all if it's a valid component on which to do anything, and secondly if the placeholder will need to be set on an html <input> element or an <textarea>. //Constants used by deduceDOMElementType() defined at class levelprivate static final String UNSUPPORTED_ELEMENT = "unsupported";private static final String TEXTAREA_ELEMENT = "textarea";private static final String INPUT_ELEMENT = "input";private String deduceDOMElementType(UIComponent component) { String componentType = UNSUPPORTED_ELEMENT;  //work out the correct component type  if (component instanceof RichInputText) {    //In this case we may have a multi-line item but assume intially that this is not the case    componentType = INPUT_ELEMENT;    //Now check for the rows attribute to see if this is multi-line    Map<String, Object> compAttr = component.getAttributes();    if (compAttr.containsKey("rows")) {      int rows = (Integer)compAttr.get("rows");      if (rows > 1) {        componentType = TEXTAREA_ELEMENT;      }    }  } else if (component instanceof RichInputDate || component instanceof RichInputListOfValues ||             component instanceof RichInputComboboxListOfValues) {   //These all resolve to inputs at the DOM level   componentType = INPUT_ELEMENT;  }  return componentType;} The JavaScript  As I mentioned above, rather than stream down reams of script for each component I have a standard JavaScript file attached to my page using the <af:resource> tag and in that I've implemented the simple function to locate the correct component on the page and apply the correct placeholder text. You could also use this method as a place to add a script based solution to browsers that don't support placeholder. Here's the  function: function addWatermarkBehavior(componentId, type, text){    var sourceInput = AdfPage.PAGE.findComponent(componentId);    var domElemement = AdfAgent.AGENT.getElementById(sourceInput.getClientId());    var targetArray = domElemement.getElementsByTagName(type);    targetArray[0].placeholder = text;} As you can see, pretty short and sweet, you could of course add various validations to check you have a real element  etc. but let's keep it simple. Using the Behavior So that's about it. The final point is, of course how to use this. Well all you need to do is register the namespace in your page or fragment as I've done here using the afg: prefix: <ui:composition xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:af="http://xmlns.oracle.com/adf/faces/rich"                xmlns:afg="http://xmlns.oracle.com/adf/faces/glitz"                xmlns:f="http://java.sun.com/jsf/core">  And then use the tag thus: <af:inputText ...> <afg:setWatermarkBehaviour value="Filter Items"/> </af:inputText>   Enjoy.

I'm sure you're all familiar with the concept of watermarking an input field to provide the user with a greyed out hint as to what to do with it.  This is often used in search boxes or UIs where space...

ADF Faces and UI

Using inputNumberSlider for Dates

I'm currently working on a prototype User Interface for an internal project that surfaced a requirement for allowing date selection using a slider control.  ADF Faces itself only supports two forms of slider control (<af:inputNumberSlider> and <af:inputRangeSlider>) , so what to do? Well putting aside for one moment the aesthetic and usability of using a slider for date selection ( not something I wholly buy into myself), can it be done?  The simple answer is (of course and hence the article) yes. Is it a Date? Is it a Number?  Fortunately it's both. Java dates are stored internally as longs so there is no fundamental issue with using the inputNumberSlider to select one, providing that we get the precision right - milliseconds are probably not that useful as an increment. However, if we try and base a inputNumberSlider on the millisecond value of a date, the main problem is going to be the labels - in fact here's what it might look like: So how do we  use this component but convert the labels to something sensible such as dates in the format "MM/dd", ending up with this: Well to achieve that we need a custom converter which can be assigned to the converter property of the component thus: <af:inputNumberSlider label="Pick a day" id="ins1"   minimum="#{uiManager.dateRangeSliderStartDate}"    maximum="#{uiManager.dateRangeSliderEndDate}"  majorIncrement="#{uiManager.dateRangeSlider30DayIncrement}"    minorIncrement="#{uiManager.dateRangeSlider1DayIncrement}"    value="#{uiManager.pickedDateAsLong}"    converter="SliderDateConverter"     contentStyle="width:50em;"/>  Defining The Converter  Before I proceed here, credit has to go to my good buddy Matthias Wessendorf who's code from this article I have freely adapted here. To define the converter, there are three steps: Write a server side converter in Java.  Write a client-side converter in JavaScript Register the converter with Faces  The Server Side Converter Class The server side converter is called by the framework as it initially renders the component on the page. It will call into this class several times to generate the major tick labels and of course the label for the slider value.  The converter class needs to implement two interfaces; org.apache.myfaces.trinidad.convert.ClientConverter and javax.faces.convert.Converter. In this case I've only had to implement four methods, two of which relate to the wiring up of the client JavaScript to the converter and the others manage the conversion itself. Let's look at those latter two first.  Converters in JSF handle the basic problem of taking a value Object  and converting it into a String form that can be sent down to the browser in HTML and then the reverse of that cam task of taking the String value that gets sent up on the request and converting that back into the Object value form.  So in this case we're attempting to convert a Long object (for convenience I'm actually storing the value as a long and then providing a typed getter to provide the actual date value when it's asked for). The conversion will be something like this: 1335135600000 --> "04/24" So this paired conversion is handled by two methods called getAsString() and getAsObject() and the implementations are pretty simple - just a bit of string parsing and date arithmetic / formatting. I'm using the org.apache.commons.lang.time.DateFormatUtils helper class as well: public String getAsString(FacesContext facesContext, UIComponent uIComponent, Object valueAsObject) {  long selectedValue =  ((Double)valueAsObject).longValue();  return DateFormatUtils.format(selectedValue, "MM/dd");} public Object getAsObject(FacesContext facesContext, UIComponent uIComponent, String valueAsString) { Calendar cal = new GregorianCalendar();  int currentMonth = cal.get(Calendar.MONTH); /* Zero based */  int currentYear = cal.get(Calendar.YEAR);          //Parse the supplied String assuming the format MM/dd in this case  String[] dateBits = valueAsString.split("[/]");  int month = Integer.parseInt(dateBits[0]) - 1;  int day = Integer.parseInt(dateBits[1]);  int year = currentYear; //Handle the situation where the span crosses a year boundary //In my specific use case the dates all work backwards from today  if (month > currentMonth){   year--;  }          //Reconstruct the actual date  Calendar selectedAsDateCal = new GregorianCalendar(year,month,day);  return selectedAsDateCal.getTimeInMillis();} So the only complexity in this case is in the case where the selected String value is something like "11/30" which, because the range of my slider extends into the past from the current date, has to be interpreted as 30th November 2011 not 30th November 2012. Of course if you are trying to create a slider that extends across multiple years you'll have to encode the year into the string as well - month and day alone will not give you enough information. The second two methods I need to implement wire up the JavaScript. The function getClientLibrarySource() tells the framework what .js file the client converter is in and  getClientConversion() defines the name of the converter function: public String getClientLibrarySource(FacesContext facesContext) {  return facesContext.getExternalContext().getRequestContextPath() +                           "/resources/js/sliderDateConverter.js";   }public String getClientConversion(FacesContext facesContext, UIComponent uIComponent) {  return ("new SliderDateReformatter()");}  The Client Side Converter   As specified above, the client converter is defined in a file called sliderDateConverter.js in my PUBLIC_HTML/resources/js directory. This converter is called as the use moves the slider around, so unlike the server side code which is used to format the labels as well, this is really just used to format the label on the selector and it's value tooltip.  The underlying logic is essentially identical to the Java version just converted to JavaScript. Again it's just a matter of methods to convert from Object to String and back. You'll note here as well, that the prototype of the SliderDateReformatter  is set to TrConverter, this is the equivalent, to implementing the Converter interface in Java terms. function SliderDateReformatter(){   }SliderDateReformatter.prototype = new TrConverter();SliderDateReformatter.prototype.getFormatHint = function(){return null;}SliderDateReformatter.prototype.getAsString = function(dateMillis,label) {var asDate  = new Date(dateMillis);        var month = asDate.getMonth()+1; /* Again zero based */        var day = asDate.getDate();return month + "/" + day;}SliderDateReformatter.prototype.getAsObject = function(dateString,label){        var dateNow = new Date();        var currentYear = dateNow.getFullYear();        var currentMonth = dateNow.getMonth();        var dateBits = dateString.split("/");        var selectedMonth = (dateBits[0]) - 1;        var selectedDay = dateBits[1];        var selectedYear = currentYear;                if (selectedMonth > currentMonth){            selectedYear--;        }        var representedDate = new Date(selectedYear,selectedMonth,selectedDay);return representedDate.getTime();}  Register the Converter  The final step is to register the converter by name in the faces-config.xml file. This allows the framework to match the reference converter="SliderDateConverter" made by the component with the actual converter class. Just edit the faces-config and set this in the Overview editor Converters page, or add it directly to the XML, thus: <faces-config version="2.1" xmlns="http://java.sun.com/xml/ns/javaee">  <application>    <default-render-kit-id>oracle.adf.rich</default-render-kit-id>  </application> ...  <converter>    <converter-id>SliderDateConverter</converter-id>    <converter-class>oracle.demo.view.slider.SliderDateConverter</converter-class>  </converter></faces-config>  Wrap Up So as we've seen it's not too difficult to use the inputNumberSlider to represent data that, at first glance, is not numerical.  The same technique can be used to control the tick labelling of the component, even when you are dealing with "real" numbers, for example you might want to define a slider that allows the user to pick a percentage from the range 1%-100% and map that onto an underlying value of 0.01 to 1. You'd use exactly the same technique to do so if you were writing things from scratch, however, that one's already handled for you! Just embed a <af:convertNumber type="percent"/> as a child of the component.We can also use the same technique for <af:inputRangeSlider> as well.

I'm currently working on a prototype User Interface for an internal project that surfaced a requirement for allowing date selection using a slider control.  ADF Faces itself only supports two forms of...

ADF Faces and UI

Skinning af:selectOneChoice

A question came in today about how to skin the selection button ()  of an <af:selectOneChoice>. If you have a delve in the ADF Skinning editor, you'll find that there are selectors for the selectOneChoice when in compact mode (af|selectOneChoice::compact-dropdown-icon-style), however, there is not a selector for the icon in the "normal" mode. I had a quick delve into the skinning source files that you can find in the adf-richclient-impl-11.jar and likewise there seemed to be no association there. However, a quick sample page and a peek with Chrome developer tools revealed the problem.  The af:selectOneChoice gets rendered in the browser as a good old <select> element (reasonable enough!). Herein lies the problem, and the reason why there is no skin selector. The <select> HTML element does not have a standard way of replacing the image used for the dropdown button.  If you have a search around with your favorite search engine, you can find various workarounds and solutions for this.  For example, using Chrome and Safari you can define the following for the select element:select {  -webkit-appearance: listbox;  background-image: url(blob.png);   background-position: center right;  background-repeat: no-repeat;  }Which gives a very exciting select box:  .

A question came in today about how to skin the selection button ()  of an <af:selectOneChoice>. If you have a delve in the ADF Skinning editor, you'll find that there are selectors for...

ADF Faces and UI

More Animation - Self Dismissing Dialogs

In my earlier articles on animation, I discussed various slide, grow and  flip transitions for items and containers.  In this article I want to discuss a fade animation and specifically the use of fades and auto-dismissal for informational dialogs.  If you use a Mac, you may be familiar with Growl as a notification system, and the nice way that messages that are informational just fade out after a few seconds. So in this blog entry I wanted to discuss how we could make an ADF popup behave in the same way. This can be an effective way of communicating information to the user without "getting in the way" with modal alerts. This of course, has been done before, but everything I've seen previously requires something like JQuery to be in the mix when we don't really need it to be.  The solution I've put together is nice and generic and will work with either <af:panelWindow> or <af:dialog> as a the child of the popup. In terms of usage it's pretty simple to use we  just need to ensure that the popup itself has clientComponent is set to true and includes the animation JavaScript (animateFadingPopup) on a popupOpened event: <af:popup id="pop1" clientComponent="true">  <af:panelWindow title="A Fading Message...">   ... </af:panelWindow>  <af:clientListener method="animateFadingPopup" type="popupOpened"/></af:popup>   The popup can be invoked in the normal way using showPopupBehavior or JavaScript, no special code is required there. As a further twist you can include an additional clientAttribute called preFadeDelay to define a delay before the fade itself starts (the default is 5 seconds) . To set the delay to just 2 seconds for example: <af:popup ...>  ...  <af:clientAttribute name="preFadeDelay" value="2"/>  <af:clientListener method="animateFadingPopup" type="popupOpened"/> </af:popup> The Animation Styles  As before, we have a couple of CSS Styles which define the animation, I've put these into the skin in my case, and, as in the other articles, I've only defined the transitions for WebKit browsers (Chrome, Safari) at the moment. In this case, the fade is timed at 5 seconds in duration. .popupFadeReset {  opacity: 1;}.popupFadeAnimate {  opacity: 0;  -webkit-transition: opacity 5s ease-in-out;} As you can see here, we are achieving the fade by simply setting the CSS opacity property. The JavaScript The final part of the puzzle is, of course, the JavaScript, there are four functions, these are generic (apart from the Style names which, if you've changed above, you'll need to reflect here): The initial function invoked from the popupOpened event,  animateFadingPopup which starts a timer and provides the initial delay before we start to fade the popup. The function that applies the fade animation to the popup - initiatePopupFade. The callback function - closeFadedPopup used to reset the style class and correctly hide the popup so that it can be invoked again and again.   A utility function - findFadeContainer, which is responsible for locating the correct child component of the popup to actually apply the style to. Function - animateFadingPopup This function, as stated is the one hooked up to the popupOpened event via a clientListener. Because of when the code is called it does not actually matter how you launch the popup, or if the popup is re-used from multiple places. All usages will get the fade behavior. /** * Client listener which will kick off the animation to fade the dialog and register * a callback to correctly reset the popup once the animation is complete * @param event */function animateFadingPopup(event) { var fadePopup = event.getSource();  var fadeCandidate = false;  //Ensure that the popup is initially Opaque  //This handles the situation where the user has dismissed  //the popup whilst it was in the process of fading  var fadeContainer = findFadeContainer(fadePopup);  if (fadeContainer != null) {    fadeCandidate = true;    fadeContainer.setStyleClass("popupFadeReset");  }  //Only continue if we can actually fade this popup  if (fadeCandidate) {  //See if a delay has been specified    var waitTimeSeconds = event.getSource().getProperty('preFadeDelay');    //Default to 5 seconds if not supplied    if (waitTimeSeconds == undefined) {    waitTimeSeconds = 5;    }    // Now call the fade after the specified time    var fadeFunction = function () {    initiatePopupFade(fadePopup);    };    var fadeDelayTimer = setTimeout(fadeFunction, (waitTimeSeconds * 1000));  }} The things to note about this function is the initial check that we have to do to ensure that the container is currently visible and reset it's style to ensure that it is.  This is to handle the situation where the popup has begun the fade, and yet the user has still explicitly dismissed the popup before it's complete and in doing so has prevented the callback function (described later) from executing. In this particular situation the initial display of the dialog will be (apparently) missing it's normal animation but at least it becomes visible to the user (and most users will probably not notice this difference in any case). You'll notice that the style that we apply to reset the  opacity - popupFadeReset, is not applied to the popup component itself but rather the dialog or panelWindow within it. More about that in the description of the next function findFadeContainer(). Finally, assuming that we have a suitable candidate for fading, a JavaScript  timer is started using the specified preFadeDelay wait time (or 5 seconds if that was not supplied). When this timer expires then the main animation styleclass will be applied using the initiatePopupFade() function Function - findFadeContainer As a component, the <af:popup> does not support styleClass attribute, so we can't apply the animation style directly.  Instead we have to look for the container within the popup which defines the window object that can have a style attached.  This is achieved by the following code: /** * The thing we actually fade will be the only child * of the popup assuming that this is a dialog or window * @param popup * @return the component, or null if this is not valid for fading */function findFadeContainer(popup) { var children = popup.getDescendantComponents();  var fadeContainer = children[0];  if (fadeContainer != undefined) {  var compType = fadeContainer.getComponentType();    if (compType == "oracle.adf.RichPanelWindow" || compType == "oracle.adf.RichDialog") {    return fadeContainer;    }  }  return null;}  So what we do here is to grab the first child component of the popup and check its type. Here I decided to limit the fade behaviour to only <af:dialog> and <af:panelWindow>. This was deliberate.  If  we apply the fade to say an <af:noteWindow> you would see the text inside the balloon fade, but the balloon itself would hang around until the fade animation was over and then hide.  It would of course be possible to make the code smarter to walk up the DOM tree to find the correct <div> to apply the style to in order to hide the whole balloon, however, that means that this JavaScript would then need to have knowledge of the generated DOM structure, something which may change from release to release, and certainly something to avoid. So, all in all, I think that this is an OK restriction and frankly it's windows and dialogs that I wanted to fade anyway, not balloons and menus. You could of course extend this technique and handle the other types should you really want to. One thing to note here is the selection of the first (children[0]) child of the popup. It does not matter if there are non-visible children such as clientListener before the <af:dialog> or <af:panelWindow> within the popup, they are not included in this array, so picking the first element in this way seems to be fine, no matter what the underlying ordering is within the JSF source.  If you wanted a super-robust version of the code you might want to iterate through the children array of the popup to check for the right type, again it's up to you.  Function -  initiatePopupFade  On to the actual fading. This is actually very simple and at it's heart, just the application of the popupFadeAnimate style to the correct component and then registering a callback to execute once the fade is done. /** * Function which will kick off the animation to fade the dialog and register * a callback to correctly reset the popup once the animation is complete * @param popup the popup we are animating */function initiatePopupFade(popup) { //Only continue if the popup has not already been dismissed   if (popup.isPopupVisible()) {  //The skin styles that define the animation     var fadeoutAnimationStyle = "popupFadeAnimate";    var fadeAnimationResetStyle = "popupFadeReset";    var fadeContainer = findFadeContainer(popup);    if (fadeContainer != null) {    var fadeContainerReal = AdfAgent.AGENT.getElementById(fadeContainer.getClientId());      //Define the callback this will correctly reset the popup once it's disappeared      var fadeCallbackFunction = function (event) {      closeFadedPopup(popup, fadeContainer, fadeAnimationResetStyle);        event.target.removeEventListener("webkitTransitionEnd", fadeCallbackFunction);      };      //Initiate the fade      fadeContainer.setStyleClass(fadeoutAnimationStyle);      //Register the callback to execute once fade is done      fadeContainerReal.addEventListener("webkitTransitionEnd", fadeCallbackFunction, false);    }  }} I've added some extra checks here though. First of all we only start the whole process if the popup is still visible. It may be that the user has closed the popup before the delay timer has finished so there is no need to start animating in that case. Again we use the findFadeContainer() function to locate the correct component to apply the style to, and additionally we grab the DOM id that represents that container.  This physical ID is required for the registration of the callback function. The closeFadedPopup() call is then registered on the callback so as to correctly close the now transparent (but still there) popup. Function -  closeFadedPopup The final function just cleans things up: /** * Callback function to correctly cancel and reset the style in the popup * @param popup id of the popup so we can close it properly * @param contatiner the window / dialog within the popup to actually style * @param resetStyle the syle that sets the opacity back to solid */function closeFadedPopup(popup, container, resetStyle) { container.setStyleClass(resetStyle);  popup.cancel();}  First of all we reset the style to make the popup contents opaque again and then we cancel the popup.  This will ensure that any of your user code that is waiting for a popup cancelled event will actually get the event, additionally if you have done this as a modal window / dialog it will ensure that the glasspane is dismissed and you can interact with the UI again.  What's Next? There are several ways in which this technique could be used, I've been working on a popup here, but you could apply the same approach to in-line messages. As this code (in the popup case) is generic it will make s pretty nice declarative component and maybe, if I get time, I'll look at constructing a formal Growl component using a combination of this technique, and active data push. Also, I'm sure the above code can be improved a little too.  Specifically things like registering a popup cancelled listener to handle the style reset so that we don't loose the subtle animation that takes place when the popup is opened in that situation where the user has closed the in-fade dialog.

In my earlier articles on animation, I discussed various slide, grow and  flip transitions for items and containers.  In this article I want to discuss a fade animation and specifically the use of...

ADF

The UIManager Pattern

One of the most common mistakes that I see when reviewing ADF application code, is the sin of storing UI component references, most commonly things like table or tree components in Session or PageFlow scope. The reasons why this is bad are simple; firstly, these UI object references are not serializable so would not survive a session migration between servers and secondly there is no guarantee that the framework will re-use the same component tree from request to request, although in practice it generally does do so. So there danger here is, that at best you end up with an NPE after you session has migrated, and at worse, you end up pinning old generations of the component tree happily eating up your precious memory. So that's clear, we should never. ever, be storing references to components anywhere other than request scope (or maybe backing bean scope). So double check the scope of those binding attributes that map component references into a managed bean in your applications.  Why is it Such a Common Mistake?  At this point I want to examine why there is this urge to hold onto these references anyway? After all, JSF will obligingly populate your backing beans with the fresh and correct reference when needed.   In most cases, it seems that the rational is down to a lack of distinction within the application between what is data and what is presentation. I think perhaps, a cause of this is the logical separation between business data behind the ADF data binding (#{bindings}) façade and the UI components themselves. Developers tend to think, OK this is my data layer behind the bindings object and everything else is just UI.  Of course that's not the case.  The UI layer itself will have state which is intrinsically linked to the UI presentation rather than the business model, but at the same time should not be tighly bound to a specific instance of any single UI component. So here's the problem.  I think developers try and use the UI components as state-holders for this kind of data, rather than using them to represent that state. An example of this might be something like the selection state of a tabset (panelTabbed), you might be interested in knowing what the currently disclosed tab is. The temptation that leads to the component reference sin is to go and ask the tabset what the selection is.  That of course is fine in context - e.g. a handler within the same request scoped bean that's got the binding to the tabset. However, it leads to problems when you subsequently want the same information outside of the immediate scope.  The simple solution seems to be to chuck that component reference into session scope and then you can simply re-check in the same way, leading of course to this mistake. Turn it on its Head  So the correct solution to this is to turn the problem on its head. If you are going to be interested in the value or state of some component outside of the immediate request context then it becomes persistent state (persistent in the sense that it extends beyond the lifespan of a single request). So you need to externalize that state outside of the component and have the component reference and manipulate that state as needed rather than owning it. This is what I call the UIManager pattern.  Defining the Pattern The  UIManager pattern really is very simple. The premise is that every application should define a session scoped managed bean, appropriately named UIManger, which is specifically responsible for holding this persistent UI component related state.  The actual makeup of the UIManger class varies depending on a needs of the application and the amount of state that needs to be stored. Generally I'll start off with a Map in which individual flags can be created as required, although you could opt for a more formal set of typed member variables with getters and setters, or indeed a mix. This UIManager class is defined as a session scoped managed bean (#{uiManager}) in the faces-config.xml.  The pattern is to then inject this instance of the class into any other managed bean (usually request scope) that needs it using a managed property.  So typically you'll have something like this:   <managed-bean>    <managed-bean-name>uiManager</managed-bean-name>    <managed-bean-class>oracle.demo.view.state.UIManager</managed-bean-class>    <managed-bean-scope>session</managed-bean-scope>  </managed-bean>  When is then injected into any backing bean that needs it:    <managed-bean>    <managed-bean-name>mainPageBB</managed-bean-name>    <managed-bean-class>oracle.demo.view.MainBacking</managed-bean-class>    <managed-bean-scope>request</managed-bean-scope>    <managed-property>      <property-name>uiManager</property-name>      <property-class>oracle.demo.view.state.UIManager</property-class>      <value>#{uiManager}</value>    </managed-property>  </managed-bean> In this case the backing bean in question needs a member variable to hold and reference the UIManager: private UIManager _uiManager;  Which should be exposed via a getter and setter pair with names that match the managed property name (e.g. setUiManager(UIManager _uiManager), getUiManager()).  This will then give your code within the backing bean full access to the UI state. UI components in the page can, of course, directly reference the uiManager bean in their properties, for example, going back to the tab-set example you might have something like this: <af:paneltabbed>  <af:showDetailItem text="First"               disclosed="#{uiManager.settings['MAIN_TABSET_STATE'].['FIRST']}"> ...  </af:showDetailItem>  <af:showDetailItem text="Second"                     disclosed="#{uiManager.settings['MAIN_TABSET_STATE'].['SECOND']}">     ...  </af:showDetailItem>  ...</af:panelTabbed> Where in this case the settings member within the UI Manger is a Map which contains a Map of Booleans for each tab under the MAIN_TABSET_STATE key. (Just an example you could choose to store just an identifier for the selected tab or whatever, how you choose to store the state within UI Manger is up to you.) Get into the Habit So we can see that the UIManager pattern is not great strain to implement for an application and can even be retrofitted to an existing application with ease. The point is, however, that you should always take this approach rather than committing the sin of persistent component references which will bite you in the future or shotgun scattered UI flags on the session which are hard to maintain.  If you take the approach of always accessing all UI state via the uiManager, or perhaps a pageScope focused variant of it, you'll find your applications much easier to understand and maintain. Do it today! More Information Another interesting article relating to this topic has been written by Steven Davelaar  subsequent to the original publication of this post. This article is well worth checking out more more information on this area and some best practice around component references. Rules and Best Practices for JSF Component Binding in ADF

One of the most common mistakes that I see when reviewing ADF application code, is the sin of storing UI component references, most commonly things like table or tree components in Session or PageFlow...

Misc

Application Scope v's Static - Not Quite the same

An interesting question came up today which, innocent as it sounded, needed a second or two to consider. What's the difference between storing say a Map of reference information as a Static as opposed to storing the same map as an application scoped variable in JSF? From the perspective of the web application itself there seems to be no functional difference, in both cases, the information is confined to the current JVM and potentially visible to your app code (note that Application Scope is not magically propagated across a cluster, you would need a separate instance on each VM). To my mind the primary consideration here is a matter of leakage. A static will be (potentially) visible to everything running within the same VM (OK this depends on which class-loader was used but let's keep this simple), and this includes your model code and indeed other web applications running in the same container. An Application Scoped object, in JSF terms, is much more ring-fenced and is only visible to the Web app itself, not other web apps running on the same server and not directly to the business model layer if that is running in the same VM. So given that I'm a big fan of coding applications to say what I mean, then using Application Scope appeals because it explicitly states how I expect the data to be used and a provides a more explicit statement about visibility and indeed dependency as I'd generally explicitly inject it where it is needed. Alternative viewpoints / thoughts are, as ever, welcomed...

An interesting question came up today which, innocent as it sounded, needed a second or two to consider. What's the difference between storing say a Map of reference information as a Static as opposed...

Hudson

Optimizing Secured Hudson performance on Tomcat

There was some debate in the Hudson Community meeting this week on various areas of performance that need to be addressed for enterprise grade installations such as that used at the Eclipse foundation. Least of these issues was a problem that we'd observed both on ci.hudson-ci.org server and other, and this was the matter of image and other resource caching, or rather, lack thereof.  Hudson itself has a filter which sets the expire header on all of these resources to a year in the future, so the browser should be retrieving from cache rather than hitting the server again. However, this simply was not happening. An investigation of the traffic via Chrome's developer tools shows the cause:  You can see that the Expires directive in the response is 2013, however, the Cache-Control: no-cache is overriding this.It turns out that this is down to Tomcat behaviour when running a secured web app. It sets the no-cache directive automatically, irrespective of the type of resource it is serving. Fortunately there is a way to prevent this behaviour  using a simple configuration in the Tomcat server.xml, simply add the following Valve definition into the <Context> being used for Hudson:<Valve className="org.apache.catalina.authenticator.NonLoginAuthenticator"       disableProxyCaching="false" />Once Tomcat is restarted, your resources will be cache-able again. For more complete information about Hudson configuration behind Tomcat check out the Tomcat page in the Hudson Wiki.

There was some debate in the Hudson Community meeting this week on various areas of performance that need to be addressed for enterprise grade installations such as that used at the Eclipse...

ADF

uncommittedDataWarning - It's a Matter of Timing

An interesting nugget came across my desk yesterday that I though was worth sharing. What's wrong with this picture: Absolutely nothing right?  That's exactly the kind of taskflow we would expect to see where the user can, from the listEmployee screen, either create a new empty record by following the new navigation rule or edit the current row using the edit rule. The problem in this particular case was, however, that the employeeList screen has uncommittedDataWarning="on" set as an attribute on the document component: <af:document title="Employee List" uncommittedDataWarning="on">  So what happens? Every time the new navigation rule is followed to navigate to the editEmployee screen the uncommitted data warning pops up.  So what's going on here? The listEmployee screen is read only in this case how could it have marked the data control as dirty?  Well it all comes down to the timing of when the uncommittedDataWarning takes place. The check will be made when the JSF View ID is being changed.  If you look at the above taskflow you'll see that the createInsert method binding will take place before the navigation away from the page, so at the point in time that the continue navigation is invoked the DataControl will be dirty after all and the uncommittedDataWarning check will fail, popping up the dialog.  The solution in this case is simple (assuming that you have to keep the uncommittedDataWarning="on" on the source page). You can revert to the technique that we used to use in ADF before TaskFlows came along.  You create the method binding for the createInsert operation in the employeeEdit Screen and add an invokeAction in the executables section of the pageDef which is conditional on a flag set on the request. Something like this: <invokeAction id="InvokeCreateIfRequired"               Binds="CreateInsert"               RefreshCondition="#{requestScope.editAction eq 'INSERT'}"              Refresh="ifNeeded"/>  Then the command item that triggers the navigation to the edit page sets that flag (or does not set it if you want to do an edit rather than an insert) : <af:commandButton text="New" id="cb1" action="new">    <af:setPropertyListener from="#{'INSERT'}" to="#{requestScope.editAction}" type="action"/></af:commandButton> So there you go - there is life in the old techniques yet! 

An interesting nugget came across my desk yesterday that I though was worth sharing. What's wrong with this picture: Absolutely nothing right?  That's exactly the kind of taskflow we would expect to...

ADF Faces and UI

CSS Animations - The Panel Flip

In the my final (for now) discussion on CSS3 animations with ADF Faces Rich Client  UI I wanted to discuss the most complex, but fundamentally useful (from a technique perspective) of the three animations shown in the introduction posting. The first two animations that I showcased were simply triggered by the browser's inherent mouse-over functionality. I didn't actually need to do anything to make the animation happen apart from assigning the correct styleClass to the panel or button.  In this final animation I'm triggering the animation from code and what's more I'm actually chaining together two animations with a server side call made in the middle. To break it down here's the logical flow: Initiate a rotation of 90 degrees --> Change the contents of the panel -->  Return rotation to 0 degrees. So the question is, how do we chain all of these actions together, given that the initial rotation will itself take a certain amount of time (2 seconds)?  Well, to handle this we have to write a little bit of JavaScript  that will first of all set the styleClass to provide the first 90deg animation and also register a listener function which will execute once the rotation is finished.  This callback function then executes the Server code we need and then kicks off the reverse animation.  The Animations   So first of all, the two styles that define the animations. This should be fairly obvious and understandable by now: .rotateOut {   -webkit-transition-property: -webkit-transform;    -webkit-transform: rotateY(90deg);    -webkit-transition-timing-function: ease-in-out;    -webkit-transition-duration: 2s;).rotateReturn { -webkit-transition-property: -webkit-transform;    -webkit-transform: rotateY(0deg);   -webkit-transition-timing-function: ease-in-out;   -webkit-transition-duration: 2s;} The JSF components In this example I'm using a switcher which is controlled by a managed bean  called uiManager. This switcher will either display the panelHeader that contains the inputForm or the comments screen. Contrary to your expectation though, it's not these panels managed by the switcher that we'll actually be animating, but rather a parent of the switcher, another panelGroupLayout. So the hierarchy looks a  like this: Panel group layout that will be animated Decorative box that will apparently rotate   Panel group layout that will be refreshed to show the change in contents Switcher  <af:panelGroupLayout layout="vertical" id="flip" clientComponent="true" binding="#{animationBB.flipPanel}" styleClass="rotateReturn"><af:decorativeBox theme="dark"> <f:facet name="center"> <af:panelGroupLayout id="refresh"  layout="vertical" binding="#{animationBB.refreshPanel}">  <af:switcher defaultFacet="ASide" facetName="#{uiManager.flipAnimationSelectedSide}" >    <f:facet name="ASide">      <af:panelHeader text="Basic Information">       ...      </af:panelHeader>     </f:facet>     <f:facet name="BSide">       <af:panelHeader text="Comments">      ...      </af:panelHeader>     </f:facet>   </af:switcher>  </af:panelGroupLayout> </f:facet>  </af:decorativeBox></af:panelGroupLayout>   Notice that the outer panelGroupLayout id="flip" has a binding to a backing bean for the page, this is so we can get the correct clientId back for it (look back at my Visual Notifications During Long Running Transactions article for details of this technique). The inner pgl, id="refresh", also has a binding to the backing bean which we will use later in the serverListener to force a refresh on that panel and the switcher inside it.  Within each of the switcher "panels" is a button (not shown above) that will actually trigger the animation.  Here's the code for the button on the A-Side: <af:commandButton text="More..." partialSubmit="true" clientComponent="true" id="cbflip1"> <af:clientAttribute name="flipPanel"                      value="#{animationBB.flipClientId}"/>  <af:clientListener method="animateFlipPanel"                     type="action"/>  <af:serverListener type="flipEvent"                     method="#{animationBB.handlePanelFipEvent}"/></af:commandButton> The code for the B-Side button is identical. To break that down we have three things of interest: A clientAttribute that is used to send the client id of the panel that we want to spin to JavaScript A clientListener to actually wire up a JavaScript  event to the button press A serverListener which identifies the server side method that will be called half way through the animation to tell the switcher to change contents. So let's look at each of those: The Client Attribute The client attribute is bound to the page backing bean where there is a simple function that asks the panel that will be "flipped" for it's client ID, in this case the flipPanel variable contains the reference to the RichPanelGroupLayout which is bound to that outer panel: /** * Gets the correct client component ID for this panel in the context in which the  * panel is placed. This provides a safe way of getting the client ID if the component * is embedded in a region or similar where the computed path may change depending on the use. * @return clientID for use in JavaScript  */ public String  getFlipClientId() {   return flipPanel.getClientId(FacesContext.getCurrentInstance());} The JavaScript The clientListener on the button calls the animateFlipPanel method. This is stored in a .js file referenced using the <af:resource> tag in the metaContainer facet of the document: function animateFlipPanel(event) { //Get the ID of the panel to flip. //This has been passed in via the clientAttribute     var fpId = event.getSource().getProperty('flipPanel'); //Grab a reference to this button that raised the //event. we need this to register the callback against    var raisingComponent = event.getSource();    //First animation sends us to 90deg    var transition = "rotateOut";    flipPanel = AdfPage.PAGE.findComponentByAbsoluteId(fpId);    initiateClientFlip(raisingComponent, flipPanel, transition);}   And here's the method that assigns the animation: /** * Kick off the animation - rotate the panel to 90 degrees which will make it   * disappear as it's sideways on to us. * Then register the callback to rotate back once the animation is finished * @param raisingComponent - the button that kicked things off * @param flipPanel - the PGL to animate (assign style to)  * @param transition - the style to apply */function initiateClientFlip(raisingComponent, flipPanel, transition) {  //Set the style to animate the rotation  flipPanel.setStyleClass(transition);      /* Setup a callback to reverse the animation once the transition is finished.  * Note that we remove the transition listener once it's executed so that   * it is not called by the flipBack transition as well    * Note also that we have to attach the listener to the underlying DOM object */      // Get the DOM object that represents this panelGroupLayout  var flipPanelReal = AdfAgent.AGENT.getElementById(flipPanel.getClientId());     //Define the callback  var reverseTransition = "rotateReturn"  var flipBackFunction = function (event) {animateFlipBack(raisingComponent, flipPanel, reverseTransition); event.target.removeEventListener("webkitTransitionEnd",flipBackFunction);};     // Add the transition listener to queue up both the animation back    // and the server side change which will apparently flip the // contents of the panel   flipPanelReal.addEventListener("webkitTransitionEnd", flipBackFunction,false);}  So the actual animation part of the above code is trivial, we just set the new style to kick that off.  The exciting part comes in the definition of the eventListener (webkitTransitionEnd) which is set up to execute once the animation has finished. Like everything that I have covered in this short series, the code here is webkit (Chrome & Safari) specific. Similar events exist both in generic terms for the future and in specific versions for FireFox and IE. And finally the animateFlipBack() function and a convenience method that it uses:  /** * Once the initial animation is done this method is invoked to change the contents of the panel and then * animate back to the starting point giving the illusion of a full 180 degree flip * @param raisingComponent - reference to the button so we can invoke the serverListener * @param flipPanel - pgl to animate * @param reverseTransition - animation style */function animateFlipBack(raisingComponent, flipPanel, reverseTransition) { // Call the event on the server which will cause the switcher to   // change it's contents and issue a PPR event  raiseServerFlipEvent(raisingComponent); //Now start the return animation flipPanel.setStyleClass(reverseTransition);   }/** * Simple function to queue up the server side event on the button that  * instigated the flip. This event does not need to send a payload * @param raisingComponent - the button  */function raiseServerFlipEvent(raisingComponent){    var flipEvent = new AdfCustomEvent(raisingComponent,"flipEvent",{},false);    flipEvent.queue(true);} The serverListener  The role of the serverListener code is to toggle the facet that the switcher is currently displaying and then force the panel containing the switcher to refresh with a PPR event: /** * Event raised from JavaScript to tell us that the flip animation is underway and we  * need to change the content on the panel  * @param clientEvent */public void handlePanelFipEvent(ClientEvent clientEvent) {  String currentSide = _uiManager.getFlipAnimationSelectedSide();  String targetSide = UIManager.A_SIDE;  if (currentSide.equals(UIManager.A_SIDE)){      targetSide = UIManager.B_SIDE;  }  _logger.info("Flipping to " + targetSide); getUiManager().setFlipAnimationSelectedSide(targetSide);          // And queue the client refresh  AdfFacesContext.getCurrentInstance().addPartialTarget(getRefreshPanel());}  This function as you can see is a toggle based on the current value stored in the uiManager.  The UIManager itself is a session scoped bean that just holds the current side value.  It is injected into this backing bean using a managed property in the managed bean definition. The function getRefreshPanel() returns a reference to the pgl that surrounds the switcher (id="refresh" in the hierarchy above).  Wrap Up  The technique that I've discussed within this article may seem a little complex but in fact it's all quite logical and can be quite easily extended and made generic. You can see how more complex animations may be achieved by stringing together a whole sequence of callbacks to execute after the previous animation has completed and how you can wire in server side calls into the mix. 

In the my final (for now) discussion on CSS3 animations with ADF Faces Rich Client  UI I wanted to discuss the most complex, but fundamentally useful (from a technique perspective) of the three...

Oracle

Integrated Cloud Applications & Platform Services