Sunday, March 1, 2015

ADF exam question: Identify five things that you can do with the declarative validation features

Solving exam questions can sometimes refresh your knowledge on technology. Recently fell into my hands following question:

Identify five things that you can do with the declarative validation features of ADF Business Components?

A. Define declarative validation rules at an attribute level and an entity level.
B. Define whether a validation rule is either an error or a warning.
C. Define whether the validation rule fires on the UI or business service tier.
D. Define the order of execution of validation rules.
E. Conditionally execute a validation rule based on an expression.
F. Parameterize validation messages to reference ADF Business Components control hints, such as labels.

OK. Lets solve our issue:

A. Defining declarative validation rules at attribute level and entity level is one of base features of ADF BC Model. So - answer A is correct

To define validation on entity or attribute level you should go to the Application Navigator and double-click the desired entity object. In the overview editor, click the Business Rules navigation tab, select the object for which you want to add a validation rule, and then click the Add icon.
  • To add a validation rule at the entity object level, select Entity. 
  • To add a validation rule for an attribute, expand Attributes and select the desired attribute. 

B. Define whether a validation rule is either an error or a warning - correct answer. When creating rule, you can also set in tab Failure Handling its Failure Severity, as shown below:



 

C. Define whether the validation rule fires on the UI or business service tier - this is in my opinion some unfortunately question. In ADF View (not in ADF BC layer only) of course you may define validation on UI layer. So the answer is true.

D. Define the order of execution of validation rules. Still some functionality in ADB BC is missing. One of this is the easy configuration for execution order. So the answer is false.

E. Conditionally execute a validation rule based on an expression - of course you can. To do this go to Business Rules navigation tab, select the object for which you want to add or modify a validation rule. Click Add or click on Rule to modify and in appeared popup go to Validation Execution tab.

 

F. Parameterize validation messages to reference ADF Business Components control hints, such as labels. - of course you can. Go to Failure Handling tab in Edit Validation Rule popup.

So, we have the solution. Right answers are: A, B, C, E, F.

Wednesday, February 25, 2015

ADF 12c: JBO-25152: Calling the constructor for class oracle.jbo.Key is not permitted.

What to do, when in JDeveloper 12c you encountered following error:

Exception in thread "AWT-EventQueue-0" oracle.jbo.JboException: JBO-29000: Unexpected exception caught: org.codehaus.groovy.control.MultipleCompilationErrorsException, msg=startup failed:

General error during semantic analysis: JBO-25152: Calling the constructor for class oracle.jbo.Key is not permitted.



oracle.jbo.ExprSecurityException: JBO-25152: Calling the constructor for class oracle.jbo.Key is not permitted.

    at oracle.jbo.script.InternalSecurityPolicyEnforcer.checkConstructor(InternalSecurityPolicyEnforcer.java:304)

    at oracle.jbo.script.ExprASTScanningVisitor.visitConstructorCallExpression(ExprASTScanningVisitor.java:127)

    at org.codehaus.groovy.ast.expr.ConstructorCallExpression.visit(ConstructorCallExpression.java:44)

    at org.codehaus.groovy.ast.CodeVisitorSupport.visitBinaryExpression(CodeVisitorSupport.java:144)

    at org.codehaus.groovy.ast.CodeVisitorSupport.visitDeclarationExpression(CodeVisitorSupport.java:245)

    at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitDeclarationExpression(ClassCodeVisitorSupport.java:107)

    at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:86)

    at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:69)

    at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:193)

    at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:40)

    at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:35)

    at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:163)

    at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:69)

    at org.codehaus.groovy.ast.CodeVisitorSupport.visitTryCatchFinally(CodeVisitorSupport.java:82)

    at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitTryCatchFinally(ClassCodeVisitorSupport.java:228)

    at org.codehaus.groovy.ast.stmt.TryCatchStatement.visit(TryCatchStatement.java:42)

    at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:35)

    at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:163)

    at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:69)

    at oracle.jbo.script.ExprASTScan.visit(ExprASTScan.java:97)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

    at java.lang.reflect.Method.invoke(Method.java:606)

    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSite.invoke(PojoMetaMethodSite.java:189)

    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)

    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)

    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:55)

    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)

    at org.codehaus.groovy.control.customizers.ASTTransformationCustomizer.call(ASTTransformationCustomizer.groovy:232)

    at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1036)

    at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:572)

    at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:550)

    at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:527)

    at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:279)

    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:258)

    at groovy.lang.GroovyShell.parseClass(GroovyShell.java:613)

    at groovy.lang.GroovyShell.parse(GroovyShell.java:625)

    at groovy.lang.GroovyShell.parse(GroovyShell.java:652)

    at oracle.jbo.ExprEval.parseScript(ExprEval.java:1571)

    at oracle.jbo.ExprEval.findScript(ExprEval.java:1152)

    at oracle.jbo.ExprEval.doEvaluate(ExprEval.java:1956)

    at oracle.jbo.ExprEval.doEvaluate(ExprEval.java:1928)

    at oracle.jbo.ExprEval.evaluateForRow(ExprEval.java:1647)

    at oracle.jbo.server.AttributeDefImpl.evaluateTransientExpression(AttributeDefImpl.java:2486)

    at oracle.jbo.server.ViewRowStorage.getAttributeInternal(ViewRowStorage.java:1947)

    at oracle.jbo.server.ViewRowImpl.getAttributeValue(ViewRowImpl.java:2036)

    at oracle.jbo.server.ViewRowImpl.getAttributeInternal(ViewRowImpl.java:886)

    at oracle.jbo.server.ViewRowImpl.getAttrInvokeAccessor(ViewRowImpl.java:968)

    at oracle.jbo.server.ViewRowImpl.getAttribute(ViewRowImpl.java:916)

    at oracle.jbo.uicli.binding.JUCtrlValueBinding.internalGetAttributeValueFromRow(JUCtrlValueBinding.java:1248)

    at oracle.jbo.uicli.binding.JUCtrlListBinding.getTargetRowData(JUCtrlListBinding.java:1988)

    at oracle.jbo.uicli.binding.JUCtrlListBinding.matchTargetWithLov(JUCtrlListBinding.java:2064)

    at oracle.jbo.uicli.binding.JUCtrlListBinding.findListIndexInternal(JUCtrlListBinding.java:2522)

    at oracle.jbo.uicli.binding.JUCtrlListBinding.findListIndex(JUCtrlListBinding.java:2261)

    at oracle.jbo.uicli.binding.JUCtrlListBinding.findAndUpdateSelectedIndex(JUCtrlListBinding.java:2227)

    at oracle.jbo.uicli.jui.JUComboBoxCtrlBinding.setValueAt(JUComboBoxCtrlBinding.java:546)

    at oracle.jbo.uicli.binding.JUCtrlListBinding.updateValuesFromRow(JUCtrlListBinding.java:2885)

    at oracle.jbo.uicli.jui.JUComboBoxBinding.updateValuesFromRow(JUComboBoxBinding.java:193)

    at oracle.jbo.uicli.jui.JUComboBoxCtrlBinding.updateValueToCurrentRow(JUComboBoxCtrlBinding.java:505)

    at oracle.jbo.uicli.jui.JUComboBoxCtrlBinding$1mRunnable.run(JUComboBoxCtrlBinding.java:417)

    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)

    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)

    at java.awt.EventQueue.access$200(EventQueue.java:103)

    at java.awt.EventQueue$3.run(EventQueue.java:694)

    at java.awt.EventQueue$3.run(EventQueue.java:692)

    at java.security.AccessController.doPrivileged(Native Method)

    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)

    at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)

    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)

    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)

    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)

    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)

    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)

    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)



1 error



    at oracle.jbo.ExprEval.parseScript(ExprEval.java:1594)

    at oracle.jbo.ExprEval.findScript(ExprEval.java:1152)

    at oracle.jbo.ExprEval.doEvaluate(ExprEval.java:1956)

    at oracle.jbo.ExprEval.doEvaluate(ExprEval.java:1928)

    at oracle.jbo.ExprEval.evaluateForRow(ExprEval.java:1647)

    at oracle.jbo.server.AttributeDefImpl.evaluateTransientExpression(AttributeDefImpl.java:2486)

    at oracle.jbo.server.ViewRowStorage.getAttributeInternal(ViewRowStorage.java:1947)

    at oracle.jbo.server.ViewRowImpl.getAttributeValue(ViewRowImpl.java:2036)

    at oracle.jbo.server.ViewRowImpl.getAttributeInternal(ViewRowImpl.java:886)

    at oracle.jbo.server.ViewRowImpl.getAttrInvokeAccessor(ViewRowImpl.java:968)

    at oracle.jbo.server.ViewRowImpl.getAttribute(ViewRowImpl.java:916)

    at oracle.jbo.uicli.binding.JUCtrlValueBinding.internalGetAttributeValueFromRow(JUCtrlValueBinding.java:1248)

    at oracle.jbo.uicli.binding.JUCtrlListBinding.getTargetRowData(JUCtrlListBinding.java:1988)

    at oracle.jbo.uicli.binding.JUCtrlListBinding.matchTargetWithLov(JUCtrlListBinding.java:2064)

    at oracle.jbo.uicli.binding.JUCtrlListBinding.findListIndexInternal(JUCtrlListBinding.java:2522)

    at oracle.jbo.uicli.binding.JUCtrlListBinding.findListIndex(JUCtrlListBinding.java:2261)

    at oracle.jbo.uicli.binding.JUCtrlListBinding.findAndUpdateSelectedIndex(JUCtrlListBinding.java:2227)

    at oracle.jbo.uicli.jui.JUComboBoxCtrlBinding.setValueAt(JUComboBoxCtrlBinding.java:546)

    at oracle.jbo.uicli.binding.JUCtrlListBinding.updateValuesFromRow(JUCtrlListBinding.java:2885)

    at oracle.jbo.uicli.jui.JUComboBoxBinding.updateValuesFromRow(JUComboBoxBinding.java:193)

    at oracle.jbo.uicli.jui.JUComboBoxCtrlBinding.updateValueToCurrentRow(JUComboBoxCtrlBinding.java:505)

    at oracle.jbo.uicli.jui.JUComboBoxCtrlBinding$1mRunnable.run(JUComboBoxCtrlBinding.java:417)

    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)

    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)

    at java.awt.EventQueue.access$200(EventQueue.java:103)

    at java.awt.EventQueue$3.run(EventQueue.java:694)

    at java.awt.EventQueue$3.run(EventQueue.java:692)

    at java.security.AccessController.doPrivileged(Native Method)

    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)

    at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)

    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)

    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)

    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)

    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)

    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)

    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

Caused by: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:

General error during semantic analysis: JBO-25152: Calling the constructor for class oracle.jbo.Key is not permitted.


This error occurs because of the difference between the EO.xml in ADF 11.x and  12.x.
ADF 12.x adds "trustMode" attribute to the groovy expression definition. By example:

<ViewAttribute
    Name="Ikona"
    IsUpdateable="false"
    IsSelected="false"
    IsPersistent="false"
    PrecisionRule="true"
    Type="java.lang.String"
    ColumnType="CHAR"
    AliasName="VIEW_ATTR"
    SQLType="VARCHAR"
    Passivate="true">
    <TransientExpression><![CDATA[try{
oracle.jbo.Key key2 = new oracle.jbo.Key(GrupaZainteresowanId);
if(GrupyZainteresowanLov1.findByKey(key2,1)[0]==null) return "";
else return GrupyZainteresowanLov1.findByKey(key2,1)[0].getAttribute("Ikona");
}
catch(e){
return "Blad: "+e.toString();
}]]></TransientExpression>
    <RecalcCondition
      trustMode="trusted"><![CDATA[true]]></RecalcCondition>
  </ViewAttribute>


As shown in ADF 12.1.3.0 release note:

"JDeveloper 12.1.3 and ADF has introduced a tightening security model for ADF BC Groovy expressions as a stepping stone for upcoming Oracle products. Oracle is progressively introducing this feature to reduce the burden on customers.
For any new ADF application, customers must set via the property inspector trustMode="true" for any ADF BC attributes or similar using a Groovy expression. Otherwise at runtime JBO-25152 will be raised.
For customers porting applications from previous releases of JDeveloper the trustMode will be set to true for existing Groovy expressions, though any new expressions still require developers explicitly set the trustMode."

Just as it is written the groovy expressions are executed by default in untrusted mode.
So you should change trustMode="untrusted"  to "trusted"(in xml or through Property Inspector).

If you invoke java method from expression then you can also use @AllowUntrustedScriptAccess annotation on such method.

Tuesday, January 6, 2015

Error 'java.lang.ClassNotFoundException: javax.faces.context.FacesContextFactory' when debugging ADF Faces application

Described error can be observer when you try to run ADF application on built-in Weblogic. Error message can look:

2015-01-02 16:28:33 CET> <Error> <Deployer> <BEA-149265> <Failure occurred in the execution of deployment request with ID '1420212508286' for task '0'. Error is: 'java.lang.ClassNotFoundException: javax.faces.context.FacesContextFactory'
java.lang.ClassNotFoundException: javax.faces.context.FacesContextFactory
    at weblogic.utils.classloaders.GenericClassLoader.findLocalClass(GenericClassLoader.java:297)
    at weblogic.utils.classloaders.GenericClassLoader.findClass(GenericClassLoader.java:270)
    at weblogic.utils.classloaders.ChangeAwareClassLoader.findClass(ChangeAwareClassLoader.java:64)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    Truncated. see log file for complete stacktrace
Caused By: java.lang.ClassNotFoundException: javax.faces.context.FacesContextFactory
    at weblogic.utils.classloaders.GenericClassLoader.findLocalClass(GenericClassLoader.java:297)
    at weblogic.utils.classloaders.GenericClassLoader.findClass(GenericClassLoader.java:270)
    at weblogic.utils.classloaders.ChangeAwareClassLoader.findClass(ChangeAwareClassLoader.java:64)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    Truncated. see log file for complete stacktrace
>

As you can suppose cause of this issue does not lie in lack of JSF libraries. The main cause is your inattention. Sorry:)

The error occurs when in Model project you put any part of ViewController descriptors, especially web.xml. This can occur when by example you mistakenly change the technology scope of Model project.

To recover this error simply remove all undesired files from Model project.

Sunday, November 2, 2014

BPM getLastPerformer() issue (continued): Error when evaluating workflow service XPath extension function, ORABPEL-30043

Long time ago I described my problem with getLastPerformer() xpatch function. Content of this artice you can find here: http://my-java-planet.blogspot.com/2012/11/bpm-getlastperformer-issue-error-in.html

Yesterday I encountered this problem once again. And again, I forget cause of this issue. After some googling, I found my own blog post regarding getLastPerformer().

Fortunatelly, today I know, that you can't use bpm.getLastPerformer() outside of Human Taskflow task (the only place I've seen getLastPerformer() method invoked successfully is from inside the human task's assignment tab), so I can share this knowledge. And this is the whole mystery:)

Friday, June 6, 2014

ADF how to: errors related to bind variables

I accidentally had found an old manual relating to errors related to "bind variables", so I decided share its fragments:

JBO-27122: SQL error during statement preparation

You need to ensure that the list of named bind variables that you reference in your SQL statement matches the list of named bind variables that you've defined on the Bind Variables page of the View Object Editor. Failure to have these two agree correctly can result in one of the following two errors at runtime.
If you use a named bind variable in your SQL statement but have not defined it, you'll receive an error like this:
(oracle.jbo.SQLStmtException) JBO-27122: SQL error during statement preparation.
## Detail 0 ##
(java.sql.SQLException) Missing IN or OUT parameter at index:: 1
 On the other hand, if you have defined a named bind variable, but then forgotten to reference it or mistyped its name in the SQL, then you will see an error like this:
oracle.jbo.SQLStmtException: JBO-27122: SQL error during statement preparation.
## Detail 0 ##
java.sql.SQLException: Attempt to set a parameter name that does not occur in the SQL: LowUserId

Valid query returns no rows

If you do not supply a default value for your named bind variable, it defaults to the NULL value at runtime. This means that if you have a WHERE clause like:
USER_ID = :TheUserId

and you do not provide a default value for the TheUserId bind variable, it will default to having a NULL value and cause the query to return no rows. Where it makes sense for your application, you can leverage SQL functions like NVL(), CASE, DECODE(), or others to handle the situation as you require. In fact, the UserList view object uses a WHERE clause fragment like:
upper(FIRST_NAME) like upper(:TheName)||'%'
so that the query will match any name if the value of :TheName is null.

Error ORA-00904 when adding a Named Bind Variable at Runtime

Assume following situation. Using setNamedWhereClauseParam() method you created code:
ViewObject vo = am.findViewObject("EmployeeList");
vo.setNamedWhereClauseParam("TheName","Jon%");
vo.setNamedWhereClauseParam("HighUserId", new Number(100));
vo.executeQuery();

However, if you run this test program, you actually get a runtime error like this:
oracle.jbo.SQLStmtException: JBO-27122: SQL error during statement preparation.
Statement: 
SELECT * FROM (select USER_ID, EMAIL, FIRST_NAME, LAST_NAME
from EMPLOYEES 
where (upper(FIRST_NAME) like upper(:TheName)||'%'
   or  upper(LAST_NAME)  like upper(:TheName)||'%')
  and USER_ID between :LowUserId and :HighUserId
order by EMAIL) QRSLT  WHERE (user_role = :TheUserRole)
## Detail 0 ##
java.sql.SQLException: ORA-00904: "USER_ROLE": invalid identifier
The root cause of this error is the mechanism that ADF view objects use by default to apply additional runtime WHERE clauses on top of read-only queries.

If you dynamically add an additional WHERE clause at runtime to a read-only view object, its query gets nested into an inline view before applying the additional WHERE clause. For example, suppose your query was defined as:
select USER_ID, EMAIL, FIRST_NAME, LAST_NAME
from EMPLOYEES 
where (upper(FIRST_NAME) like upper(:TheName)||'%'
   or  upper(LAST_NAME)  like upper(:TheName)||'%')
  and USER_ID between :LowUserId and :HighUserId
order by EMAIL 

At runtime, when you set an additional WHERE clause like user_role = :TheUserRole, the framework nests the original query into an inline view like this:
SELECT * FROM(
select USER_ID, EMAIL, FIRST_NAME, LAST_NAME
from EMPLOYEES 
where (upper(FIRST_NAME) like upper(:TheName)||'%'
   or  upper(LAST_NAME)  like upper(:TheName)||'%')
  and USER_ID between :LowUserId and :HighUserId
order by EMAIL) QRSLT
and then adds the dynamic WHERE clause predicate at the end, so that the final query the database sees is:
SELECT * FROM(
select USER_ID, EMAIL, FIRST_NAME, LAST_NAME
from EMPLOYEES 
where (upper(FIRST_NAME) like upper(:TheName)||'%'
   or  upper(LAST_NAME)  like upper(:TheName)||'%')
  and USER_ID between :LowUserId and :HighUserId
order by EMAIL) QRSLT
WHERE user_role = :TheUserRole
This query "wrapping" is necessary in the general case since the original query could be arbitrarily complex. In those cases, simply "gluing" the additional runtime onto the end of the query text could produce unexpected results. By nesting the original query verbatim into an inline view, the view object guarantees that your additional WHERE clause is correctly used to filter the results of the original query, regardless of how complex it is. The downside that you're seeing here with the ORA-00904 error is that the dynamically added WHERE clause can refer only to columns that have been selected in the original query.