Thursday, September 30, 2010

No no no - SQL paging in oracle - It cant be

SELECT * FROM (
SELECT t1.*, ROWNUM rnum
FROM your_table t1
WHERE t1.name = ? ORDER BY t1.name DESC)
WHERE rnum >=? AND rownum <= ?


You got to be kidding me is there not an easy way like limit in mysql

Wednesday, September 29, 2010

Auto Focus in ADF

still to fill in details but heres the idea

-- bind query to backing bean
-- get Id from bound query and inject some javascript with the id.

public void focus(UIXComponent comp) {
StringBuilder script = new StringBuilder();
FacesContext context = FacesContext.getCurrentInstance();
script.add("var elem = document.getElementById(").append(comp.getClientId(context)).append("); if (elem != null) {elem.focus();}");
Service.getRenderKitService(context, ExtendedRenderKitService.class).addScript(context, script.toString());
}

-- viola

ok after some pain here is the javascript function that works on ie and firefox

function focusField(elementId) {
var comp = document.getElementById(elementId);
if (comp != null) {
comp.focus();
comp.select();
}
}

NOTE: On some screens the auto focus does not work because the component does not have an id or children(has not been initialized etc) for this just run the method bound to the value attribute on component after the one you want to focus or create a dummy. ie



in the java : {public String getAutoFocus() { focus(focusField); return "";}}

Remeber this method will be called more than once so it may have undesired results.

Tuesday, September 28, 2010

Get the package body for oracle stored procedure

select dbms_metadata.get_ddl('PACKAGE_BODY', 'PACKAGE', 'SCHEMA') from dual;

Thursday, September 23, 2010

ADF Excel export

In adf if you export your tables that contain lov inside the index or id is exported and not the selected item value.

If your table is read only change your existing table column from eg:
<af:outputText value="#{row.bindings.Field.items[row.bindings.Field.inputValue].label}"
id="ot3"/>

Me and my ADF

--Just a random set of opinions read no further if you are looking for technical info.

Ok so I have been working with ADF for 8 months now (have worked with SOA suite before) and here are a couple of rants and findings:

Development speed etc:
  • The initial learning curve in VERY steep.
  • Get help - we had an adf expert help us out - invaluable.
  • Get the adf source code - it will help you.
  • Like any framework you need to write a bit of framework extension code
  • It is NOT just drag and drop dev if you want anything custom.
  • Try to get things right from the start or you will end up redoing a lot and it is not very "refactoring" friendly.
  • Forms devs will have to get a LOT of training to use this. (they will have to learn java and ADF unless you run a sweat shop dev process)
  • Hire a very very compentant java dev before switching over from forms.
  • Having a lot of logic in pl\sql with this framework may not be a bad thing.
  • Try to do as little custom stuff as possible
  • Once you have a good set of patterns and framework in place dev speeds up CONSIDERABLEY (+- 6 months for a fresh team with no ADF experience)
Comparision with other frameworks:
Getting your forms team to learn java would be less of a learning curve unless you structure you teams very well.

I would love to have a project that uses EJB3 with ADF's (fabulous JSF components) jsf stuff. Not overly fond of BC right now.

At the moment I find the ADF framework more difficult to use than other JEE frameworks because of the size of it and it does a lot of stuff "for free" so it is difficult to debug if it goes wrong. (Note I have worked with the following (Maven, Maven2, Ant, glassfish, DB2, postgres, mysql, EJB3, EJB2, Hibernate, trinidad, myfaces, struts, jsp, IBM RAD, eclipse etc) so I am not speaking out of my ass)

Wish list:
  • Maven2 Intergration
  • Proper SVN and CI intergration
  • JDev startup times improved
  • JDev is crap so use eclispe (wishful thinking)
  • OJDeploy compile times
  • JDev (shortcuts are anti intuitive, Ctrl - across open projects, speed of rendering of Design view etc etc)
Final thoughs: ADF given time will mature into an awesome framework that will speed up dev time and allow developers to focus on solving business problems. It is not a silver bullet and the answer to all you problems though and takes time to learn.

Almost foolproof ADF Oracle proxying

1) Create a common application model (this also sets up the oracle users in the context just for auditing)
@Override
    protected void prepareSession(Session session){

        super.prepareSession(session);

        try{
            String userName = ADFContext.getCurrent().getSecurityContext().getUserName();
            String host = ((HttpServletRequest)ADFContext.getCurrent().getEnvironment().getRequest()).getRemoteHost();
            String ip = ((HttpServletRequest)ADFContext.getCurrent().getEnvironment().getRequest()).getRemoteAddr();

            if (userName != null){
                setupSessionInfo(getDBTransaction(), host, ip, userName);
            }
            proxyUser(getDBTransaction());
            //this is done because of a crappy weblogic caching error
            clearPoolCache(getDBTransaction());
        } catch (Exception e){
            session = null;
            System.out.println("------> Error in user proxy");
            e.printStackTrace();
            throw new ApplicationModuleException(e);
        }
    }



2) Extend this AM in all you application modules that require proxy
public class MyAMImpl extends MyParentApplicationModuleImpl implements MyAM{

3) Grant user rights to connection pool user

alter user MyUser grant connect through CPUser;

4) Proxy user method

public static void proxyUser(DBTransaction transation) throws SQLException{

        Statement stat = transation.createPreparedStatement("rollback", 0);
        OracleConnection oConn = (OracleConnection)stat.getConnection();

        Properties props = new Properties();
        String uname = ADFContext.getCurrent().getSecurityContext().getUserPrincipal().getName();
        props.put(OracleConnection.PROXY_USER_NAME, uname);
        if (oConn.isProxySession()){
            oConn.close(OracleConnection.PROXY_SESSION);
        }
        try{
            oConn.openProxySession(OracleConnection.PROXYTYPE_USER_NAME, props);
        } catch (SQLException e){
            oConn.abort();
            if (!stat.isClosed()){
                stat.close();
            }
            throw e;
        }

        if (!stat.isClosed()){
            stat.close();
        }

    }

5) Clear cache method (could just switch weblogics cache off)
public static void clearPoolCache(DBTransaction transation) throws SQLException{

        Statement stat = transation.createPreparedStatement("rollback", 0);
        OracleConnection oConn = (OracleConnection)stat.getConnection();
        clearPoolConnStmntCache(oConn);
        if (!stat.isClosed()){
            stat.close();
        }
    }

6) setupSessionInfo method
protected void setupSessionInfo(DBTransaction transaction, String host, String ipAddress, String userName){

//this sql is just an example you can do more here
        String sql = " BEGIN dbms_session.set_identifier(:host); dbms_application_info.set_client_info(:ipAddress); END;";

        Map parameters = new HashMap();
        parameters.put("host", host);
        parameters.put("ipAddress", ipAddress);
        parameters.put("userName", userName);
        AdfJdbcUtil.executeNamedCall(false, transaction, sql, parameters);
    }

Wednesday, September 22, 2010

ant and ojdeploy

oracle.jdeveloper.ojdeploy.path=/Oracle/Middleware/jdeveloper/jdev/bin/ojdeploy
application.name=Common
<target name="buildJar">
<exec executable="${ojdeploy.path}" dir="${basedir}/${application.name}">
    <arg line="-workspace ${basedir}/${application.name}/${application.name}.jws"/>
    <arg line="-project ${application.name}"/>
    <arg line="-profile ${application.name}"/>
    <arg line="-nodatasources"/>
    <arg line="-forcerewrite"/>
    <arg line="-basedir ${basedir}/${application.name}"/>
  </exec>
</target>

UnsupportedCallbackException: Accessing the HttpServletRequest from a custom auth provider

There could be more than one cause of this problem but here is what cause it for me:

My custom provider was the first provider in the list and was set to sufficient.

I got an UnsupportedCallbackException when I tried to use the ContextHandlerCallback to retrieve the request in my provider.

This was due to the fact that weblogic log in was using my provider and it uses the SimpleCallbackHandler (boo hiss).

Here is my code: (I throw an login exception and fail the login if the callbacks are null for my login)

  private Callback[] getCallbacks() throws LoginException{
    Callback[] callbacks = new Callback[3]; // need one for the user name
    callbacks[CALLBACK_USERNAME_POSITION] = new NameCallback("username: ");
    callbacks[CALLBACK_PASSWORD_POSITION] = new PasswordCallback("password: ", false);
    callbacks[CALLBACK_CONTEXT_POSITION] = new ContextHandlerCallback();

    try{
      callbackHandler.handle(callbacks);
    } catch (IOException e){
      e.printStackTrace();
      throwException(e);
    } catch (UnsupportedCallbackException e){
      System.err.println("UnsupportedCallbackException:" + e.getMessage());
      return null;
    }
  return callbacks;
  }
Get the Request after obtaining the callback:
private HttpServletRequest getRequestCallback(Callback[] callbacks){
  ContextHandlerCallback cb = (ContextHandlerCallback)callbacks[CALLBACK_CONTEXT_POSITION];
  if (cb != null){
    return (HttpServletRequest)cb.getContextHandler().getValue("com.bea.contextelement.servlet.HttpServletRequest");
  }
  return null;
}

Friday, September 17, 2010

Case Insensitive Filter

On the column just set the filterFeatures attribute to caseInsensitive

CODE ALTERNATIVE

1) Map your querylistener and table binding to methods in your backing bean.

2) Implement the above mentioned methods and so what you need to the filter:

public void queryListener(QueryEvent queryEvent){
FilterableQueryDescriptor des = (FilterableQueryDescriptor)getModuleTable().getFilterModel();
Map _criteriaMap = des.getFilterCriteria();
Set featureSet = new HashSet();
featureSet.add(FilterableQueryDescriptor.FilterFeature.CASE_INSENSITIVE);
Iterator criteriaIter = _criteriaMap.keySet().iterator();
Map filterFeatures = new HashMap();
while (criteriaIter != null && criteriaIter.hasNext()){
String keyCr = (String)criteriaIter.next();
((HashMap)filterFeatures).put(keyCr, featureSet);
}
des.setFilterFeatures(filterFeatures);
JSFUtils.invokeMethodExpression("#{bindings.MdsModuleElementsVO2Query.processQuery}", Object.class, QueryEvent.class, queryEvent);
}

private RichTable moduleTable;

public void setModuleTable(RichTable moduleTable){
this.moduleTable = moduleTable;
}

public RichTable getModuleTable(){
return moduleTable;
}

LOV resizing error: IllegalStateException

When doing a search on a lov then resizing the columns your recieve an error message along the lines of IllegalStateException. Try configuring your columns and table in adf-config file (view menu).

Back button and connection leaks

If your back button behaves badly or connections are not closed when you close the browser and leaky.

On your application module try checking "Disconnet Application Module Upon Release" this solved our problem. (Click on your AM, goto configurations, click on the Pooling and scalibility tab)