Red Mavericks articles

Calendar- Date Time in PCS - Header

Dealing with Dates and Times in Oracle Process Cloud Service

Introduction

Oracle Process Cloud Service (PCS) is great! You can build process-based applications in two shakes of a lamb’s tail, much quicker than most Low Code platforms in the market. Of course, you can’t, or at least shouldn’t, develop any “normal” master-detail CRUD application with Oracle Process Cloud Service. If you need this kind of applications perhaps Oracle Application Builder Cloud Service will suit you better, but for process-centric applications, it’s a hard to beat tool.

As you may know, Oracle also has an on-premise product, called Oracle BPM, which features a similar codebase, but it features a more advanced and complex UI and it takes a bit more time to produce a similar application.

Oracle PCS really shines for its simplicity and ease of use, because the UI was streamlined and is much more focused. However, all this optimization and streamlining led to decisions to simplify the UI and some features present in Oracle BPM are not present in Oracle PCS. Most of them we won’t really need except for 1% of all our application needs, but a few are a more common necessity. The capacity to use functions to manage and operate dates and times fit this last set.

Oracle BPM allows you to manipulate dates using several options, with Data Associations and Script tasks perhaps being the most common. In Oracle PCS, the Data Associations don’t allow you manipulate dates nor retrieve the current Date / Time, and script tasks plain and simply are not available.

It’s possible to create services that do whatever we need to do with dates and then call them in Oracle PCS, but sometimes we want a more direct approach.

The Use Case

Let’s consider the following case:

We have a simple approval process with 3 steps. Every time there’s a response to a task, we want to record which response was and at which date and time it was made. We also want to show this information to the user, in the task web form, and we want that the whole process takes a calculated amount of time as the most, with it automatically finishing up after that amount.

Something a bit like this:

The Use Case process

The Use Case process

And the web form:

The Use Case web form

The Use Case web form

 

Notice that Oracle PCS automatically creates a data object in the process, of the same type as the start form.

Automatically created data object corresponding to our web form

Automatically created data object corresponding to our web form

Also, all task data associations are done automatically, without the need to do this manually, when you set the task form.

Choose the web form for the task to use

Choose the web form for the task to use

Automatic Data Associations - Cool Stuff!

Automatic Data Associations – Cool Stuff!

Remember that we want to fill each of the decision fields with both the Outcome of the last response and the date and time of that response.

If we try to so it through the web form functions, you’ll notice that you can only set a field to the current date/time. This would change the value of the field “When?” every time the user was shown the form. This is not what we want.

Trying to automatically fill this field

Trying to automatically fill this field

... and you can. But that's not what you want.

… and you can. But that’s not what you want.

Also, you can’t do calculations between fields which are of type date/time. Let’s say you also want a new field which tells you the number of days between the date of the first decision and the last one. How can you calculate this in the form?

Common sense would lead us to try to subtract the value of the field that holds the date/time of the first decision, from the value of the field that holds the date/time of the last decision. Unfortunately, this doesn’t work, as you can see below (31 May – 18 May = 0)

Our form doesn't calculate the Nr of days correctly

Our form doesn’t calculate the Nr of days correctly

The Nr of days calculation function

The Nr of days calculation function

We can also try the data association route, but, as we can see from the image below, there are no functions to deal with dates in this part.

Data Associations Expression Builder - Data Objects

Data Associations Expression Builder – Data Objects

Data Associations Expression Builder - Operators

Data Associations Expression Builder – Operators

Finally, as there are no Script Tasks, as you have in Oracle BPM, you can’t actually program this in your process.

So, how can we do this?

We cheat!

Let’s try to use a Business Rule for this. By placing a Business Rule after each task, we guarantee an immediate execution right after the decision is taken and we record the rule execution date/time as the decision date.

Business Rules Calendar objects

Business rules get an input, do some magic, and produce an output… pretty much as any other task in our process. What makes them special is the amount of magic one can do inside them.

When we create a decision, we can use a lot of Java functions, including a few related to treating dates and times.

So we create a Business Rule, setup the input and output as objects of the type of the web form (this makes it easier to do the data associations) and, once we enter the decision screen we just create a new General Rule.

Creating your General Rule

Creating your General Rule

Then we create a true condition in the “If” part of the rule, as we want it to always execute, and in the “Then” part, we specify that we want to modify the object that we specify in the Drop Down List (in the example below the object is called “Other”).

Our Rule Configuration

Our Rule Configuration

We click on the pencil icon and choose the field in which we want to do the date processing (click on the magnifying glass). We are taken into the Condition Browser, where we can access the Expression Builder

Condition Browser

Condition Browser

Business Rules Expression Builder

Business Rules Expression Builder

As you can see, this expression builder is much more advanced than the one available in the Data Associations dialog, with a few more tabs, including the Functions.

In here we can do calculations with our dates, set them as we want.

So we’ll grab the CurrentDate.date.time calendar and apply the JavaDate.to datetime string to it, like so:

Our Date expression

Our Date expression

And that’s it. This will calculate the current date and time, put it in the output object, which is our web form.

Now we only need to repeat for all tasks. A bit like this:

Our Use Case process with Business Rules

Our Use Case process with Business Rules

I hope that this article can help you do more complex calculations and extend the normal use of Oracle PCS, to cope with more business scenarios.

If you have any questions please place them in the comments box below.

José Rodrigues

P.S: All of this could also be done with the help of ICS, JCS or ACCS. I’ll write about it in a couple of weeks.

Post header image by Sebastien Wiertz

Building Case Management Patterns in PCS

Implementing Case Management Patterns using Oracle Process Cloud Service (PCS)

Hi everyone and welcome to the second part of our article on implementing Case Management (CM) patterns with Oracle Process Cloud Service (PCS).

On the first part, we learned a bit about the concepts around Case Management and we (barely) started a process on PCS. We’ll use this process now as a container to implement the ad-hoc nature patterns.

The First Rule of Fight Club

First Rule Fight Club

The First Rule of Fight Club © 20th Century Fox

“We do NOT try to implement Case Management on PCS!” – That’s the first rule. What we will do is implement a small subset of behaviors, which will offer some of the advantages of Case Management.

The second rule is that we have two buddies that can help us in this quest: Database Cloud Service (DBCS) and Integration Cloud Service (ICS). Some of the behaviors will need a bit of persistence, which implies placing a lot of case metadata in some control tables, hence the DBCS, with the ICS being used to handle all integrations. ICS may not be necessary but makes integration easy as peach. Use them extensively!

As we’re trying to “hammer a screw”, things will not be pretty. This is a workaround. Please take it as a way to implement these behaviors.

Regarding the first rule, the set of behaviors which we’re going to implement is the following:

  • Ad-hoc Task and Process Invocation
  • Milestone and Stage Trigger/Set
  • Event Listeners

Let’s Start

So, last time we created a message based process

Again, the process must be created with messages events, as these will allow it to be called by other cases in an asynchronous way.

The first thing we do is get a case ID. This ID should come from another system (for instance, a database) and will be used to guarantee correlation between all elements of the case. We’ll get into to that further ahead.

Then, what we typically do is set up a business rule (decision table) or a database table, in which we predefine some configurations, such as Overall Process SLA, Milestone SLA’s, etc… This will allow you to change the way a process/case behaves, without actually having to change the process model.

Centralized Control – The Case Main UI

Now, we’re going to need a UI, from which we should be able to invoke whatever actions I want, in the order that I want them.

For that, we’ll build a Human Task and implement the respective form, using the Web Form technology. In fact, you can build your UI in whatever technology you want and then use the REST API’s to perform the task actions, but in this case, we did it with the web forms.

Here is an example of a Custom UI, using Oracle’s Alta UI, and delivered by Link Consulting’s BPM Framework (Very cool product! Ask for a demo at linkconsulting.com/oracle :))

No matter what technology you use, you should guarantee that it contains the following information:

  • All business relevant data
  • Access to documents to view, upload or download.
  • A list of all available milestones, their status and moment in which the last status was set
  • A list of all previous actions in the case, including the famous “Who did what and when?”
  • A selector of all possible actions available at that moment
    • Typically you’ll want to restrict the actions you can do at any moment, based on the actions performed before and the milestones reached, i.e. the case state
    • The list of possible actions is determined through one of two options:
      • either we implement this logic outside and then invoke it as a web service, for instance in the database
      • or we implement it by using Business Rules.
    • In both cases, the set of possible actions must be determined prior to entering the Human Task

Main Case Loop Handler

The idea of having a centralized control is complemented with a loop handler. This will ensure that the process keeps coming back to the Case Main UI with each action taken.

We do this by creating a container, in this case, an embedded subprocess and then placing both the activity that determines the allowed actions and the Case Main UI. Then you evaluate the action taken and the case state, determining if the case is now resolved, canceled or if it still continues, looping back to the embedded subprocess in this case.

With each loop iteration, and because this is a case, we must check if the changes in the case state or milestone state will trigger automatically any actions. For instance, resolving a dispute in customer service by offering the customer some money should trigger automatically a bank transfer and a notification by e-mail both to the customer and to the support supervisor.

 

So we need to implement this verification into the Main Case Handler. First, we validate if the last iteration generates any automatic action. We do this by invoking a service that implements this logic. In our example, we did the validation in the Database, through a stored procedure that checks the case data and understands if any automatic action is to be taken. Then we have a branch: If there are any automatic actions to be taken, the process just takes them. If not, the process collects the user allowed actions based on the current case state and them spawns a new instance of the human task Case Main UI.

Do notice that the automatic actions may change the case state or milestone state, in which case there may be further automatic actions to be taken, and so on. This may lead to infinite loops, so be careful when setting the conditions that lead to automatic actions.

The Case Action Controller

After the process/case determines that an action is to be taken, either automatic or manual, we then need to take it in such a way that the process/case doesn’t stop there waiting for the action to be completed. In a normal case management scenario, a user can trigger multiple new tasks without needing to finish the previous ones. So we need to allow multiple actions to run in parallel.

Also, we may want to have some restrictions on how a given task is invoked. Let’s say that, for instance, you want to ask your supervisor for his approval on a compensation for a customer. So you trigger the Action “Superior Approval”. Now you want to be able to do other actions, for instance, to contact the customer, but you don’t want the system to allow the user to trigger another “Superior Approval” action until the last one was completed.

This is what your Case Action Controller does. It controls the actions that can be taken and in what conditions it can take them.

Right now you’re probably asking “Huuummmm, but isn’t that what the ‘Get Automatic Actions’ and the ‘Get Allowed Actions’ do?” Well, kind of… We use the case main controller to do a few specific things:

  • Control the cardinality of the execution of actions – This is done with a Service Task
  • Allow parallel tasks to happen – We use an inclusive gateway, and we model all possible actions inside it.
  • Set Case Stage status – This is done with a Service Task

Our Case Action Controller looks like this, in a very simplified way

Notice that we use Throw Message Events to trigger the actions. This allows the process/case to trigger this, but then immediately follows to the end of Case Action Controller, without waiting for that action to be concluded. This is how we implement the semantics of an ad-hoc invocation of a process or task, as many times we want, in the order that we want, and not using a predefined, well-structured process.

Implementing our tasks and processes

To implement our tasks and processes that are to be called inside our Case Action Controller, we use the exact same pattern. A task is implemented with a message-based process that only has that task in it.

For processes is exactly the same, but instead of having a single task inside the process, the whole process logic is in it.

Milestone and Stage Trigger/Set

In regards to updating the Milestone and Stage states, we do it through web service invocation and directly update the underlying database. We build a table for Milestones and one for Stages, which include who did what and when. Every time we need to update a Milestone or a Stage state, we just send it to the DB, through the use of REST web services (DBCS features ORDS). This is done by placing service tasks where we want them to be updated.

Updating Milestones and Stages is the way we can understand how a case is progressing and what actions can be taken at any moment, manual or automatic.

Event Listeners

There may be times in which you would want to listen to events and trigger a case activity based on those events. This is implemented in CMMN with the use of Event Listeners, and are represented like this.

The first one is a human event listener. In this case, it triggers a task called “Request Help from Colleague”. In PCS we implement this behavior as we mentioned before: invoking a message based process that only has this task inside. It’s like invoking an Ad-Hoc task.

The second one is a timer event listener and it’s a bit trickier to implement because PCS doesn’t offer that many tools to calculate dates and times. Sometimes you would want to do date/time calculations, and PCS isn’t very cooperative in this subject. Comparing with the on-premise product (Oracle BPM), it’s very limited. There are workarounds for this (think of business rules), but we should try and avoid them.

What we typically do is we create a boundary timer event and attach it to either the Main Case embedded subprocess or a given task, and set the timer using the interval condition.

In the case shown here, the timer is attached to the embedded subprocess in a non-interrupting way. When it triggers, it just sets a given milestone. As the event is non-interrupting, the execution stays where it is.

Putting it all together

Adding all of this into a PCS application will render your case-like processes. We built an example on a small project to handle baggage damage claims for airline and airport handlers. The corresponding CMMN model was something like this:

Complaint CMMN model

Complaint CMMN model

And the corresponding PCS main process was this one.

Case Management using PCS - Part II - 14

PCS implementation of the case

Conclusions

So we hope this article helps you build some less-structured processes using Oracle Process Cloud Service, and that the limitations of not having case management (at least at the moment of publication) may be overcome, to deliver more value to your organizations.

As always, feel free to reach us with your comments and questions. We’ll try to answer that as quickly as possible.

More articles are in the pipeline and you’ll definitely hear from us in the next few weeks.

Until then

Maverick (José Rodrigues)

This is a cross post with Link Consulting. For more Oracle Middleware related posts, please visit http://www.redmavericks.com

post header image by Alden Jewell

Naming Conventions - part 3

ADF Namings Conventions – Part III

Hi all,

In my previous post ADF Namings Conventions – Part II I have focused my attention on:

  • Model & View Controller Project

Today I will focus on:

  • Task Flows
  • Templates
  • JSF, JSFF, JSPX
  • JAVA Events
  • JAR, WAR, EAR files

 

Task Flows

In this section we will provide the namings related with task flows.

 

Task Flow Namings

 

The name for Task Flows should be defined as follows:

<TASK_FLOW_CAMEL_CASE> + TF

Example: myTaskFlowTF

We may have different task flows types, each one built to address one purpose. For these cases we added a constant to the name in order to easily recognize their purpose/target. Next table presents the Types and Target Names:

Type Task Flow Target Name
 Task Flow to filter data  <TASK_FLOW_CAMEL_CASE> + Filter + TF
 Task Flow to perform actions on data <TASK_FLOW_CAMEL_CASE> + Action + TF
 Task Flow to list data <TASK_FLOW_CAMEL_CASE> + List + TF
 Task Flow to detail data <TASK_FLOW_CAMEL_CASE> + Detail + TF
 Task Flow to combine multiple task flows <TASK_FLOW_CAMEL_CASE> + Container + TF

 

Task Flow Managed Beans

 

Task Flows’ managed beans are responsible for managing data. Multiple managed beans can be created for a single Task Flow. Nevertheless you usually have one main managed bean. For these cases managed beans should have a similar name as the task flow.

As you may have already noticed, you are free to provide any name you want to the Java Class you assign to your managed bean in “Managed Beans” task flow’s tab. For this scenario we recommend to use the same name of the Java Class.

By following this two advises you will be able to find what you are looking more easily without losing time and effort to understand the mappings made by each developer. This is very important for developers during development and maintenance phases. Based on these assumptions take a look on the following example:

 Task Flow Name:  myTaskFlowTF
 Java Class Name:  MyTaskFlow
 Managed Bean Name:  MyTaskFlow

 

Task Flow Input & Return Parameters

 

Task flow’s input parameters should be prefixed with “in”:

in + <CAMEL_CASE>

Example: inMyParameter

Task flow’s return parameters should be prefixed with “rtn”:

rtn + <CAMEL_CASE>

Example: rtnMyParameter

 

Templates

ADF lets us to create different types of templates to abstract common functionalities used in our projects, for example: Page Templates and Task Flow Templates. This templates should be created using the following pattern:

<CAMEL_CASE> + Template

Example: myTaskFlowTemplate, myPageTemplate

 

JSF, JSFF, JSPX Namings

Pages names should have a self-explanatory name in order to be easily identified and recognized with its purpose. The default pattern we followed was:

<CAMEL_CASE>

 

In Task Flows you may have multiple pages depending on the route it takes, but for the main page (if we have one) we should provide it with the same name as the task flow but without ‘TF’ suffix.

Example:

 Task Flow Name: myFinantialTasksListTF
 Page Name: myFinantialTasksList

 

Java Events Namings

For our controls events we set suffixes for them. This will help you to understand the event type you are taking care without the need to go directly to the page, only if you need to understand it in more detail. The list of suffixes for each type of event are listed in the following table:

Event Type Suffix
 Action Event Action
 Value Change Listener VCL
 Selection Event Listener SEL
 Client Event Listener CEL
 Return Event Listener REL
 Action Event Listener AEL

 

JAR, WAR, EAR Files

Building and deploying projects lead us to create deployment profiles. In this deployments profiles you should use the same namings. The next table addresses this topic by providing the namings for each type of deployment profile.

File Type Prefix
 JAR jar + <PROJECT_NAME> + <MODULE_NAME>
 ADF JAR Library adflib + <PROJECT_NAME> + <MODULE_NAME>
 Shared Library sharedlib + <PROJECT_NAME> + <MODULE_NAME>
 WAR war + <PROJECT_NAME> + <MODULE_NAME>
 EAR ear + <PROJECT_NAME> + <MODULE_NAME>

 

You can find the PDF with these series of posts right here.

I hope these series of posts may help you in your projects 🙂

 

Cheers,

Pedro Gabriel

@PedrohnGabriel

This is a cross post with LinkConsulting. For more Oracle Middleware related posts, please visit http://www.linkconsulting.com/oracle

Post Header photo by Geoffrey Fairchild

Case Management using PCS

Case Management Patterns using Oracle Process Cloud Service

Hi and welcome to a new article on Oracle Process Cloud Service (PCS).

This time, we’re going to address some use patterns that may seem difficult to implement using PCS, and tackle the need for unstructured parts of the process, which is to say, parts of the process that can’t be previously modelled because, well… we don’t know how they’ll turn out.

Take for instance a complaint to your customer service department. You’ll never know, in advance, what kind of complain it will be, or if you need one, two, five or fifty interactions with the customer, or if you need to get approval from department A or B to try and compensate the customer, or even if any legal action will be needed with a supplier of yours, after they failed to compensate the complainer in due time.

So, you see, there are some elements that may render part of your process impossible to predict, at least in terms of activity sequence. You know that these may take place at some point in time in the process, but you can’t plan ahead and model the exact activity sequence (“A” will happen after “B”).

To handle this type of less structured processes (I don’t like the term “Unstructured”, because they have a structure), there’s a discipline called “Case Management” (CM). CM handles the choreography of this type of processes, called Cases, guaranteeing that the activities that are part of the process are executed at the right time and when conditions permit it.

For the remainder of the article, please consider the terms “Case” and “Process” as interchangeable, the term “Less structured Process” as equivalent to Case, and the term “Structured Process” as equivalent to a predefined flow-controlled Process (BPMN process or equivalent).

The main idea behind CM is that instead of the process model determining the next action to be taken, it’s the worker who, actually decides what should be the next best action to perform in each situation, using his experience.

This is not to say that the worker can just do any activity at any time. Typically, there are specific business rules that enable or disable a given activity based on the current data and events associated with a specific process. However, these rules can be as tight or as flexible as we may need.

Case Management Patterns

The idea of the article is to give you the tools you need to implement Case Management patterns using Oracle PCS. This is not to implement Case Management in PCS, but just some case management behavioral patterns. Parts of what is “Case Management” will not be addressed in any way, but things like Ad-hoc process/task calls will, and this is sufficient for most needs.

Short Summary of Case Management Modelling Notation (CMMN)

Just as we have BPMN as a standard way to model structured business processes, OMG (Object Management Group) also defined a standard to model Cases, called Case Management Modelling Notation, or CMMN.

In a short summary, the most meaningful objects are:

  • Case – It’s our main object process all other objects are inside this one.
  • Stages – You can see it as a group of activities that represent a business concept.
  • Tasks – represents work to be done. Can be Human tasks, Process Tasks (call a structured process) or Case Tasks (call other cases). These can be mandatory or optional.
  • Events – Represents something that happens that is significant for the case: e.g. a new file is added to the case, or someone who applied for a loan at the bank suddenly dies.
  • Sentries – Criteria that need to be verified in order to instantiate or complete a task.

As with BPMN, you combine these objects to model the case behavior graphically.

Complaint CMMN model

Complaint CMMN model

For an introduction to CMMN, I suggest the following references:

  • Case Management Modeling and Notation – Knut Hinkelmann

http://knut.hinkelmann.ch/lectures/bpm2013/12_CaseModeling.pdf

  • Introduction to the Case Management Model and Notation (CMMN) – Mike Marin

https://arxiv.org/pdf/1608.05011.pdf

  • There’s an excellent book in the subject. You can find it in the link below.
    • Oracle Case Management Solutions – Léon Smiers, Manas Deb, Joop Koster, Prasen Palvankar

https://www.crcpress.com/Oracle-Case-Management-Solutions/Smiers-Deb-Koster-Palvankar/p/book/9781482223828

First Steps

The first rule is that we need to be able to start/invoke cases whenever we want, from whichever channel we want.

As we’re going to use PCS for this, we first need to create a new Application

Create New Application - Step II

Create New Application – Step II

Let’s call it “Complaint Case”.

Create New Application - Step II

Create New Application – Step II

Now, we create a new process in it. The process needs to start and end with a message event. This is what will allow us to reuse this when we want. Please, do not use None or Form events to start it.

Create New Application - Step III

Create New Application – Step III

Create New Application - Step IV

Create New Application – Step IV

In the next article

In the next article, we’ll address specific implementation patterns in Process Cloud Service and the setup of the data structure that facilitates Case behavior.

Until then, have a great week!

Maverick (José Rodrigues)

This is a cross post with LinkConsulting. For more Oracle Middleware related posts, please visit http://www.linkconsulting.com/oracle

Post Header photo by doug rattray

To break the rules you must first master them

ADF Namings Conventions – Part II

Hi all,

In my previous post ADF Namings Conventions – Part I I have focused my attention on:

  • Application & Project Namings
  • Packages Namings
  • Business Components Namings

Today I will start to talk about Model & View Controller Project namings.

 

Model Namings

For new ADF applications we are requested to set the names for Model and ViewController projects. In what concerns the Model it should following naming:

<PROJECT_NAME> + <MODULE_NAME> + Model

Example: RMKMyAdfLibModel

 

For the package structure it should be configured as follows:

<DOMAIN_NAME> + . + <PROJECT_NAME> + . + <MODULE_NAME> + . + model

Example: red.mavericks.rmk.my.adf.lib.model

 

As you can see, package structure follows the same structure defined in my previous post plus “model“.

View Controller Namings

In ViewController projects we have a wide range of namings we can follow since we have multiple features we can take advantage of. For that reason we divided it in sub topics. .

 

Project Name

 

The name for the project should be defined as follows:

<PROJECT_NAME> + <MODULE_NAME> + Controller

Example: RMKMyAdflibController

By using “Controller” prefix we are able to automatically identify projects type and purpose.

 

Project Default Package Structure

 

Package structure for View Controller project should be defined as follows:

<DOMAIN_NAME> + . + <PROJECT_NAME> + . + <MODULE_NAME> + . + view

Example: red.mavericks.rmk.my.adf.lib.view

As you can see, package structure follows the same structure defined in my previous post plus “view“.

 

Images, CSS and JavaScript Directories

 

Images, CSS and JavaScript directories should be defined right under “Web Content” folder. The folders should have the following names:

 

Folder Type Folder Path
 To contain images  resources/images
 To contain CSS files  resources/css
 To contain javascript files  resources/js

 

Example:

ImagesCssJavascript

 

Inside “web.xml” file in ViewController project set the following mappings:

<servlet-mapping>  
   <servlet-name>resources</servlet-name>  
   <url-pattern>resources/images/*</url-pattern>  
</servlet-mapping>  
<servlet-mapping>  
   <servlet-name>resources</servlet-name>  
   <url-pattern>resources/css/*</url-pattern>  
</servlet-mapping>  
   <servlet-mapping>  
   <servlet-name>resources</servlet-name>  
   <url-pattern>resources/js/*</url-pattern>  
</servlet-mapping>

 

Bounded Task Flows, JSFF, JSPX Directories

 

Reusable bounded task flows can be published in ADF Libraries and consumed by other ADF applications. For this use case is important, and a must, that all bound task flows have a unique name. If this isn’t accomplished ADF has no way to distinguish between task flows with the same name.

Before creating bounded task flows you should set a folder structure under “WEB-INF” folder. After this folder structure is created you can start creating your bounded task flows.

Folder structure should be created according to the following convention:

 

 <DOMAIN_NAME> + <PROJECT_NAME> + <MODULE_NAME> + view + <BUSINESS_AREA>

Example:

taskFlowsFolderStructure

JSF, JSFF and JSPX files must be saved on the same folder of the task flow.

Page definitions will be automatically generated with same package structure under Application Sources folder. Example: red.mavericks.rmk.my.adf.lib.view.financial or red.mavericks.rmk.my.adf.lib.view.retail

Managed Beans for Task Flows should be created under Application Sources folder with the following package structure:

<DOMAIN_NAME> + <PROJECT_NAME> + <MODULE_NAME> + <BUSINESS_AREA>

Example:

taskFlowsManagedBeans

 

We decided to create Managed Beans outside “view” package in order to not have a mixture between page definitions and java classes.

 

In my next post I will focus my attention on:

  • Task flows as well as Templates and some more regarding View Controller Projects
  • JAR, WAR, EAR files

 

Don’t miss my next post 🙂

Cheers,

Pedro Gabriel

@PedrohnGabriel

 

This is a cross post with LinkConsulting. For more Oracle Middleware related posts, please visit http://www.linkconsulting.com/oracle

Post Header photo by Lefteris Heretakis

ADF Naming Conventions - Part I

ADF Namings Conventions – Part I

Hi all,

Today I’m focusing my attention to ADF naming conventions.

Beside this post I will write two more in order to cover as much as possible all areas of this subject. In the last post I will provide a PDF with all information covered in these series of posts.

Motivation

During ADF applications development we may encounter many development challenges. One of these challenges is about implementing a naming convention to be used by all involved project developers during implementation.

Each developer have his own background and his own ideas on how things should be implemented. We want them to have freedom of thought in order to get the best approaches to reach the goal, but what we really don’t want is to have multiple ways of doing the same thing otherwise we might face really difficult challenges in the future, namely around software maintenance and bug tracing.

Also, the developer roster may change during project development. For the new ones who enter we need to provide proper training. If we can follow conventions we will have shorter training periods and they will be brought to speed quicker while familiarizing with the application.

After the application is deployed in the production environment, we face a new challenge, Maintenance and Support. Big headaches usually appear right there, and they can be even bigger if we don’t follow these important naming conventions in our applications’ code.

I have found some information here about this topic but we needed more, and we needed to instantiate it to our projects, so we decided to defined our own ADF Naming Conventions, to be used organization-wide on our ADF projects.

In this post I will share my experience and our ADF Naming convention rules regarding the following topics:

  • Application & Project Namings
  • Packages Namings
  • Business Components Namings

Abbreviations

Consider the following terms used in these series of posts:

Abreviation Definition Example
PROJECT_NAME Customer or project’s short name. Try to use only the necessary characters that are able to describe your customer/project so that everyone can understand it.  RMK (Red Mavericks)
MODULE_NAME Provide a name that describes the target of the project (module).  MyAdfLib
DOMAIN_NAME Internet domain name.  red.mavericks
BUSINESS_AREA Feature Business area (retail, financial, etc.)  retail/financial

Application & Project Naming

For Applications and Projects we defined the following naming rules:

Application Project
<PROJECT_NAME> + <MODULE_NAME> + App

Example: RMKMyAdfLibApp

<PROJECT_NAME> + <MODULE_NAME>

Example: RMKMyAdfLib

IMPORTANT NOTE: For both previous naming rules, decide if they should be in upper case, lower case or camel case. Once you do, stick to it!

Packages Namings

In the wizard for creating a new application, you are prompted to set up the “Application Package Prefix“. This package prefix will define the root package for the projects contained in this new application.

The default “Application Package Prefix” for new applications should be:

<DOMAIN_NAME> + . + <PROJECT_NAME>

Example: red.mavericks.rmk

 

For each new project, you will inherit the application’s root package structure. Nevertheless you should configure it to have a distinct name from other projects. With this, you are able to identify your modules/libraries. The package structure for your project should follow the next pattern:

<DOMAIN_NAME> + . + <PROJECT_NAME> + . + <MODULE_NAME>

Example: red.mavericks.rmk.my.adf.lib

Business Components Naming

For this topic, we will provide our proposed package structure and file naming rules for Business Components.

IMPORTANT NOTE: Files should be named in camel case.

Packages Structure

For Business Components projects, we should gather Entity Objects, View Objects, View Links and Associations under the following packages::

Type Package Description
 Entity Associations  <DOMAIN_NAME>+ . +<PROJECT_NAME>+ . +<MODULE_NAME>adfc.entity.associations  Contain entity associations
 Entity Objects  <DOMAIN_NAME>+ . +<PROJECT_NAME>+ . +<MODULE_NAME>adfc.entity.objects  Contain entity objects
 View Links  <DOMAIN_NAME>+ . +<PROJECT_NAME>+ . +<MODULE_NAME>adfc.view.links  Contain view links
 View Objects  <DOMAIN_NAME>+ . +<PROJECT_NAME>+ . +<MODULE_NAME>adfc.view.objects  Contain view objects
 Model JPX File  <DOMAIN_NAME>+ . +<PROJECT_NAME>+ . +<MODULE_NAME>adfc  Contain model JPX file

Example:

Entity Associations:  red.mavericks.rmk.my.adf.lib.adfc.entity.associations
 Entity Objects:  red.mavericks.rmk.my.adf.lib.adfc.entity.objects
 View Links:  red.mavericks.rmk.my.adf.lib.adfc.view.links
 View Objects:  red.mavericks.rmk.my.adf.lib.adfc.view.objects
 Model’s JPX File:  red.mavericks.rmk.my.adf.lib.adfc

File Naming

For each Business Component type, you should provide the following prefixes:

File Type Suffix Example
 Entity Associations  Assoc  SomeNameAssoc
 Entity Objects  EO  SomeNameEO
 View Links  VL  SomeNameVL
 View Objects  VO  SomeNameVO
 List Of Values  LOV SomeNameLOV
 Model JPX File  Equal to project’s name

View Link File Naming

View Link names should be self-explanatory so we can easily identify their purpose. Based on this we defined the following pattern::

<ViewObjectSourceName> + <ViewObjectDestinationName> + VL

Example: EmployeeEmployeeBranchVL

Application Modules

You may have multiple “Application Modules” in your application. For this case we should be able to identify their purpose as well as their business area target. Based on this we followed the next pattern:

<PROJECT_NAME> + <MODULE_NAME> + AM

Example: RMKMyAdfLibAM

End of Part I – Next episodes…

In my next post I will talk about:

  • Model & View Controller Projects

Cheers,

Pedro Gabriel

@PedrohnGabriel

Post image by Tim Green

This is a cross post with Link Consulting, for which Pedro currently works. If you need any help regarding Oracle Middleware projects, visit http://www.linkconsulting.com and drop them a line

The Great Migration

ADF Applications – Migration from 12.1.3 to 12.2.1

Hi all and welcome to a new article on Red Mavericks!

This article will present some problems and respective solutions in order to migrate ADF applications from 12.1.3 to 12.2.1. In this case, we used an example application that consists in a framework with several ADF applications and dependencies between them. In the current version (12.1.3), the framework works without issues.

ADF 12.2.1 comes with several corrections of customer-reported and internal (unpublished) errors, along with a new features that can be useful when developing applications:

  • Responsive Layout (Masonry Layout, af:matchMediaBehavior)
  • Visualization components (NBox, new charts and enhancements)
  • ADF Business Components (Creating RESTfull Web Services with Application Modules)

For more information about the changes in the ADF 12.2.1, click here to visit oracle documentation.

For clarify any misleading concept, I will assume the following meanings in this document:

  • Application: Group of ADF applications
  • ADF application: Group of ADF project
  • ADF project: Single ADF project

 

JDeveloper wizard migration

In order to do the migration to the new ADF version, we used the JDeveloper 12.2.1 to open all ADF projects and followed the steps in the migration wizard:

MigrationsStep1

MigrationsStep2

MigrationsStep3

Repeat this steps for every ADF projects in your application.

In this process, we did the initial migration required by the JDeveloper with success in all projects.

Advice – Debug Problems

In my migration case, I had several problems with ADF projects that contains declarative components.

In complex ADF applications with multiple dependencies is hard to know what is going on. So my advice is to try to start with simple ADF projects, with fewer dependencies, and then move on to the more complex ones. If there are declarative components that you can insert into a test ADF application to try them out, do it, and see if you can run the test or if there is a problem with it.

Validate, Update and Add ADF projects missing dependencies

For each ADF project you migrate to the new version,  check the libraries in the ADF project properties:

  1. Right click on the ADF project and select “Project Properties…” (our double click over the ADF project)projectDependenciesStep1
  2. Check all the libraries tabs, including Facelets Tag Libraries, JSP Tag Libraries and Libraries and Classpath:projectDependenciesStep3
  3. Sometimes JDeveloper doesn’t correctly migrate all libraries to the new versions. In this case, you need to remove the faulty libraries and add them manually.projectDependenciesStep4

Another aspect to take a quick look is the ADF Model projects. Sometimes during the ADF project migration, the ADF generates ViewController files in the Model project. My advice is to delete this new files using the window explorer because they can be a source of problems when trying to run your ADF application (refresh the application in JDeveloper after removing the files).

ADFModelStep1

ADFModelStep2

Also update the BPM, UCM and others libraries you have inside your ADF projects. To do this copy the libraries you need from your <oracle_home>/oracle_commom/modules, where <oracle_home> is the directory home where your jdeveloper 12.2.1 was installed.

BPM_UCM_libs

 

Then you have to check and update (in case the library has a different name) any of this libraries decencies inside your project properties.

Clean ADF projects before compile and deploy

In order to certify all the ADF project will compile using the new configurations, I recommend you to do the following steps:

  1. For each ADF project, go to “Build” menu and select “Clean All

projectClean

  1. You can also delete any existing compiled code like .jar, .war, … Use file explorer for this.

jarsWarsClean

Classes not found errors

  1. application.ModuleException: java.lang.ClassNotFoundException: oracle.adfinternal.view.faces.facelets.rich.IncludeHandler and oracle.adf.view.faces.bi.webapp.GraphServlet

If you are stuck with this exception and already done all recommended steps in Validate, Update and Add ADF projects missing dependencies, try to add a new empty page to your adfc-config.xml (you can remove it after). This will automatically add some libraries in the project properties. In my case it adds the “ADF DVT Core Runtime”, “Oracle BI Graph” and correct some others dependencies if it’s the case.

 

  1. application.ModuleException: java.lang.ClassNotFoundException: oracle.dss.rules.ComponentTypeConverter

This typically is associated with ADF projects that contain declarative components. I usually leave this one to solve in the end, because it is more complex to find the problem.

First thing I like to do is cleaning up the dependencies and add new ones that are used when we created a new declarative components ADF project. To guide you, try to remove the dependencies that aren’t in the following list and add the ones that your project is missing:

  1. In project->properties->Libraries and Classpath:declarativeComponents1
  2. In project->properties->JSP Tag Libraries:declarativeComponents2
  3. In project->properties->Facelets Tag Libraries:declarativeComponents3

If this doesn’t solve your problem, let’s try another approach. Before this, make a quick backup of your project so if anything goes wrong you can rollback and without losing your application.

First thing, close the declarative components ADF application from JDeveloper. You need to do this because you will change the .jpr ADF project file.

Search in your project for the tag “<hash>” followed by “<value n=”displayName” v=”WEB-INF/lib”/>”. In my declarative component, I solved the problem removing a lot of .jars that are referred here:

    1. Not working:
<hash>
     <value n="displayName" v="WEB-INF/lib"/>
     <hash n="filters">
        <list n="rules">
           <hash>
              <value n="pattern" v="xml-apis-ext.jar"/>
              <value n="type" v="1"/>
           </hash>
           <hash>
              <value n="pattern" v="prefuse.jar"/>
              <value n="type" v="1"/>
           </hash>
           <hash>
              <value n="pattern" v="dvt-utils.jar"/>
              <value n="type" v="1"/>
           </hash>
           <hash>
              <value n="pattern" v="dvt-shared-js.jar"/>
              <value n="type" v="1"/>
           </hash>
           <hash>
              <value n="pattern" v="dvt-facesbindings.jar"/>
              <value n="type" v="1"/>
           </hash>
           <hash>
              <value n="pattern" v="dvt-databindings.jar"/>
              <value n="type" v="1"/>
           </hash>
           <hash>
              <value n="pattern" v="dvt-basemaps.jar"/>
              <value n="type" v="1"/>
           </hash>
           <hash>
              <value n="pattern" v="batik-xml.jar"/>
              <value n="type" v="1"/>
           </hash>
          (…)
           <hash>
              <value n="pattern" v="jarUtilities.jar"/>
              <value n="type" v="1"/>
           </hash>
           <hash>
              <value n="pattern" v="com.bea.core.apache.commons.collections_1.0.0.0_3-2.jar"/>
              <value n="type" v="1"/>
           </hash>
           <hash>
              <value n="pattern" v="**"/>
              <value n="type" v="0"/>
           </hash>
        </list>
     </hash>
     <value n="internalName" v="libraries"/>
     <list n="selectedLibraries">
        <string v="ADF Faces Runtime 11"/>
        <string v="ADF DVT Faces Runtime"/>
     </list>
     <value n="targetWithinJar" v="WEB-INF/lib"/>
     <value n="type" v="3"/>
  </hash>
    1. Working:
<hash>
     <value n="displayName" v="WEB-INF/lib"/>
     <hash n="filters">
        <list n="rules">
           <hash>
              <value n="pattern" v="**"/>
              <value n="type" v="0"/>
           </hash>
        </list>
     </hash>
     <value n="internalName" v="libraries"/>
     <value n="targetWithinJar" v="WEB-INF/lib"/>
     <value n="type" v="3"/>
     <list n="unselectedLibraries">
        <string v="JarUtilities.jar"/>
        <string v="AdfLibResourceBundles.jar"/>
     </list>
 </hash>

Compile and Run

Now you can compile all ADF projects and deploy them to the WebLogic server. Don’t forget to see for each ADF project if the deploy ends successfully.

projectCompileStatus

 

Conclusion

Sometimes the ADF applications migration is not a simple button press, so when you are thinking of migrate our ADF application take in consideration that it is possible to lose some time to make all your code working in a new ADF version. However, I hope that reading this document could help you and speed up any problem situation you face in this process.

Keep checking out Red Mavericks for additional tips of Oracle Middleware technology

Cheers,
Pedro Curto

(this article is also published at Link Consulting’s website)

Post image by Steve Corey

Error in JDeveloper 12.2.1 - OSB project with XQuery changes to SOA project

Error in JDeveloper 12.2.1 – OSB project with XQuery changes to SOA project

Hi all,

After having performed a quick dive into JDeveloper 12.2.1, I came across a quite interesting feature. OSB projects started to get converted to SOA projects! Being clueless about the reason for this strange phenomenon, I conducted a quick investigation and concluded it was due to adding XQuery transformations to the project. Below are my findings and how to go around this problem if you had the misfortune of coming across it as well.

Symptoms

While working on an OSB project in Jdeveloper 12.2.1, after adding an XQuery transformation, JDeveloper changes it to a SOA project. The project structure will change and an error will be produced by Jdeveloper when completing the XQuery creation. This will occur also when importing an OSB project that contains XQuery tranformations in Jdeveloper 12.2.1. Basically, as long as there is an XQuery file in the project, it will be converted to a SOA project. When trying to deploy the project, Jdeveloper will open the Wizard for SOA project deployment, which will fail, because we have in fact an OSB project.

Adding an XQuery file to the project

Below is an example of what happens when adding an XQuery file to an existing OSB Project.

Sample OSB project before adding XQuery

Sample OSB project before adding XQuery

 

Sample OSB project after adding XQuery

Sample OSB project after adding XQuery

Meanwhile, in the JDeveloper log, the below error can be seen as well:

Uncaught exception
java.lang.NullPointerException
at oracle.tip.tools.ide.fabric.addin.SCAProjectConfigurator.configSCAProject(SCAProjectConfigurator.java:216)
at oracle.tip.tools.ide.fabric.addin.SCAProjectConfigurator.configSCAProject(SCAProjectConfigurator.java:131)
at oracle.tip.tools.ide.fabric.addin.SCAProjectConfigurator.configSCAProject(SCAProjectConfigurator.java:126)
at oracle.tip.tools.ide.fabric.addin.wizard.CompositeCreator.createComposite(CompositeCreator.java:284)
at oracle.tip.tools.ide.fabric.addin.wizard.CompositeCreator.createEmptyComposite(CompositeCreator.java:202)
at oracle.tip.tools.ide.fabric.addin.SCATechnologyListener$2.run(SCATechnologyListener.java:123)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at oracle.javatools.internal.ui.EventQueueWrapper._dispatchEvent(EventQueueWrapper.java:169)
at oracle.javatools.internal.ui.EventQueueWrapper.dispatchEvent(EventQueueWrapper.java:151)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Trying to deploy the project

Let’s say we are brave enough to ignore what happened and go ahead and try to deploy the project. We will be presented with the Deployment Wizard for SOA projects, which will fail if we go through all the way, since we have an OSB project in hands. Below you can see highlighted an indication that JDeveloper is looking at the project mistakenly as a SOA project.

Trying to deploy affected OSB project

Trying to deploy affected OSB project

Solution

There is a patch to fix this problem. To retrieve it, go to Oracle Support and refer to

Doc ID 2090174.1. Be sure to shut down JDeveloper before applying the patch and also to recreate the Default Domain in your installation (if you happen to be using the Integrated Server). As for the projects already affected, the cleanest approach is to recreate them and import the old files into them. As an alternative, it’s also possible to delete all soa-related artefacts from the projects and manually editing the .jpr files to remove the line highlighted below.

<hash n="oracle.ide.model.TechnologyScopeConfiguration">
  <list n="technologyScope">
    <string v="SOA"/>
    <string v="ServiceBusTechnology"/>
    <string v="XML"/>
    <string v="XML_SCHEMA"/>
  </list>
</hash>

Applies to

JDeveloper 12.2.1.0.0, when creating XQuery files in OSB projects
JDeveloper 12.2.1.0.0 when importing OSB projects containing XQuery files

And there you go. I hope this helps you to tackle this odd problem.

 

Carlos Pona (@carlospona84)

Carlos Pona is a SOA Technical Leader at Link Consulting.

Post header image by lees bus pics

You no longer need to be a genius to do pattern matching

Tapping into life – An Introduction to Stream Analytics

Dear Readers,

Welcome to a new stream (no pun intended) on Red Mavericks articles. This time, we’ll be doing an introduction on Oracle’s new Stream Analytics.

We’ll be guiding you through this new, and very cool, product showing what it is and what it can do to leverage this largely untapped resource which is event stream analysis. In fact, streams are everywhere and are becoming more and more open and accessible. If you “wiretap” these, listen to them and understand the behavioral patterns , you can build extremely valuable applications that will help you deliver more to your customers.

It’s a whole new ball game. I hope you find this interesting.

What is Oracle Stream Analytics?

Oracle Stream Analytics (previously Oracle Stream Explorer) is, in fact, an application builder platform, focused on applications that process events coming from the most various systems, internal or external to the organization, thus enabling Business Insight information and deriving relevant data from these events.

Stream Analytics - Login Screen

Stream Analytics – Welcome to Fast Data Business Insight

It works using an Event Processing Engine to perform Fast Data Analysis over a large number of events that typically appear in a given timeframe.

It also provides a run-time platform that will allow you to run and manage the applications you built.

It’s not a new Oracle Event Processor. It uses OEP as the underlying Event Processing Engine (you can also use Apache Spark as a processing engine, if you prefer. More on this in other articles)

The real power in Oracle Stream Analytics is, curiously, in its UI. As an application builder, it went to great lengths to keep the UI really easy to use. The result is, in my view, very well achieved, with enough simplicity to allow that Business Users, provided they have a bit of technical knowledge, can actually build  applications on their own or with little help from the IT.

Concepts and Ideas

But to be able to build these applications, you must first understand the concepts and rules behind them. We’ll explain these by mixing real-life concepts and their representations on the platform (Oracle Stream Analytics). Let’s start by the main concepts…

Event

An Event is the representation of something that happened in a particular time. This is most important, as events must always be correlated with a notion of time, of when it happened.

Shape

A Shape is the data structure representation of an event. It describes the actual information structure of an event, to ensure at least a minimum of data coherence between events that represent the same occurrence type. If you have a bit of technical knowledge, try to think of the shapes as the XSD of the event.

Events that represent the same type of occurrence should use the same Shape. Events that represent different types of occurrences should use different shapes.

Stream

A Stream is a sequence of data elements (in this case Events) made available over time. These data elements have shapes that must be known before hand to allow proper processing. The easiest way to visualize a Stream is to think of a food processing plant conveyor belt transporting vegetables from one point to another inside the plant.

A Bell Pepper Stream

A Bell Pepper “Stream” – Photo by the US Department of Agriculture

As the vegetables go through the conveyor belt they will be made available at a given time at the output of the belt. This will be the point where the person or the system will collect the bell peppers and process them.

Source

A Source represents the system that is making a given stream available. Typically it represents a system that is producing its own data streams or “proxying” data streams from other systems. Stream Analytics will connect to Sources by making Connections to them.

Target

A Target is a channel to where Stream Analytics will send the result of the event processing work. A Target will connect downstream to other systems and will obey to a given Shape.

Exploration

An Exploration is Stream Analytics‘ way to process events. It allows for events to be filtered, combined and enriched with additional data, as well as allowing for event data manipulation and conversion, when suited, thus producing their own events which are the result of all of this processing.

Explorations can use other the product of other Explorations as their inputs, as well as Streams and Reference Data Tables (called simply References in Stream Analytics), which are used to enrich the Exploration outputs.

For instance, a Stream can contain the status of a given vending machine, identified by an internal vending machine ID, while its GPS coordinates are stored in a reference database table. This way, the vending machine doesn’t have to send the GPS coordinates every 5 seconds along with the status, as this information will not change frequently or by itself.

Pattern

A Pattern is, well… a pattern 🙂 a repetitive regularity that can be identified by some means.

Stream Analytics allow to create new Explorations based on given patterns such as trends over time, geospace boundary checks, Top/Bottom N matches, etc… and, if there are matches, pass these on to Targets.

Stream Analytics - Patterns Palette

Stream Analytics – Patterns Palette

Timeframe

A Timeframe defines the time window reference for a given Exploration event processing. Stream Analytics allow you to define two characteristics of the Timeframe:

  • Range – The universe of events that will be considered when making Exploration processing, for instance by using aggregate functions. In plain English, the range is used to limit the events considered calculating averages, max values or event counts (e.g: Nr of Events of type A happening in the last 30 minutes). As there can be too much events, it’s essential to have some kind of boundaries in which the analysis makes sense
    • If a sensor states that is operating below a given threshold, it’s important to know that it’s not a sporadic event that happens once a year, but something that is happening every 2 minutes in the last hour.
  • Eval. Frequency – The frequency in which the events are passed on to the Exploration. Sometimes, it’s important to collect the data from the Exploration inputs not at every milisecond, but in bigger intervals. This will stipulate the cadence at which a given exploration produces results (and thus pushes them to Targets)

Although some of these concepts may seem confusing and unclear, as we go through the next articles and use them, they’ll become second nature.

 

So that’s a wrap on this article.

On our next article, we’ll start building our example application. Be prepared to have some fun doing it. Until then…

Maverick (José Rodrigues)

Document metadata Set/Get

WebCenter Content User Interface – Get and Set Document’s Metadata

Hi all,

In my previous post about WebCenter Content User Interface I have written an overview about the available features of this new UI as well as how to start customizing it, and my experience and important milestones regarding installation. You can find my previous post here.

Today I’m going a little further and focus the attention on how to get and set document’s current properties and metadata attributes using the API available in the “WccAdfCustomization” application.

In my last post I’ve dragged-and-dropped a button to the “docInfoTabs.jsff” page that you can find inside of the “WccAdfLibrary.jar” library of the ViewController project. This is how it looks like:MyCustomButton

Now what we want is to get both document’s properties and metadata, and then set the comments for this same document when we click on the button. To do this we need to perform the following steps:

  1. Open the JDeveloper with “Default Role”. Then go to the ViewController project and create “MyCustomClass” java class. Create an action event listener method to be used by our button.MyCustomClass
  2. Assign “MyCustomClass” java class to the managed beans of “adfc-config.xml” file. From now on this class is available in the context of the “docInfoTabs.jsff” page.ManagedBean
  3. Go to your “docInfoTabs.jsff.xml” file and set the actionListener property like is shown in the next image:ActionListener
  4. Our “docInfoTabs.jsff” page is invoked inside “wccdoc.xml” bounded task flow. If you go to Managed Beans tab you can see the available classes inside it. We will take advantage of “DocInfoBean” class.WccdocTaskFlow
  5. Let’s return to our “MyCustomClass” java class and insert the following code inside “myCustomButtonAction”.
package wcc.custom.view;

import java.io.Serializable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import oracle.wcc.adf.model.Attachment;
import oracle.wcc.adf.model.Revision;
import oracle.wcc.adf.model.form.Field;
import oracle.wcc.adf.model.form.Form;
import oracle.wcc.adf.model.form.Item;
import oracle.wcc.adf.vc.DocInfoBean;
import oracle.wcc.adf.vc.DocumentOperationHelper;
import oracle.wcc.adf.vc.DynamicFormBean;

public class MyCustomClass {
    public MyCustomClass() {
        super();
    }
    
    public void myCustomButtonAction(javax.faces.event.ActionEvent p1) {
        
        //Getting document's properties
        
        //Getting the instance of 'DocInfoBean' class.
        DocInfoBean docInfoBean = (DocInfoBean)ADFUtils.getValueFromViewScope("wccDocInfoBean");
        //Getting the current revision of the selected document.
        Revision revision = docInfoBean.getRevision();
        System.out.println("Document Title:" + revision.getDDocTitle());
        System.out.println("Document Author: " + revision.getDDocAuthor());
        System.out.println("Document Last Modified Date: " + revision.getDReleaseDate());
        System.out.println("Document Status: " + revision.getLocalizedDStatus());
        System.out.println("Document Revision Number:" + revision.getDRevLabel());
        System.out.println("Document Comments: " + revision.getXComments());
        System.out.println("Document Profile: " + revision.getXIdcProfile());
        System.out.println("Document Type: " + revision.getDDocType());
        System.out.println("Document Format: " + revision.getDFormat());
        System.out.println("Document File Size: " + revision.getDFileSize());
        
        //Getting all metadata of the current revision of the selected document.
        DynamicFormBean dynamicFormBean = docInfoBean.getMetadataFormBean();
        Form form = dynamicFormBean.getForm();
        HashMap<String, Serializable> fieldValues = form.getFieldValues();
                
        Iterator iter = fieldValues.entrySet().iterator();
        while (iter.hasNext())
        {
            Map.Entry pair = (Map.Entry)iter.next();
            System.out.println(pair.getKey() + " = " + pair.getValue());
        }
        
        revision.setXComments("My Custom Comment");
        docInfoBean.setRevision(revision);
        //Set document's metadata for the current revision.
        DocumentOperationHelper.updateRevision(revision);
    }
}

6. The “getValueFromViewScope” method in my ADFUtils class look likes this:

public static Object getValueFromViewScope(String variable) {
      return AdfFacesContext.getCurrentInstance().getViewScope().get(variable);
}

7. Finally run your application and test the button.

 

Cheers,

Pedro Gabriel

@PedrohnGabriel

Post image by Cross Duck with small changes.