Wednesday, November 5, 2014

Oracle ADF - Performance Testing Tools

Following post list some tools that can be used for Oracle ADF application performance testing, along with other available tools.
  
JMeter

JMeter is required in order to make multiple calls to the application. A test plan should be created which specifies the steps to be replicated by the JMeter
Test plan configured for sample application is attached here

Following are the changes that are required to be done in order to use this test plan with sample application. 

1)  Open the test plan file in JMeter.

2)  Replace the <Server Name or IP> and <Port Number> field corresponding to five HTTP requests that exist in the test plan as shown below, with the details of the server where  ADF application is running. This is not required if the application is running on local host


3) Now click on Thread Group – Sample App in order to specify the number of users, loop count per user and the ramp-up time in which the threads should start sending the request to the application.



JDeveloper Memory Profiler

JDeveloper memory profiler is required in order to see the number of objects that are getting created in each request and the number of objects that are getting garbage collected. It also displays the number of objects and their size that’s left in the memory after application finishes the requests.


Following are the steps to use JDeveloper memory profiler.

1)  Open JDeveloper.
2)  Browse the application that is to be analyzed.
3)  Start the memory profiler from the JDeveloper Run menu as shown below.




4)  This will start/restart the integrated weblogic server. Once the server is up, the application will start at local host and JDeveloper weblogic port.
5)  In order to access the application, either we can directly hit the application from browser or we can use JMeter to hit the application.
6)  Following is a sample report generated using JDeveloper which is showing the total number of instances created and total number of instance collected during garbage collection.


JVisualVM

JVisualVM is required to create the heap dump of the JVM on which the ADF application is deployed and running. The heap dump file generated using JVisualVM can be used to analyze the memory usage, objects count and any suspect for memory leak.

Following are the steps to create the heap dump using JVisualVM

1)  Open JVisualVM from the JDK directory like 

…/jdk160_29/bin/jvisualvm.exe

2)  Select the weblogic server instance on which ADF application is running.


3)  Now open the JMeter and click start button to initiate the requests to <ADF application>
4)  Analyze the heap allocation and garbage collection activities in JVisualVM.


5)  Once the threads started from JMeter complete, click on Heap Dump button to generate the heap dump file.


Eclipse Memory Analyzer

Eclipse memory analyzer is required to analyze the heap dump created using JVisualVM. It helps in identifying the possible issues that might have been reported while running the application.

Following are the steps required to analyze the heap dumps file using Eclipse Memory Analyzer

1)  Start the eclipse memory analyzer standalone application or eclipse IDE if it has eclipse memory analyzer plug-in installed.
2)  Browse for the heap dump file created above using JVisualVM.
3)  Click finish when prompted to generate the Leak suspect report.


4)  Click on various other options provided in the IDE to analyze the dump file.


Sample Report

The below screenshot shows the problem suspects in the application.


Wednesday, August 6, 2014

Oracle ADF TreeTable CRUD Operations

Following post describes the CRUD operation on ADF TreeTable component. In order to create a TreeTable component on the page, drag and drop the collection from data control on to the page as treeTable.

Following is the code for showing department's name as tree and its employees as table under selected tree node.

<af:treeTable value="#{bindings.DepartmentsView1.treeModel}"  var="node" columnStretching ="last" selectionListener="#{bindings.DepartmentsView1.treeModel.makeCurrent}" rowSelection="single" id="tt1" partialTriggers="::cb2 ::cb4">
            <f:facet name="nodeStamp">
              <af:column id="c1">
                <af:outputText value="#{node.DepartmentName}" id="ot2"/>
              </af:column>
            </f:facet>
            <f:facet name="pathStamp">
              <af:outputText value="#{node}" id="ot1"/>
            </f:facet>
            <af:column id="c7" headerText="EmployeeId">
              <af:inputText value="#{node.EmployeeId}" id="ot6"/>
            </af:column>
            <af:column id="c8" headerText="FirstName">
              <af:inputText value="#{node.FirstName}" id="ot7"/>
            </af:column>
            <af:column id="c9" headerText="LastName">
              <af:inputText id="it1" value="#{node.LastName}"/>
            </af:column>
            <af:column id="c2" headerText="Email">
              <af:inputText id="it2" value="#{node.Email}"/>
            </af:column>
            <af:column id="c3" headerText="HireDate">
              <af:inputText id="it3" value="#{node.HireDate}"/>
            </af:column>
            <af:column id="c4" headerText="JobId">
              <af:inputText id="it4" value="#{node.JobId}"/>
            </af:column>
          </af:treeTable>

Now add buttons on the page. One for Adding employee under a department, one for deleting the selected employee and one "Commit" button for saving the changes in database.

Create actionListener for "Add Employee" button and write following code in the managed bean:

    public void actionCreate(ActionEvent actionEvent) {
        try {
            //tt1 is table id in jspx page. Instead of this, table binding can also be used to access table.
            RichTreeTable richTreeTable = (RichTreeTable)actionEvent.getComponent().getParent().findComponent("tt1");
            RowIterator ri = getSelectedNodeRowIterator(richTreeTable);
            Key selectedNodeKey = getSelectedNodeRowKey(richTreeTable);
            Row[] found = ri.findByKey(selectedNodeKey, 1);
            if (found != null) {
                Row foundRow = found[0];
                String nodeDefname = foundRow.getStructureDef().getDefFullName();
                String deptViewDefName = "com.model.DepartmentsView";
                String empViewDefName = "com.model.EmployeesView";
                if (nodeDefname.equals(deptViewDefName)) {
                   //EmployeesView is name of Employee View object.
                    RowSet parents = (RowSet)foundRow.getAttribute("EmployeesView");
                    Row childrow = parents.createRow();
                    parents.insertRow(childrow);
                } else {
                    RowSet parents = (RowSet)foundRow.getAttribute("EmployeesView");
                    Row childrow = parents.createRow();
                    childrow.setAttribute("DepartmentId", foundRow.getAttribute("DepartmentId"));
                    parents.insertRow(childrow);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Key getSelectedNodeRowKey(RichTreeTable richTreeTable) {
        if (richTreeTable != null &&
            richTreeTable.getSelectedRowKeys() != null) {
            for (Object opaqueFacesKey : richTreeTable.getSelectedRowKeys()) {
                richTreeTable.setRowKey(opaqueFacesKey);
                return ((JUCtrlHierNodeBinding)richTreeTable.getRowData()).getRowKey();
            }
        }
        return null;
    }

    public RowIterator getSelectedNodeRowIterator(RichTreeTable richTreeTable) {
        if (richTreeTable != null &&
            richTreeTable.getSelectedRowKeys() != null) {
            for (Object opaqueFacesKey : richTreeTable.getSelectedRowKeys()) {
                richTreeTable.setRowKey(opaqueFacesKey);
                return ((JUCtrlHierNodeBinding)richTreeTable.getRowData()).getRowIterator();
            }
        }
        return null;
    }

For "Delete Employee" button actionListoner, write following code:

    public void actionDelete(ActionEvent actionEvent) {
        try {
            RichTreeTable richTreeTable = (RichTreeTable)actionEvent.getComponent().getParent().findComponent("tt1");
            RowIterator ri = getSelectedNodeRowIterator(richTreeTable);
            Key selectedNodeKey = getSelectedNodeRowKey(richTreeTable);
            Row[] found = ri.findByKey(selectedNodeKey, 1);
            if (found != null) {
                for (Row row : found) {
                    row.remove();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Commit button can be directly dragged and dropped on the page from data control.

Wednesday, July 9, 2014

Oracle ADF WebSerice - XMLGregorianCalendar to Util DateTime

In our Oracle ADF applicaiton, if we are consuming a web service by creating JAX-WS proxy client and exposing its methods as data control using our facade java class, then the xsd:dateTime attributes in web service input will be shown as collection attribute in data control palette and will be created as XMLGregorianCalendar object in generated java class getter's and setter's, as shown below




In order use the attribute as original date time, we can convert that to java util date, using the steps mentioned below:

1) Create a jax-ws-jaxb-customization xml file having mapping of xsd types to java types:

<?xml version="1.0" encoding="UTF-8"?>
<jaxws:bindings node="wsdl:definitions/wsdl:types/xsd:schema"
                xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
                xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
                xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                wsdlLocation="http://localhost:9001/soa-infra/services/default/SyncService/syncprocess_client_ep?WSDL">
  <jaxb:globalBindings>
    <jaxb:serializable/>
    <jaxb:javaType name="java.util.Date" xmlType="xsd:dateTime"/>
    <jaxb:javaType name="java.util.Date" xmlType="xsd:date"/>
  </jaxb:globalBindings>
</jaxws:bindings>

2) Add the above customization file in the web service property wizard, as shown in below screen shot:
Open the properties window
Click on Add File and select the customization file created above.
3) Click "Ok" to close the wizards.

4) The web service proxy files will get regenerated. Also the XMLGregorianCalendar objects in the request or response java files, will get converted into java.util.date


4) Under the web service files, new adapter files will get created based on the number of mappings added in the customization file. The files can be modified to format the date time as per required format, as shown in the code below:



Code::
public class Adapter1 extends XmlAdapter<String, Date>
{
    private String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS";

    public Date unmarshal(String value) throws ParseException {
        return new SimpleDateFormat(pattern).parse(value);
    }

    public String marshal(Date value) {
        String dateAsString = "";
        if (value == null) {
            return null;
        }
        try{
            SimpleDateFormat format = new SimpleDateFormat(pattern);
            dateAsString = format.format(value);
        }catch(Exception e){
        //Handle
    }
        return dateAsString;
    }
}


5) Recreate the data control based on facade class. The attributes will now be shown as simple attributes:
Note: Each time the proxy service is regenerated, the Adapter files will get regenerated as well. So we need to keep the backup of adapter file code (if the default code was modified) before regenerating the proxy and update it again after regeneration.

Saturday, February 1, 2014

Oracle ADF WebService LoadGrammer Error

Following error might be encountered while regenerating web service JAX-WS proxy either by directly right clicking on service and selecting "Regenerate WebService Proxy" or by opening the service properties windows and clicking "Ok".

oracle.jdeveloper.webservices.tools.WsdlValidationException: Error creating model from wsdl "http://localhost:9001/soa-infra/services/default/SyncService/syncprocess_client_ep?WSDL": org.apache.xerces.impl.xs.XMLSchemaLoader.loadGrammar([Lorg/apache/xerces/xni/parser/XMLInputSource;)V
    at oracle.jdevimpl.webservices.tools.wsa.WsaAdaptor.newWsdlValidationException(WsaAdaptor.java:825)
    at oracle.jdevimpl.webservices.tools.wsa.WsaAdaptor.createProxy(WsaAdaptor.java:295)
    at oracle.jdeveloper.webservices.tools.WebServiceTools.createProxy(WebServiceTools.java:293)
    at ....
Caused by: java.lang.NoSuchMethodError: org.apache.xerces.impl.xs.XMLSchemaLoader.loadGrammar([Lorg/apache/xerces/xni/parser/XMLInputSource;)V
    at org.apache.xerces.jaxp.validation.XMLSchemaFactory.newSchema(Unknown Source)
    at com.sun.tools.xjc.reader.internalizer.DOMForest.weakSchemaCorrectnessCheck(DOMForest.java:487)
    at com.sun.tools.xjc.api.impl.s2j.SchemaCompilerImpl.bind(SchemaCompilerImpl.java:227)
    at com.sun.tools.xjc.api.impl.s2j.SchemaCompilerImpl.bind(SchemaCompilerImpl.java:85)
    at ...

An unofficial solution to above issue is to remove "ADF Model Runtime" and "ADF Model Generic Runtime" libraries from the project properties (the project in which proxy is getting generated).


After removing the libraries, the proxy should get regenerated by using either of the above two ways,

Monday, October 28, 2013

Oracle ADF Exception Handling Methods

1) Binding Layer : At binding layer, the exceptions can be either be handled for all the pages included in dataBinding.cpx file or for an individual page.

Handle exception of all the pages:

To handle binding layer exception for all the pages, extend the DCErrorHandlerImpl class and override the reportException method. Register this custom error handler class in DataBinding.cpx file under Application tag as follows:

ErrorHandlerClass="com.exception.handler.CustomErrorHandler "


public class CustomErrorHandler extends DCErrorHandlerImpl {

    private String[][] overrideExceptions = {{"oracle.jbo.JboException", "CUST_001","This is custom JBO exception message."}};

    public CustomErrorHandler (boolean setToThrow) {
        super(setToThrow);
    }

    public CustomErrorHandler () {
        this(true);
    }

    @Override
    public void reportException(DCBindingContainer bc, Exception ex) {
        BindingContext ctx = bc.getBindingContext();
        String err_code = null;
        if (ex instanceof TxnValException) {
            // Handle JBO-27023
            // Display exception message
        }
        if (ex instanceof oracle.jbo.DMLException) {
            // Handle JBO-26061
            // Display exception message        } else if (ex instanceof oracle.jbo.JboException) {
           // Display exception message
        } else {
            super.reportException(bc, ex);
        }
    }

    @Override
    protected boolean skipException(Exception ex) {
        // Override this method to skip any exception.
        return super.skipException(ex);
    }

    @Override
    public String getDisplayMessage(BindingContext context,
                                    Exception exception) {

        //Override this method to return custom error message
        return message;
    }
}

Handle exception of individual page:

To handle exception for a single page, create a CustomFacesPageLifeCycle class that extends FacesPageLifecycle. Now override the reportErrors method:

public void reportErrors(PageLifecycleContext pageLifecycleContext) {
        DCBindingContainer bc = (DCBindingContainer)pageLifecycleContext.getBindingContainer();
        if (bc != null) {
            ControllerContext context = ControllerContext.getInstance();
            ViewPortContext currentRootViewPort = context.getCurrentRootViewPort();
            Exception exceptionData = currentRootViewPort.getExceptionData();
            if (currentRootViewPort.isExceptionPresent()) {
                currentRootViewPort.clearException();

                FacesContext facesContext = FacesContext.getCurrentInstance();
                facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, exceptionData.getMessage(), null));
            }
}

Open the page definition file of the page for which exception is to be handled and add ControllerClass="com.exception.CustomFacesPageLifeCycle" in the pageDefinition tag.

2) Controller Layer : To handle exception at controller layer, there are following two ways:

Handle exception using task flow exception handler

The exceptions inside task flow, which are thrown by the method call activity used inside it, can be handled by marking bean method/jspx page as exception handler.

Handle exception using custom exception handler

If the exception is not handled by taskflow exception handler, then create custom exception handler as follow.

Create a CustomExceptionHandler class by extending  ExceptionHandler class and define the exception handling logic in handleException method.

public void handleException(FacesContext facesContext, Throwable throwable,
                                PhaseId phaseId) throws Throwable {
        String error_message;
        error_message = throwable.getMessage();


        // Handle the exception if required, Otherwise re-throw by using "throw throwable;"
}

In order to register this custom exception handler, create a folder named "services" inside .adf\META-INF and inside that folder create a text file with name "oracle.adf.view.rich.context.ExceptionHandler" having content as the path of CustomExceptionHandler file with package structure, like:

com.exception.handler.CustomExceptionHandler

3) Application Layer: In order to handle the exception at master application level, which is having multiple number of projects, create a custom application life cycle and register our custom exception handler.

First create custom exception handler class, CustomErrorHandler, that extends DCErrorHandlerImpl and override the reportException method. This is described in the post above.

Now create CustomFacesLifeCycle class that extends FacesPageLifecycle class and override prepareModel method:

    public void prepareModel(LifecycleContext lifecycleContext) {
        if (!(lifecycleContext.getBindingContext().getErrorHandler() instanceof
              CustomErrorHandler)) {
            lifecycleContext.getBindingContext().setErrorHandler(new CustomErrorHandler(true));
        }
        super.prepareModel(lifecycleContext);

    }

Now create a CustomADFPhaseListener class that extends ADFPhaseListener class and Override the createPageLifecycle method to return a new custom lifecycle as follows .

public class CustomADFPhaseListener extends ADFPhaseListener {
  protected PageLifecycle createPageLifecycle() {
    return new CustomFacesLifeCycle();
  }
}

Now register the CustomADFPhaseListener in the faces-config file, under Life Cycle tab.

Friday, February 1, 2013

Oracle ADF Read Images From Database Dynamically

Following is one of the way of displaying images from database dynamically and show on ADF page without using HTTP Servlet. The advantage of this method is that we don't require to create DB connection, create and execute query, which are required if we use servlet for displaying the images.

Following are the steps:

1) Create View Object : First create a view object based on table having images as blob column. The below viewObject is based on entityObject but should be created as read only without entity object.


2) Create Managed/Backing Bean: Create a bean file and write following code to read the blob content of image as byte array and convert that to encoded string. This string content will be used to display the image on page.

    public String getImageArray() {
            BlobDomain attribute = (BlobDomain)ADFUtils.evaluateEL("#{row.bindings.Image.inputValue}");
            try {
                byte[]   bytesEncoded = Base64.encode(attribute .getBytes(1L,(int)attribute.getLength()));
                imageArray= new String(bytesEncoded);
            } catch (Exception e) {
                e.printStackTrace();
            }
        return imageArray;
    }


The above code is using EL as #{row.bindings.Image.inputValue} since the data is shown under table.

3) Create Image Component: Drop the image attribute from datacontrol onto jspx page as outputText component just to create the binding of the image attribute. Alternatively we can go to binding tab of the page and add image attribute binding. Now add image component as follow:

           <af:image  source="data:image/png;base64,#{bean.imageArray}"
                          shortDesc="#{row.bindings.ImageName.inputValue}"
                          id="it1">
            </af:image>

4) Final Page: The above method will display the images as follow



Thursday, December 6, 2012

Oracle ADF Ready To Use Sample Codes

*********Add Faces Message*********
FacesContext facesContext = FacesContext.getCurrentInstance();

facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, rb.getString("reqEmail"),null));

*********To Show Rich Popup*********
private RichPopup richPopup;
UIComponent source = (UIComponent)actionEvent.getSource();
String alignId = source.getClientId(facesContext);
RichPopup.PopupHints hints = new RichPopup.PopupHints();
hints.add(RichPopup.PopupHints.HintTypes.HINT_ALIGN_ID, source).add(RichPopup.PopupHints.HintTypes.HINT_LAUNCH_ID,
source).add(RichPopup.PopupHints.HintTypes.HINT_ALIGN,RichPopup.PopupHints.AlignTypes.
ALIGN_START_AFTER);
richPopup.show(hints);

*********To get Application Module Connection Object*********
ELContext elContext = null;
ValueExpression valueExp = null;
try {
            FacesContext fc = FacesContext.getCurrentInstance();
            Application app = fc.getApplication();
            ExpressionFactory elFactory = app.getExpressionFactory();
            elContext = fc.getELContext();
            valueExp = elFactory.createValueExpression(elContext, "#{data.idWorkshopAppModuleDataControl.dataProvider}",Object.class);
} catch (Exception e) {
            logger.error("getAm():" + e);
}
 return (idWorkshopAppModuleImpl)valueExp.getValue(elContext);

*********To access attribute using Key value*******
//Inside any method in App module
Key key= new Key( new Object[]{empID});
Row row=this.getEmployeeView1().getRow(key);
Row.setAttribute(“AttribName”, AttribValue);
try{
            this.getDBTransaction().commit();
}catch(Exception e) {}

*********Setting the Value of Named Bind Variables Programmatically*********
// changed lines in TestClient class
ViewObject vo = am.findViewObject("UserList");
vo.setNamedWhereClauseParam("TheName","alex%");
vo.setNamedWhereClauseParam("HighUserId", new Number(315));
vo.executeQuery();

*********Defining new Bind variable at Runtime:*********
vo.setWhereClause("user_role = :TheUserRole");
vo.defineNamedWhereClauseParam("TheUserRole", null, null);
vo.setNamedWhereClauseParam("TheUserRole","technician");
// execute the query and process the results, and then later...
vo.setNamedWhereClauseParam("TheUserRole","user");


*********Creating and Setting View Criteria attributes:**********
ApplicationModule am =
Configuration.createRootApplicationModule(amDef, config);
ViewObject vo = am.findViewObject("UserList");
// 1. Create a view criteria rowset for this view object
ViewCriteria vc = vo.createViewCriteria();
// 2. Use the view criteria to create one or more view criteria rows
ViewCriteriaRow vcr1 = vc.createViewCriteriaRow();
ViewCriteriaRow vcr2 = vc.createViewCriteriaRow();
// 3. Set attribute values to filter on in appropriate view criteria rows
vcr1.setAttribute("UserId","> 304");
vcr1.setAttribute("Email","d%");
vcr1.setAttribute("UserRole","technician");
vcr2.setAttribute("UserId","IN (324,326)");
vcr2.setAttribute("LastName","Baer");
// 4. Add the view criteria rows to the view critera rowset
vc.add(vcr1);
vc.add(vcr2);
// 5. Apply the view criteria to the view object
vo.applyViewCriteria(vc);
// 6. Execute the query
vo.executeQuery();

setWhereClause() : uses the column name while the createViewCriteriaRow's setAttribute uses attribute name.
We can also use the setConjuction(ViewCriteria.VIEW_CNJ_AND ) method on VC to set the AND or OR operation that will be used between View Criterias.


**********Using Entity object to get attribute value**********
private EntityImpl retrieveServiceRequestById(long requestId) {
String entityName = "devguide.model.entities.ServiceRequest";
EntityDefImpl svcReqDef = EntityDefImpl.findDefObject(entityName);
Key svcReqKey = new Key(new Object[]{requestId});
return svcReqDef.findByPrimaryKey(getDBTransaction(),svcReqKey);
}


*********Using association to get the attribute value for the related Entity object*********
public String findServiceRequestTechnician(long requestId) {
// 1. Find the service request entity
EntityImpl svcReq = retrieveServiceRequestById(requestId);
if (svcReq != null) {
// 2. Access the User entity object using the association accessor attribute
EntityImpl tech = (EntityImpl)svcReq.getAttribute("TechnicianAssigned");
if (tech != null) {
// 3. Return some of the User entity object's attributes to the caller
return tech.getAttribute("FirstName")+" "+tech.getAttribute("LastName");
}
else {
return "Unassigned";
}
}
else {
return null;
}
}


*********Updating Attribute using EO*********
public void updateRequestStatus(long requestId, String newStatus) {
// 1. Find the service request entity
EntityImpl svcReq = retrieveServiceRequestById(requestId);
if (svcReq != null) {
// 2. Set its Status attribute to a new value
svcReq.setAttribute("Status",newStatus);
try {
// 3. Commit the transaction
getDBTransaction().commit();
}
catch (JboException ex) {
getDBTransaction().rollback();
throw ex;
}
}
}


*********Creating new Row in EO*********
public long createProduct(String name, String description) {
String entityName = "devguide.model.entities.Product";
// 1. Find the entity definition for the Product entity
EntityDefImpl productDef = EntityDefImpl.findDefObject(entityName);
// 2. Create a new instance of a Product entity
EntityImpl newProduct = productDef.createInstance2(getDBTransaction(),null);
// 3. Set attribute values
newProduct.setAttribute("Name",name);
newProduct.setAttribute("Description",description);
try {
// 4. Commit the transaction
getDBTransaction().commit();
}
catch (JboException ex) {
getDBTransaction().rollback();
throw ex;
}
// 5. Access the database trigger assigned ProdId value and return it
DBSequence newIdAssigned = (DBSequence)newProduct.getAttribute("ProdId");
return newIdAssigned.getSequenceNumber().longValue();
}


*********Creating new Row using VO*********
import java.sql.Timestamp;
import oracle.jbo.ApplicationModule;
import oracle.jbo.Row;
import oracle.jbo.ViewObject;
import oracle.jbo.client.Configuration;
import oracle.jbo.domain.DBSequence;
import oracle.jbo.domain.Date;
public class TestCreatingServiceRequest {
public static void main(String[] args) throws Throwable {
String amDef = "devguide.model.SRService";
String config = "SRServiceLocal";
ApplicationModule am =
Configuration.createRootApplicationModule(amDef, config);
// 1. Find the ServiceRequests view object instance.
ViewObject svcReqs = am.findViewObject("ServiceRequests");
// 2. Create a new row and insert it into the row set
Row newSvcReq = svcReqs.createRow();
svcReqs.insertRow(newSvcReq);
// 3. Show effect of entity object defaulting for Status attribute
System.out.println("Status defaults to: "+newSvcReq.getAttribute("Status"));
// 4. Set values for some of the required attributes
newSvcReq.setAttribute("CreatedBy",308); // Nancy Greenberg (user)
Date now = new Date(new Timestamp(System.currentTimeMillis()));
newSvcReq.setAttribute("RequestDate",now);
newSvcReq.setAttribute("ProdId",119); // Ice Maker
newSvcReq.setAttribute("ProblemDescription","Cubes melt immediately");
// 5. Commit the transaction
am.getTransaction().commit();
// 6. Retrieve and display the trigger-assigned service request id
DBSequence id = (DBSequence)newSvcReq.getAttribute("SvrId");
System.out.println("Thanks, reference number is "+id.getSequenceNumber());
Configuration.releaseRootApplicationModule(am, true);
}
}


**********Gettning Records from Master and Details table**********
import oracle.jbo.ApplicationModule;
import oracle.jbo.Row;
import oracle.jbo.RowSet;
import oracle.jbo.ViewObject;
import oracle.jbo.client.Configuration;
public class TestClient {
public static void main(String[] args) {
String amDef = "devguide.model.SRService";
String config = "SRServiceLocal";
ApplicationModule am =
Configuration.createRootApplicationModule(amDef,config);
// 1. Find the StaffList view object instance.
ViewObject staffList = am.findViewObject("StaffList");
// 2. Execute the query
staffList.executeQuery();
// 3. Iterate over the resulting rows
while (staffList.hasNext()) {
Row staffMember = staffList.next();
// 4. Print the staff member's full name
System.out.println("Staff Member: "+staffMember.getAttribute("FullName"));
// 5. Get related rowset of ServiceRequests using view link accessor
RowSet reqs = (RowSet)staffMember.getAttribute("ServiceRequests");
// 6. Iterate over the ServiceRequests rows
while (reqs.hasNext()) {
Row svcreq = reqs.next();
// 7. Print out some service request attribute values
System.out.println(" ["+svcreq.getAttribute("Status")+"] "+
svcreq.getAttribute("SvrId")+": "+
svcreq.getAttribute("ProblemDescription"));
if(!svcreq.getAttribute("Status").equals("Closed")) {
// 8. Get related rowset of ServiceHistories
RowSet hists = (RowSet)svcreq.getAttribute("ServiceHistories");
// 9. Iterate over the ServiceHistories rows
while (hists.hasNext()) {
Row hist = hists.next();
// 10. Print out some service request history attributes
System.out.println(" "+hist.getAttribute("LineNo")+": "+
hist.getAttribute("Notes"));
}
}
}
}


*********Finding and Updating a foreign key value**********
import oracle.jbo.ApplicationModule;
import oracle.jbo.JboException;
import oracle.jbo.Key;
import oracle.jbo.Row;
import oracle.jbo.ViewObject;
import oracle.jbo.client.Configuration;
public class TestFindAndUpdate {
public static void main(String[] args) {
String amDef = "devguide.model.SRService";
String config = "SRServiceLocal";
ApplicationModule am =
Configuration.createRootApplicationModule(amDef,config);
// 1. Find the ServiceRequests view object instance
ViewObject vo = am.findViewObject("ServiceRequests");
// 2. Construct a new Key to find ServiceRequest# 101
Key svcReqKey = new Key(new Object[]{101});
// 3. Find the row matching this key
Row[] reqsFound = vo.findByKey(svcReqKey,1); //An entity-based view object delegates the task of finding rows by key to its underlying
if (reqsFound != null && reqsFound.length > 0) { //entity row parts. When you use the findByKey() method to find a view row by key,
Row svcReq = reqsFound[0]; //the view row turns around and uses the entity definition's findByPrimaryKey() to
// 4. Print some service request information //find each entity row contributing attributes to the view row key.
String curStatus = (String)svcReq.getAttribute("Status");
System.out.println("Current status is: "+curStatus);
try {
// 5. Try setting the status to an illegal value
svcReq.setAttribute("Status","Reopened");
}
catch (JboException ex) {
System.out.println("ERROR: "+ex.getMessage());
}
// 6. Set the status to a legal value
svcReq.setAttribute("Status","Open");
// 7. Show the value of the status was updated successfully
System.out.println("Current status is: "+svcReq.getAttribute("Status"));
// 8. Show the current value of the assigned technician
System.out.println("Assigned: "+svcReq.getAttribute("TechnicianEmail"));
// 9. Reassign the service request to technician # 303
svcReq.setAttribute("AssignedTo",303); // Alexander Hunold (technician)
// 10. Show the value of the reference info reflects new technician
System.out.println("Assigned: "+svcReq.getAttribute("TechnicianEmail"));
// 11. Rollback the transaction
am.getTransaction().rollback();
System.out.println("Transaction cancelled");
}
Configuration.releaseRootApplicationModule(am,true);
}
}