Friday, July 23, 2010

portats and portlets

Web Portal is a web page that aggregates information from multiple sources and presents it in a unified way. Typically the information is available in form of portlets.

Portlets are pluggable user interface components that are managed and displayed in a web portal.

Standards
WSRP V1 (Web Services for Remote Portlets)
JSR 168 (Java portlet definition standard)
JSR 286 (Java portlet V2 defintion standar)
Emerging Standard
WSRP V2

WSRP is a web services standard that allows for plug and play for remotely running portlets from disparate sources.
Java portlet specification allows interoperability of portlets between different web portals. It defines a set of APIs for interaction between the portlet container and portlet, addressing areas of personalization, presentation and security.

Friday, May 28, 2010

Uploading Files: ADF InputFile Component

In this post we will look at how the InputFile component can be used to upload files to the app server. Once the handle of a file is available at the app server then that file can processed in any way desirable. It can be stored on a file system or on a database or sent over a web service message.

Create a JSF page and drag a Input File component available in ADF Faces common components pallete, onto the page.

Next create a backing bean (faces context). Import the class: org.apache.myfaces.trinidad.model.UploadedFile; This class object will hold the reference to the file that will be uploaded using this component.

Here is the sample code for this backing bean:

import org.apache.myfaces.trinidad.model.UploadedFile;

public class FileUploader {
UploadedFile myFile;
public FileUploader() {
}
public String uploadFile() {
System.out.println("inside fileUpload method");
return null;
}
public void setMyFile(UploadedFile myFile) {
this.myFile = myFile;
System.out.println("inside set uploaded file method");
System.out.println("filename is : "+file.getFilename());
System.out.println("type is : "+file.getContentType());
System.out.println("filesize is : "+file.getLength());
}
public UploadedFile getMyFile() {
return myFile;
}
}

Set the value property, of the Input File component to point to the public instance variable myFile of the backing bean class created above. This variable will hold the reference to the file being uploaded.

Next add a push botton to the page and point its action to the uploadFile() method above. In this method you can write the code to process the file that has been uploaded.


Tuesday, May 25, 2010

base64 encoding for attachments in a web service

Attachments can be sent over web services through base64 encoding of the binary files and transporting them as string through a SOAP message.

Here is util file in java for encoding and decoding a binary file into base64 string.

package com.peoplesoft.hr.sa;
import java.util.zip.*;
import java.util.Enumeration;
import java.io.*;
import java.util.Stack;
import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;

public class base64Utils {
public base64Utils() {
}

/**
* encodes a file in base64 format
* @param filename name of the file to encode
* @return String the base64 text of the encoded file
*/
public String base64Encode(String filename) {
BASE64Encoder b64e = new BASE64Encoder();
byte[] temparray, filearray;
int bytecount;
try {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
filename));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
b64e.encode(bis, bos);
bis.close();
return bos.toString();
}
catch (Exception a) {
return null;
}
}

/**
* decodes a file from base64 format
* @param filename name of the file to decode to
* @param filedata the base64 encoded data
* @return String the base64 text of the encoded file
*/

public boolean base64Decode(String filename, String filedata)
{
BASE64Decoder b64d=new BASE64Decoder();
byte [] outputfile;
try {
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(filename));
outputfile=b64d.decodeBuffer(filedata);
bos.write(outputfile);
bos.close();
}
catch (Exception a) {
return false;
}
return true;
}
}

Downloading a File

Downloading a File:

To a button or a Command link you have to add a File Download Action Listener (af:fileDownloadActionListener). This component can be found under the Operations tab in the component pallete.

The page source code will look like:

<af:commandLink text="#{row.bindings.UserFileName.inputValue}"
shortDesc="#{bindings.SadAttachmentsVO1.hints.UserFileName.tooltip}"
id="it2">
<af:fileDownloadActionListener method="#{ConstituentData_BackingBean.handleFilekDownload}"
filename="#{row.bindings.UserFileName.inputValue}"
contentType="#{row.bindings.FileType.inputValue}"/>
</af:commandLink>


The properties to set are:
- ContentType: the MIME type of the file. This can be retrieved from a VO property is it has been stored along with the file
- Filename: name of the file. Again it should be available along with the file.
- Method: A call to a method on the backing bean, that will prepare the output Stream.

Example: In this method the file data is received as byte array by calling an AM service method. It is then passed onto the output stream.

public void handleFileDownload (FacesContext facesContext, OutputStream outputStream){
try {
Object result = executeMethodWithResult("getCachedAttachment");
outputStream.write((byte[])result);
} catch (IOException e) {
System.out.println("Exception "+e);
}
}

Thursday, May 6, 2010

af:iterator component

Below is a scenario where I tried using af:iterator component. This component will enable you to show multiple records in a layout other than a table. It worked ok for most part but was not able to recognise the value set for the Radio Group.

<af:iterator id="i1"
value="#{bindings.SccAdmExtnDataVO1.collectionModel}"
var="row"
rows="#{bindings.SccAdmExtnDataVO1.rangeSize}">
<af:panelFormLayout id="pfl3">
<af:inputText value="#{row.SeqNo}"
label="#{bindings.SeqNo1.hints.label}"
required="#{bindings.SeqNo1.hints.mandatory}"
columns="#{bindings.SeqNo1.hints.displayWidth}"
maximumLength="#{bindings.SeqNo1.hints.precision}"
shortDesc="#{bindings.SeqNo1.hints.tooltip}"
id="it3">
<f:validator binding="#{bindings.SeqNo1.validator}"/>
</af:inputText>
<af:outputText value="#{row.Question}"
id="ot3"/>
<af:selectOneRadio value="#{row.Answer}"
label="#{bindings.Answer.label}"
required="#{bindings.Answer.hints.mandatory}"
shortDesc="#{bindings.Answer.hints.tooltip}"
id="sor3">
<f:selectItems value="#{bindings.Answer.items}" id="si3"/>
</af:selectOneRadio>
</af:panelFormLayout>
</af:iterator>

Monday, May 3, 2010

XMLGregorianCalendar and Date conversions

Converting from oracle.jbo.domain.Date to java.util.Date to GregoriaCalendar to XMLGregorianCalendar

try {
System.out.println("converting date");
oracle.jbo.domain.Date jboDate = (oracle.jbo.domain.Date )myConstRow.getAttribute("BirthDate");
java.sql.Date sqlDate = jboDate.dateValue();
long longDate = sqlDate.getTime();
java.util.Date javaDate = new java.util.Date(longDate);
GregorianCalendar c = new GregorianCalendar();
c.setTime(javaDate);
XMLGregorianCalendar date2;
date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
constData.setBIRTHDATE(date2);
} catch (DatatypeConfigurationException e) {
System.out.println("Error with converting date");
}

Converting from XMLGregorianCalendar to GregoriaCalendar to java.util.Date to oracle.jbo.domain.Date

System.out.println("Birthdate IF");
java.util.Date javaDate = constData.getBIRTHDATE().toGregorianCalendar().getTime();
long longDate = javaDate.getTime();
java.sql.Date sqlDate = new java.sql.Date(longDate);
oracle.jbo.domain.Date jboDate = new oracle.jbo.domain.Date(sqlDate);
myConstRow.setAttribute("BirthDate", jboDate);

Sunday, April 25, 2010

Framework Extension Classes

Idea behind doing extending classes

One of the benefits of working with a framework is the ability to extend the framework classes to get a built in feature to work differently or enhanced / enrich its behaviour and utilise it all across the application.
- To augument a built in feature
- change how a built in feature works
- workaround a bug in the built in feature

Extending the class is pretty straightforward. Just create a new class and use extends keyword to make it extend the old class.

Including extended classes:
you can created extended classes in a separate project. If you have done that then you would have to include the project which contains the extended classes as a dependency of you project. Go to dependencies property in your project properties and add the extended claasses project in there.

if you have packaged the extended classes in a JAR file then create a named library definition to reference the JAR file and also list the library in library list of the project where you need these extended classes.

Getting ADF components to use the extended classes: For each ADF component there is a java page on the wizard. Here you can choose the base class that you want to extend and create an extended classes that can be used by the component.

Multiple levels of extension classes. In practice there can be and probably will be multiple levels of extension classes which are created for a an application. Some generic functionality is added or altered at the application level and hence an ApplicationCustomAppModuleImpl is created. Furthere there may be a need to add or alter some features at the project level. So ProjectCustomAppModuleImpl will extend ApplicationCustomAppModuleImpl. And at the application module level MyAMAppModuleImpl will extend ProjectCustomAppModuleImpl.

By default defining fwk extension classes for all new components: If you want to use a specific set of base classes upon which the custom classes for your project components should be based then you can define it in project properties > business components > base classes
You can also specify the extension classes for all new projects by going to Tools > Preferences > business components > base classes


Its always a good idea to create customised extension classes for your project or application at the very beginning. As you start writing you very first lines of code you might not have a need for any generic code. Nor you may fathom a requirement in the future. But quite frequently as the application begins to take shape you will come across bits and pieces that you would think can be shared across you various code components. By then it would involve a lot of effort to extend all you existing classes on a new class. So its a good idea to create a set of custom extension classes right at the beginning and add code to them as and when required.

A common set of customized framework base classes in a package name of your own choosing like com.yourcompany.adfextensions, each importing the oracle.jbo.server.* package, would consist of the following classes:
- public class CustomEntityImpl extends EntityImpl
- public class CustomEntityDefImpl extends EntityDefImpl
- public class CustomViewObjectImpl extends ViewObjectImpl
- public class CustomViewRowImpl extends ViewRowImpl
- public class CustomApplicationModuleImpl extends ApplicationModuleImpl
- public class CustomDBTransactionImpl extends DBTransactionImpl2
- public class CustomDatabaseTransactionFactory extends DatabaseTransactionFactory
For completeness, you may also want to create customized framework classes for the following classes as well, note however that overriding anything in these classes would be a fairly rare requirement.
- public class CustomViewDefImpl extends ViewDefImpl
- public class CustomEntityCache extends EntityCache
- public class CustomApplicationModuleDefImpl extends ApplicationModuleDefImpl

It is best to package these framework extension class in a JAR file so that they can be used across projects and applications.
Named libraries are a convenient way to use these JAR files in your code.


Reference:
http://download.oracle.com/docs/cd/E15523_01/web.1111/b31974/bcadvgen.htm#insertedID0

Wednesday, April 21, 2010

Username Token security call on web service

Code snippet:
SAD_ADMISSIONS sAD_ADMISSIONS;
SADCREATEAPPLRESP respCreateAppl = new SADCREATEAPPLRESP();
System.out.println("Before Try..in Create Appl");
try {

// Security Policy is set to User Name Token
SecurityPolicyFeature[] securityFeatures =
new SecurityPolicyFeature[] { new SecurityPolicyFeature("oracle/wss_username_token_client_policy") };

sAD_ADMISSIONS = new SAD_ADMISSIONS();

// port object is created passing in the security policy
SAD_ADMISSIONS_PortType sAD_ADMISSIONS_PortType = sAD_ADMISSIONS.getSAD_ADMISSIONS_Port(securityFeatures);

// request context object created
Map requestContext = ((BindingProvider) sAD_ADMISSIONS_PortType).getRequestContext();
SAD_ADMISSIONS_PortClient.setPortCredentialProviderList(requestContext);

System.out.println("Username/password:" + username + "/" +password);
requestContext.put(BindingProvider.USERNAME_PROPERTY, username);
requestContext.put(BindingProvider.PASSWORD_PROPERTY, password);

// service operation called
respCreateAppl = sAD_ADMISSIONS_PortType.sadCREATEAPPL(reqCreateAppl);

} catch (Exception ex) {
ex.printStackTrace();
}

Saturday, April 3, 2010

Working with a Non Database AM

Create you view object as one "Rows Populated programmaticaly, not based upon a query"
NoDatabaseApplicationPoolImpl : Custom Application Module Pool Implementation Class. Overrides isSupportsPassivation() method to return False, indicating to runtime that this AM does not support Passivation.
NonDatabaseConnectionStrategy : Custom Connection Strategy Class
CustomSessionImpl : Custom Session Class, returns a custom session transaction handler factory
CustomTxnHandlerFactoryImpl : A custom transaction handler factory, used to return an instance of the CustomTxnHandlerImpl class
CustomTxnHandlerImpl : custom Transaction Handler implementation class

The Session Class Configuration property is set to the name of the Custom Session Implementation Class (CustomSessionImpl)
The PoolClassName configuration property is set to the custom application module pool implementation class (NoDatabaseApplicationPoolImpl)

The jbo.ampool.connectionstrategyclass configuration property is set to the name of the custom connection strategy class which overrides the createApplicationModule() method to set some key properties in the environment hashmap before calling super.

Remove the reference to the Database connection in the Model.jpx file.

Sample App : Application 8

Thursday, February 11, 2010

ADF - Customizations and Personalizations

Personalisations and Customisations

Personalisation: Is the ability by the end user to change the look and feel of the application per their preferences. Like re-arranging, hiding columns in a table. Hiding or showing a detailed region, etc. Personalisations can persist within the same user sessions or can be configured to persist along user sessions.

Customisation (Seeded changes): Allow for design time customisation of a generic for specific sites or industries. These are done in jdeveloper using the customisation role. Its part of the deployment process.

Design time at Runtime: It is also possible to have a design time experience at runtime where administrators and analysts can used advanced components to create and model pages for the end user without the need for writing any code. This feature is provided by web centre which is a separately licensed product. We will not discuss that here since this comes in the domain of web 2.0 domain which has many other more powerful and useful features to exploit from.

Topics to be covered
- Customizing the appearance using style and skins
- Internationalizing and localizing pages
- Developing Accessible ADF pages



Personalisation:

The end user of the application can make certain changes to the UI they interact with as per their preferences.

Examples of these changes are:
- behaviour of widgets that show detail information (typically with a plus sign) can be changed to hide or show the detail by default.
- Resizable components can be resized, for example columns in a table, a frame.
- Panel splitter can be resized or collapsed.
- In a Calendar the view mode, whether year, month or week can switched. Active day can be selected
- Columns in a table can be re-ordered, frozen, visible, hidden, width changed. etc

Using MDS and the full Fusion stack also provides the following additional persistence functionality:
- Persisting additional attribute values
- Persisting search criteria
- Persisting the results of drag and drop gestures in the UI
- Reordering components on a page at runtime
- Adding and removing components and facets from the page at runtime


The application can be configured to allow user personalisation changes to persist within the same user session or across sessions.

- Same User Session: Any changes that the user makes to the application will persist throughout the session. If they log off and log in again then the changes will be lost and they will the see the UI in the default mode. The application has to be configured to allow session persistence. If allowed then all component behviourial properties that can be persisted will be persisted for the session. You cannot choose specific ones to allow persistance for the session.

- Across Sessions (MDS persistance) : The application can be configured to allow changes to certain type of changes to certain widgets to persist across user sessions. At design time it can be decided that changes to which behviourial property of which components should be allowed to persist across user session. In a sense the user preference is stored for good. The setting for the components and their properties can be overriden at individual instance of it. Which means that if a persistance change for a certain component's behaviour might not be allowed at the application level, but it can be allowed for the specific instance of that component on a particular page / UI. The component and their properties that are chosen for MDS persistance are recorded in adf-config.xml

Templates and Regions used across mutliple pages: Any changes made in properties of components on these behave as follows:
Session persistance: The changes made by the end user will only reflect on the page in whose context the change has been made.
MDS persistance: the changes made will appear on all pages that use the region or template.
This is because of a difference in the way the persistance is applied in either scenario.

To be covered: Implementing User Customisations (sections 35.5 and .6)



Application Customization:

Most end user of generic applications (typically application products) like to customise the application to suite their specific needs both in terms of validations applicable and the appearance of the application. For example customer software teams implementing a generic application at different sites can have a different customisation for each of their sites. In addition customisations can also be done for group of users such as different appearance for user with different roles and responsibilities.

Static Customisation: Static customisation is the one where the applicable customisation is visible to all users of that application. For example a site level customisation will be meant for all users at that site.

Dynamic Customisation: Dynamic Customisation is the one where the customisation applies differently to different users using the same application. This differentiation can be based on user roles.

Layered approach to Customisations:
Customisations are defined and applied in a layered way making the whole process of customisation more modular and easier to manage. The base application can have multiple layers of customisations.
For example a first layer can be 'industry' where different set of customisation can be configured for different industries in which the application might be used. Hence a different customisation set can be defined for say 'financial' industry and a different one for 'healthcase' or 'education' etc. These are called the layer values (i.e. 'financial','education','healthcare').
The next layer could be the 'site' layer. Where different sites can have different customisations.
The one after that could be a dynamic customisation layer for a user group such as a user role. Different roles have different customisations applicable to them.
As is evident here the customisation is defined at a customisation layer value. Which means that a set of customisation modifications would be defined for example education industry, another one for a site in New York.

The final behaviour of an application for the end user would depend upon the different layers of customisation applicable for that user. Hence at runtime the base layer is picked up then each customisation layer is applied (in the sequence in which is defined in the cust-config section of adf-config.xml) to it, depending upon the layer values derived from the context in which the application is running and the specific user using it.

diagram

This layered approach to customisations keeps the customisations as upgrade safe. The base layer can change without impacting the customisation layers.
Note: I dont think all customisations can be performed in the layer approach. This can be studied more to identify instance of customisations that cannot be applied through this approach. But this is definetely a good first step to try make customisations isolated from the base application and make the process of upgrading the base app less of a pain for the customers

Customisations on ADF model and business components are applicable all across the app since they are loaded only once. They cannot be controlled to behave differently for different users.
Customisations on controller or view level cane be configured based upon user role. Examples: different sets of users can be shown different sets of fields based upon their role.



This is a good video:
http://download.oracle.com/otn_hosted_doc/jdeveloper/111demos/mds/mds.html