Tuesday, January 17, 2012

#ADF Talk Session 2 on Youtube

In ADF Talk Session 2 Ulrich and me dive a bit deeper into the details of PL/SQL Code integration by custom jdev extension. The video shows the usage of custom jdeveloper extension: Application Module from Database Package. See it in action.



Get updated on new sessions by following us on Twitter: @adftalk


Any feedback is greatly appreciated. Feel free to comment. Take also a look at Ulrichs Posts. There are already some comments related to the shown jdev extension.


Enjoy.

Play!ing with #WebSockets

Development Stack

Server: Play 1.2.4, WebSocket
Client: jQuery, Boostrap
Tested with: Safari 5.0.5 (on Win XP)
On: Localhost

Inspired by a Blog-Post from Lucas Jellema I have done a similar demo with Play!.


The nice thing is that it was really easy to setup and deploy into the cloud. So everyone can test the websocket app - eeehm that was my initial plan (Actually it does not work currently, see why below). Further I took the chance to get in touch with git and published the source code on github. So feel free to test and fork.

https://github.com/multikoop/play-push-imgsel

0000@2772_2772-41266a678e29b7f1

Since there are some great cloud services arosed in the past I wanted to give it a try. So here are my experiences:

Deployment@Heroku

Prerequisite: install heroku CLI, git client (Please google for it how to set app.  I only post the interesting stuff here)

C:\play\apps\play-push-imgsel>heroku login
C:\play\apps\play-push-imgsel>heroku create -s cedar play-push-imgsel
Creating play-push-imgsel... done, stack is cedar
http://play-push-imgsel.herokuapp.com/ | git@heroku.com:play-push-imgsel.git
Git remote heroku added

C:\play\apps\play-push-imgsel>git push heroku master
Counting objects: 46, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (40/40), done.
Writing objects: 100% (46/46), 110.54 KiB, done.
Total 46 (delta 6), reused 0 (delta 0)

-----> Heroku receiving push
-----> Play! app detected
-----> WARNING: Play! version not specified in dependencies.yml. Default version
: 1.2.4 being used....
-----> Installing Play! 1.2.4.....
-----> done
-----> Installing ivysettings.xml..... done
-----> Building Play! application...
~        _            _
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/
~
~ play! 1.2.4, http://www.playframework.org
~
1.2.4
Building Play! application at directory ./
Resolving dependencies: .play/play dependencies ./ --forceCopy --silent -
Duser.home=/tmp/build_jxh1de2j7wc9 2>&1
:: loading settings :: file = /tmp/build_jxh1de2j7wc9/.ivy2/ivysettings.x
ml
~ Resolving dependencies using /tmp/build_jxh1de2j7wc9/conf/dependencies.
yml,
~
~
~ No dependencies to install
~
~ Done!
~
Precompiling: .play/play precompile ./ --silent 2>&1
Listening for transport dt_socket at address: 8000
10:26:55,430 INFO  ~ Starting /tmp/build_jxh1de2j7wc9
10:26:56,387 INFO  ~ Precompiling ...
10:27:03,224 INFO  ~ Done.
-----> No Procfile found. Will use the following default process:
play run --http.port=$PORT $PLAY_OPTS
-----> Discovering process types
Procfile declares types -> (none)
Default types for Play! -> web
-----> Compiled slug size is 26.6MB
-----> Launching... done, v5
http://play-push-imgsel.herokuapp.com deployed to Heroku

To git@heroku.com:play-push-imgsel.git
* [new branch]      master -> master

C:\play\apps\play-push-imgsel>heroku open
Opening http://play-push-imgsel.herokuapp.com/

C:\play\apps\play-push-imgsel>


This is an awesome and easy to use stack!!!!! #PGH => Play, Git, Heroku!



Deployed at: http://play-push-imgsel.herokuapp.com/



Application is accessible but WS request are not working (oops).



C:\play\apps\play-push-imgsel>heroku logs
...
...
2012-01-14T10:36:29+00:00 heroku[router]: Error H12 (Request timeout) -> GET pla
y-push-imgsel.herokuapp.com/ap... dyno=web.1 queue= wai
t= service=30000ms status=503 bytes=0


=> Feature Request has been filed at Heroku. http://support.heroku.com/tickets/40910



Deployment@Cloudbees



Since WebSocket is currently not supported (according to: http://www.jamesward.com/2011/12/11/tutorial-play-framework-jpa-json-jquery-heroku) I decided to give cloudbees a try. Same here



Deployed at: http://play-push-imgsel.multikoop.cloudbees.net/



Same issues here:



... 20:27:42,952 WARN ~ 404 -> GET /application/pushimgsel/process (GET /application/pushimgsel/process) ...



=> Request #2383 "HTTP 404 on WebSocket Reque..." created. https://cloudbees.zendesk.com/tickets/2383



Conclusion



The cloud is not ready for WebSocket applications in early 2012! ;-)



If you want to see the demo live, all you need to do is



-Install Play 1.2.4

-Get push-imgsel Sourcecode: https://github.com/multikoop/play-push-imgsel


-Test with Safari (Other modern browsers currently not working, cause WebSocket Implementation in Play 1.2.4 cannot handle the newest Sec-WebSocket-Version Headers. Hopefully it will be fixed in 1.2.5 at least in 2.0.



Have fun!

Sunday, January 1, 2012

ADF: MDS power user layer and "How to control MDS customizations at runtime"

Tested with: JDeveloper/ADF 11.1.1.2
Happy new year 2012 to all of my readers! First post this year is a follow up on "ADF: Define default UI for MDS user customization".
http://multikoop.blogspot.com/2010/01/adf-11g-define-default-ui-for-mds-user.html
Introduction
In that previous post I introduced a feature to be able to define a default UI layout at runtime by a specific user. That particular UI customization acts as the initial default for any other logged in users. That is great and simplifies developers life as the default layouting (which columns to display, in which order arrange, splitter posisions and so on) can be done by a business user.
Although those great capabilities there is still a lack of control regarding applied MDS customizations of specific users. In User Support situations it is often helpful to reset the user customizations to factory defaults in order to have the "same view on the UI".
So here is our solution how to be able to reset MDS Customizations at runtime for ALL users, or for specific users with regards keeping the power user defaults.
First recap that we have defined a special layer "DefaultUserCC"
0000@2752_2752-41266a4f4bf6e5d5
With this Customization class configured it is now possible to login as the user "layout" and define the default UI for all other users. It just means that the DefaultUserCC customizations are applied before the UserCC. (So the order of the CCs in the above screen is important!)
(You can test the behaviour with attached sample application based on ADF11.1.1.2. See download link at the end of this post)
Sample application
0001@2752_2752-41266a4f51401846
Two test users bob and alice and the power layout user "layout".
1. Login as layout
2. Remove all rows except Firstname and Lastname, Email.
0005@2752_0004@2752_2752-41266a4f52fc9630
3. Logout layout
4. Login as bob
0006@2752_0005@2752_0004@2752_2752-41266a4f52fc9630
[Notice that bob has inherited the ui settings from user layout]
5. Now Remove the email column
0007@2752_0002@2752_2752-41266a4f523ef500
6. Logout bob
[Imagine: You get a support call from user bob. He says he is not able to lookup the email adress. To simplify further investigations you should be able to get his user layout back to default.]

7. Login as layout (or in general as an MDS Admin)
8. Enter username: bob
0008@2752_2752-41266a4f5894ab6d
9.Click "Reset to layout user defaults"
As feedback you will get
0009@2752_2752-41266a4f58efb11d
[Imagine: In Support case you would now advise the user to login again. From that moment you can be sure user bob has same ui layout as defined by the user layout.]
Wow. This is a really powerful feature I think. Is there any other web app framework which can do this? ;)
How we do it: Delete MDS documents at runtime
To implement the mentioned features there is not really much to do (beyond the basic MDS configuration which I will not describe here. See references for details.)
1. Implement and configure custom Customization Class (Here: DefaultUserCC.java)
2. Use Oracle MDS API to delete MDS documents. To find how this actually can be done I followed to approaches. a) Reverse engineeer from deleteMetadata WLST command. b) Google.
Option a guided me through
oracle.mds.internal.lcm.mbean.AppRuntimeMBeanImpl
   public Map deleteMetadata(String[] docs, String[] custNames, boolean excludeAllCust, boolean excludeBaseDocs, boolean excludeExtendedMD, boolean cancelOnException)

oracle.mds.internal.lcm.MDSLCMManager
   Map deleteMetadata(String[] docs, String[] custNames, boolean excludeAllCust, boolean excludeBaseDocs, boolean excludeExtendedMD, boolean cancelOnException, Locale locale)
      ...
      doDelete(...)

  List doDelete(MetadataStore store, String[] docs, boolean excludeAllCust, boolean excludeBaseDocs, boolean excludeExtendedMD, boolean cancelOnException, TypeConfig typeConfig, CustConfig custConfig, List custLayerFilterList, DependencyConfig dConfig)
       ...
       TransferUnitList transferUnitList = TransferUnitList.create(mdsInstance, docsList, transferOptions, !excludeBaseDocs, true);
       List resultList = MDSTransfer.getInstance(mdsInstance).delete(transferUnitList, cancelOnException);
       ...
oracle.mds.internal.transfer.InternalMDSTransfer
    delete ...
    execute....

Option b guided me to a some really great resources. 1. http://oraclemw.blogspot.com/2011/04/working-with-oracle-mds-repository.html 2. http://idmclub.wikidot.com/metadata-store where I found some basic information on the usage of the MDS API.
Finally I came up with a MDSUtils.java and MDSAdminBean.java which does the needed work.
Here are the most important code snippets
MDSUtils.java
public static void deleteDocuments(final MDSInstance mdsInstance,
final List listOfFiles) throws MDSException {

MDSTransfer transferInstance = MDSTransfer.getInstance(mdsInstance);

TransferUnitList transferUnitList =
TransferUnitList.create(mdsInstance, listOfFiles, null, true,
true);
transferInstance.delete(transferUnitList, false /* cancelOnException */);
transferInstance.release(mdsInstance);
}

public static List queryAllFiles() {
final MDSSession mdsSession = MDSUtils.getCurrentMDSSession();

//String packagePath, String documentName, boolean recursive,
final NameQueryImpl nameQuery =
new NameQueryImpl(mdsSession, ConditionFactory.createNameCondition("/",
"%",
true));
final Iterator result = nameQuery.execute();
final ArrayList listOfFiles = new ArrayList();
while (result.hasNext()) {
final QueryResult qr = result.next();
final String absoluteName = qr.getAbsoluteName();
listOfFiles.add(absoluteName);
}

return listOfFiles;
}


   
MDSAdminBean.java


Nothing special here. Just use the "hard worked out";-) MDSUtils in action listern methods, e.g.


List listOfFiles =
MDSUtils.queryFilesMatch("/mdssys/cust/user/" + username);
try {
System.out.println("MDS Admin: Deleting " + listOfFiles);
MDSUtils.deleteDocuments(listOfFiles);
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
null,
"Deleted the following MDS-Documents for user " +
getUsername() +
": " +
listOfFiles));
} catch (MDSException e) {
e.printStackTrace();
}


Download the application and checkout the customization possibilities with bob, alice and layout!

http://www.box.com/s/kvjc43my8mbvoyi9lh3v (JDev 11112 Workspace)


References


User Customization with and without MDS

http://blogs.oracle.com/raghuyadav/entry/user_customization_with_and_wi


Programmatic access to Oracle Metadata Store (MDS)

http://idmclub.wikidot.com/metadata-store


Working with Oracle MDS Repository (MetaData Services)

http://oraclemw.blogspot.com/2011/04/working-with-oracle-mds-repository.html


ADF: Define default UI for MDS user customization

http://multikoop.blogspot.com/2010/01/adf-11g-define-default-ui-for-mds-user.html

Tuesday, December 20, 2011

Custom ADF Skin: Consume as Library

Tested with JDeveloper: 11.1.2.1.0
Main purpose of this post is for me to have a reference project and proof of concept using an ADF Skin as Library.
Part 1: Skin Application
So first the ADF Skin project should be created. Since JDevR2 this process has been simplified by new ADF Skin wizard.
0000@2728_2728-41266a37beff9ee9
In the next screen just give your skin a name and extend from the fusionFx-simple-v2.desktop Oracle Skin. It is specially designed with extensibility in mind for cusom skins. Fortunataly the recommended skin is selected. (It is not with every ADF/Jdeveloper feature ;). So well done Oracle!
0001@2728_2728-41266a37bfbbbbbc
The following bunch of things is created on the fly
0002@2728_2728-41266a37c0ee2cc1
Now lets create a "green" skin with smallest amount of modifications. This is achieved by opening the CSS file and
go to the "Images" View. Just change some of the colors.
0003@2728_2728-41266a37c2b9d648
And afterwards click "Apply to Skin"
=> This will generate a lot of images according to your color schema.
0004@2728_2728-41266a37c3487043
In order to support versioning of skin I am adding the following to the trinidad-skins.xml
   <version>
     <name>v1</name>
     <default>true</default>
   </version>
=>
0005@2728_2728-41266a37c41b4e82
Now we are ready to bundle the custom skin as ADF library. There is nothing special here. Create the Deployment profile, keep defaults and deploy.
Next step is to test the provisioning of the ADF Skin through ADF Library through File System connection. To do that we create a filesystem connection in the resource pallete
0006@2728_2728-41266a37c59fab0c
The Skin shows up as expected
0007@2728_2728-41266a37c5c8a0ce
Part 2: Consume ADF Skin
a) Create an pure empty Fusion ADF Application by wizard.
b) Select the ViewController project
c) Select adflib-myskin.jarm Right Click and Click add to Project
0008@2728_2728-41266a37c70bc1cd
The Message Pane should output something like
These ADF Library jar items are now in ViewController.jpr
{
  file:/C:/ak/JDeveloper/mywork/TestADFSkin/MySkin/deploy/adflib-myskin.jar
  These are in the project as a result of your ADF jar imports:
  Resource Bundle Variable Resolver from .../TestADFSkin/MySkin/MySkin.jpr
}
d) Apply custom ADF Skin as default in Project Properties>ADF View
0009@2728_2728-41266a37c7b425ed
e) Create a simple JSF Page based on the threeColumnTemplate and  take a look
0010@2728_2728-41266a37c94320ff
At Design-Time there seem to be some problems.
At Runtime it looks as expected
0011@2728_2728-41266a37cb518a6e
Is it a Bug at Design Time?
Using just a QuickLayout everything is as expected also in design time
0012@2728_2728-41266a37cd2f684c
Download Sample Workspaces: http://www.box.com/s/h8mggth460ntujhg7o3r

Tuesday, December 13, 2011

RESTful Management Services in Oracle WebLogic Server 12c

Version: 12.1.1 (developer edition, ZIP, no installer)

Installation

unzip wls1211_dev as follows

0000@2713_0-41266a23103b2a19

In order to be able to work with this edition we have to call configure.cmd. This basically unpacks all jars, create the registry.xml and wlserver\.product.properties

To have some reusable snippets I have created additional scripts in the new MW_HOME

env_wls12c_dev.cmd

@echo off
@rem ***************************************************************************
@rem This script is used to set the environment for
@rem Oracle WebLogic Server 12.1.1 dev ZIP edition
@rem ***************************************************************************

set MW_HOME=C:\oracle\product\12.1.1\middleware
set JAVA_HOME=C:\oracle\product\11.1.2.1\middleware\jdk160_24
set JAVA_VENDOR=Sun


install_wls12c_dev.cmd



@echo off
@rem ***************************************************************************
@rem This script is used to install Oracle WebLogic Server 12.1.1 dev ZIP edition
@rem ***************************************************************************

call env_wls1211_dev.cmd

title Installing WLS 12.1.1.0...

call %MW_HOME%\configure.cmd

pause


Now execute install_wls12c_dev.cmd



In order to create a domain by configuration wizard



a) call env_wls12c_dev.cmd



b) %MW_HOME%\wlserver\common\bin\config.cmd



RESTful Management Service API



Sounds cool...lets try



Activate by Domain > Configuration > Advanced Configuation > Enable RESTful Management Services



=> (restart required)



After restart you will notice the following in the output



INFO: Scanning for root resource and provider classes in the packages:
weblogic.management.rest.resources
weblogic.management.rest.provider
13.12.2011 00:03:13 com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
class weblogic.management.rest.resources.ApplicationResource
class weblogic.management.rest.resources.TestResource
class weblogic.management.rest.resources.ClusterResource
class weblogic.management.rest.resources.DataSourceResource
class weblogic.management.rest.resources.ServerResource
13.12.2011 00:03:13 com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Provider classes found:
class weblogic.management.rest.provider.CollectionResponseXmlProvider
class weblogic.management.rest.provider.ItemResponseJsonProvider
class weblogic.management.rest.provider.CollectionResponseJsonProvider
class weblogic.management.rest.provider.CollectionResponseHtmlProvider
class weblogic.management.rest.provider.ItemResponseHtmlProvider
class weblogic.management.rest.provider.ItemResponseXmlProvider
13.12.2011 00:03:14 com.sun.jersey.server.impl.application.WebApplicationImpl _i
nitiate
INFO: Initiating Jersey application, version 'Jersey: 1.9 09/02/2011 11:17 AM'


(=> This is good news! It states that some RESTful service will be available.)



After Restart open http://localhost:7001/management/tenant-monitoring/servers



(the authorized users must be in the group Administrators or Monitors)



0001@2713_2713-41266a27ed555555



Login in as weblogic user and see the default HTML output



0002@2713_2713-41266a27efb11d34



If you e.g. need better proccessable formats, JSON and XML are of course also supported. Let's see how it is done and what it looks.



Add Accept Header with application/json



0004@2713_2713-41266a27f2c474d0



Add Accept Header with application/xml



0005@2713_2713-41266a27f36b5493



Currently there is REST support for Servers (all in a domain or specific one), Clusters ( all in a domain or specific incl server members), applications (all in a domain or specific app), data sources (all in a domain or specific).



With these capabilities it' possible to implement a custom monitoring solution. A slim mobile wls monitoring app (and more)! => Hands on;)



See doc for details of all available RESTful-Services in WLS12.1.1 http://docs.oracle.com/cd/E24329_01/web.1211/e26722/toc.htm



Collected Documentation links



Overview OTN: http://www.oracle.com/technetwork/middleware/weblogic/documentation/index.html



WLS 12c  Data sheet: http://www.oracle.com/us/products/middleware/application-server/oracle-weblogic-server-ds-1391360.pdf



WLS 12c online Documentation Library: http://docs.oracle.com/cd/E24329_01/index.htm



Usind RESTful Services  With WLS 12c: http://docs.oracle.com/cd/E24329_01/web.1211/e26722/toc.htm



Dislikes



- Still many BEA* stuff in diffrent scripts. It would be nice to have a clean and straight product without any historical garbage.



- configure.xml : ProgramGroupName=BEA WebLogic Platform 10.3 (Integrated Build)....


Why there is still the need to have a programm group called "BEA WebLogic Platform 10.3"?


My suggestions: Oracle WebLogic Platform 12.1.1 or Oracle Fusion Middleware Platform 12.1.1, everythin else, but not 10.3!



Like



- Java EE 6 Support. (It took a long time..)


- Better Maven Support


- RESTful Management Service


- ZIP distribution. Although the file is called wls1211_dev.zip it is possible to create a domain in production mode by the configuration wizard. At least in a simple testdrive it worked for me.


-Startup time feels better than wls11g


- more to test...(-Dservertype=wlx  to avoid loading EJB, JMS, JCA )

Saturday, November 26, 2011

ADF: Panel Tabbed Inter-Region Communication through shared bean datacontrol

Tested with JDeveloper 11.1.1.2

Use Case

  • JSF Page with two tabs (Departments, Employees)
    image The DepartmentName is rendered as a command link. If the user clicks on a DepartmentName the view changes on to the Employees Tab and filters the data
    image
  • In each tab there is an static adf region (bound to fragment based BTF)
    image
In summary we need the following to do:
  • DepartmentName as command link
  • View switches to the Employees Tab
  • Tab text should change to “Employees (<DepartmentName>)
  • On the employees tab - of course – only the corresponding entries should be displayed
  • The employees tab contains a button to remove the “global” filter.

How to do it?

Create DataExchange Bean as follows
public class DeptEmpExchange {
    private Number deptId;
    private String deptName;
    public DeptEmpExchange() {
        super();
        System.out.println("DeptEmpExchange created " + this);
    }
    public void setDeptId(Number deptId) {
        this.deptId = deptId;
    }
    public Number getDeptId() {
        return deptId;
    }
    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }
    public String getDeptName() {
        return deptName;
    }
    /**
     * Exposed as DC Operation.
     * Called from the dept btf
     * @param deptId
     * @param deptName
     */
    public void onDepartmentChange(final Number deptId,
                                   final String deptName) {
        System.out.println("onDepartmentExchange called: " + deptId + "/" + deptName);
        setDeptId(deptId);
        setDeptName(deptName);
        View1Bean view1 = (View1Bean)JSFUtils.resolveExpression("#{View1Bean}");
        view1.getEmpTab().setDisclosed(true);
        view1.getDeptTab().setDisclosed(false);
        view1.setEmpTabText("Employees ("+deptName+")");
        AdfFacesContext.getCurrentInstance().addPartialTarget(view1.getPanelTabbed());
    }
And expose as JavaBean DataControl.
Now, on depts page fragment: drop the exposed operation onto the command link and provide the parameters from the current row.
image
The refresh of the panel tabbed is done programmatically in the onDepartmentChange(..) method. In order to refresh the emp btf with the new dept id configure the following bindings / properties on the main page
image
- create an attribute binding on the deptId from the DeptEmpExchange Bean.
- bind the tf input parameter to the attribute binding
- do not forget to set refresh=ifNeeded => this causes the btf to refresh in case the input params will change.
Implementing the “remove global filter” functionality is pretty simple. Just drag the onDepartmentChange-Operation from the data control palette on to the toolbar and adjust the text.
image

image
I hope I have not forgotten any important steps.

Download JDev11112Workspace

Update on Dec 19th 2011: Added Sample Application