Status

Blog::Calendar

« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today
XML

Blog::Navigation

Blog::Editing

Bookmarks::Blogroll

Blog::Referers

Today''s Page Hits: 120

Other sites

Google Analytics

Powered by Roller Weblogger.
All | Music | General | Java | ZK | Android | JBoss&Seam | JSF
Main | Next page »
20110319 Saturday March 19, 2011
Some zk5 client side examples in this article, I will keep append some ZK 5 client examples just for memorizing.

Client side selector and widget test



Hello, World! 

Client side confirm


    

To be Continued

20110111 Tuesday January 11, 2011
My first android app. daily-money

daily-money is a simple android application that helps me to record daily expanses, monthly incomes and assets.
the main idea comes from a desktop application "Money Assistant", I have used this app to record my expenses more than 5 years. however it is out of maintenance and for windows only (I have give up windows).
Because of I quit my last job last month and not yet find next job, so, I spent two days reading android doc and 6 days writing application, Daily-Money.

The main function of this application is free and open. I will write some report activity also in this month if i still a free man.

you can download the apk here if you want to : Daily-Money

Here is some screenshoots:


Too bad, After I registered android developer and paid the fee (it costs US$ 25, what the F..riend.), when uploading apk file.....I found I don't have my application icon. all the icons are come from.......android source code!!, could someone helps me to do the art?.
20101208 Wednesday December 08, 2010
Custer/Failover developing guide line in Jboss + Seam
  1. 該Serializable就Serializable, 不該的, 就用transient 和 cache的觀念來作, 拿不到就重拿.
  2. Serializable不能有loop (A->B, B->A)
  3. 嚴重不建議用conversation scope的entity bean, 在failover時, set的關聯會出錯 (我建議ui可以用conversation scope, 因為ajax方便, 但entity最好還是走老路, 每次重新refresh, 不要用conversation, 這樣問題才少)
  4. Temp file跟temp url 一樣要用cache的觀念, 要用transient, 拿不到的時才就重新產生. (因為failover過去, 那裏並沒有這裏產生的temp file可以用呀!!)
  5. 不要在Object的建構子裏拿Seam component (如果object也是seam component,可以在@Create, 或是用lazy 的方式), failover時newInstance會因為沒有Seam context出錯
  6. 任何Seam component, 都不能留下reference (除非只留到當前的event scope), 需要的時候再拿.否則failover時, re-assign member filed會出錯. (可利用留下name加cache的觀念來玩)
  7. facelets.REFRESH_PERIOD要設成-1, 否則在failover時, 頁面會被recreate成另一個component tree, client tree跟server tree不一樣, 在接序下來的ui action都會應對應不上而出錯.
  8. About dynamic class loader above webap class loader, 所有用DCL建出來的Object, 都該由自建的serialize跟deserialize來作, 不能直接交由webap的class loader, 否則在failover deserialize時會load不到對應的class而出現class not found error.
20100607 Monday June 07, 2010
zkseam2, integrates ZK with Seam context

zkseasm2 - My parttime project that provides ZK and Seam2 integration.

project site : http://code.google.com/p/zkseam2/

Features of zkseam2

Seam components as ZK variables

You can access seam component as ZK variables in zscript or EL

zscript

You can directly use seam components as a variables in zscript. Following example shows how to persist a new Item entity by entityManager(Seam component, a J2EE EntityManager) in zscript.

data binding

Binding value to todoCtrl.current.name, todoCtrl could be a EJB or a JAVA Bean type Seam component.

i18n messages

Both ZK and Seam provide a i18n messages feature, if you want to access Seam i18n messages in ZK, you could use EL and access messages (a map type Seam component) with a string type message key.

Binding Seam Conversation Scope with ZK desktop

start a conversation

To start a Seam conversation and binding it to ZK desktop, you use DesktopConversaton.begin. After this invocation, I will eanble a long running Seam conversation and lifecyle is binding with ZK Deskotp, in the words, you will get same conversation scope Seam component in same desktop.
DesktopConversation.begin();
You usually begin a conversation in a conversation scope seam controller's creation method. for example :
@Name("winCtrl")
@Scope(ScopeType.CONVERSATION)
public class WinCtrl {
  @Create
  public void create(){
    DesktopConversation.begin();
  }
}

end a conversation

To end a Seam conversation and unbinding with ZK desktop, just call DesktopConversation.end()
DesktopConversation.end();
The conversation will be destroyed automatically when the desktop cleanup by zkau request or conversation timeout.

Inject ZK components into Seam component

inject implicit object

The string 'desktop','page'..etc are keywords to get these instance.
    @In(value="desktop",required=false)
    Desktop desktop;

    @In(value="page",required=false) //the first page in current desktop
    Page page;

    @In(value="execution",required=false)
    Execution exec;

inject named component

    @In(value="mypage1",required=false)
    Page page;

    @In(value="win",required=false)
    Window window;
    
    @In(value="win.btn",required=false)
    Button btn;
    
    @In(value="win.tb",required=false)
    Textbox textbox;
Until now, I have no idea how to bind zk IdSapce in seam, if you want to inject a component, you have to know the component path and replace the path character '/' by '.'.

Seam component as an action listener

action listener annotation in zul

To enable this, you have to add a zk directive as follow

<?init class="com.infinitiessoft.zkseam.zk.AnnotateActionBinderInit"?>

20100506 Thursday May 06, 2010
A solution that fixes accessing Seam components bug in multiple WAR in a EAR
Seam is a great web-bean framework indeed.
However, It has a limitation when running EAR with multiple WAR.
look into the code of Lifecycle and ServletLifecycle, you can see it store applicationContext in 'static' way.
which means , if you have multiple WAR in a EAR, the last initialized WAR become the application context of entire EAR.
It doesn't matter if you only access Seam component in JSF page/event, because FacesLifecycle provide another way to retrieve application context.
but, if you want to access Seam component in a custom servlet or in a thread (for example:Timer, Scheduler), you will always get the last registered application(WAR module) and it might be wrong one if servlet and thread are running for another WAR module.
Following is the example to access Seam component in servlet and thread.
[Access Seam component in Servlet]
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        ServletLifecycle.beginRequest(request);
        try{
            Requests.instance().setRequest(request);
            // do some thing.
        }finally{
            ServletLifecycle.endRequest(request);
        }
    }
[Access Seam component in Thread]
public void run() {
    Lifecycle.beginCall();
    try{
        //do something
    }finally{
        Lifecycle.endCall();
    }
}
Since Lifecycle and ServletLifecycle handle application context in static, so you might get wrong application when use it.
To solve this , we have to know which application context we needed when we want to initial Seam Thanks Open Source, after deep into the code, I has a chance to fix it.
I wrote two Lifecycle Util and one seam component to workaround it.
[LifecycleEx] : helps you to retrieve application by name.
package org.jboss.seam.contexts;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.jboss.seam.ScopeType;
import org.jboss.seam.core.Manager;
import org.jboss.seam.log.Log;
import org.jboss.seam.log.Logging;
/**
 * A enhanced lifecycle controller for running seam in multiple war
 * 
 * @author dennis
 */
public class LifecycleEx {
    
    private static String NULL_APP_NAME = "LifecycleEx.NULL.APPNAME";
    private static Map<String,Object> defaultApplication = null;
    private static Map<String,Map<String,Object>> applications = new HashMap<String,Map<String,Object>>();
    private static List<Map<String,Object>> applicationList = new LinkedList<Map<String,Object>>();
    private static final Log log = Logging.getLog(LifecycleEx.class);
    
    static public void registerApplication(String name,Map<String,Object> application){
        
        name = name == null?NULL_APP_NAME:name;
        
        if(applications.containsKey(name)){
            log.warn("trying to register application '#0' again",name);
        }
        
        applications.put(name,application);
        applicationList.add(application);
        
        defaultApplication = application;
    }
    
    static public void unregisterApplication(String name){
        name = name == null?NULL_APP_NAME:name;
        
        Map<String,Object> app = applications.remove(name);
        
        if(app!=null){
            applicationList.remove(app);
            if(app==defaultApplication){
                if(applicationList.size()>0){
                    //last one
                    defaultApplication = applicationList.get(applicationList.size()-1);
                }else{
                    defaultApplication = null;
                }
            }
        }
    }
    
    static Map<String,Object> getApplication(String name){
        return getApplication(name,false);
    }
    
    /**
     * get Application context by name, if no application context found, then try to get default application context (the last registered)
     * @param name name of application
     * @param as_possible true: if get application not found, then return default application 
     * @return RuntimeException if no application found.
     */
    static Map<String,Object> getApplication(String name,boolean as_possible){
        name = name == null?NULL_APP_NAME:name;
        
        Map<String,Object> app = applications.get(name);
        if(app==null&&as_possible){
            log.debug("name #0 not found, use default application",name);
            app = defaultApplication;
        }
        if(app==null){
            throw new RuntimeException("application "+name+" not found ");
        }
        return app;
    }
    
    public static void setupApplication(String name)
    {
       Contexts.applicationContext.set( new ApplicationContext(getApplication(name)) );
    }

    public static void cleanupApplication()
    {
       Contexts.applicationContext.set(null);
    }
    
    static void clearThreadlocals() 
    {
       Contexts.eventContext.set(null);
       Contexts.pageContext.set(null);
       Contexts.sessionContext.set(null);
       Contexts.conversationContext.set(null);
       Contexts.businessProcessContext.set(null);
       Contexts.applicationContext.set(null);
    }
    
    public static void beginCall(String appname){
        beginCall(appname,false);
    }
    
    public static void beginCall(String appname,boolean as_possible)
    {
       Contexts.applicationContext.set( new ApplicationContext(getApplication(appname,as_possible)) );
       Contexts.eventContext.set( new BasicContext(ScopeType.EVENT) );
       //TODO should we initial session?? 
       Contexts.sessionContext.set( new BasicContext(ScopeType.SESSION) );
       Contexts.conversationContext.set( new BasicContext(ScopeType.CONVERSATION) );
       Contexts.businessProcessContext.set( new BusinessProcessContext() );
    }

    public static void endCall()
    {
       try
       {
          Contexts.destroy( Contexts.getSessionContext() );
          Contexts.flushAndDestroyContexts();
          if ( Manager.instance().isLongRunningConversation() )
          {
             throw new IllegalStateException("Do not start long-running conversations in direct calls to EJBs");
          }
       }
       finally
       {
          clearThreadlocals();
       }
    }
}
[ServletLifecycleEx] : helps you to retrieve application by name.
package org.jboss.seam.contexts;

import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.jboss.seam.log.Log;
import org.jboss.seam.log.Logging;
import org.jboss.seam.servlet.ServletApplicationMap;
import org.jboss.seam.servlet.ServletRequestMap;
import org.jboss.seam.servlet.ServletRequestSessionMap;
import org.jboss.seam.web.Session;
/**
 * A enhanced servlet lifecycle controller for running seam in multiple war
 * @author dennis
 */
public class ServletLifecycleEx {

    private static final Log log = Logging.getLog(ServletLifecycleEx.class);
    
    static public void registerApplication(String name,ServletContext context){
        log.info("Register application context name #0",name);
        Map<String,Object> application = new ServletApplicationMap(context);
        LifecycleEx.registerApplication(name,application);
        
    }
    
    static public void unregisterApplication(String name){
        log.info("Unregister application context name #0",name);
        LifecycleEx.unregisterApplication(name);
        
    }
    
    public static void beginRequest(String path,HttpServletRequest request){
        log.debug( "begin web request #",path );
        Contexts.eventContext.set( new EventContext( new ServletRequestMap(request) ) );
        Contexts.sessionContext.set( new SessionContext( new ServletRequestSessionMap(request) ) );
        Contexts.applicationContext.set(new ApplicationContext( LifecycleEx.getApplication(path) ) );
        Contexts.conversationContext.set(null); //in case endRequest() was never called
    }
    
    public static void endRequest(HttpServletRequest request) {
        log.debug("After request, destroying contexts");
        try
        {
           Session session = Session.getInstance();
           boolean sessionInvalid = session!=null && session.isInvalid();
           
           Contexts.flushAndDestroyContexts();

           if (sessionInvalid)
           {
              LifecycleEx.clearThreadlocals();
              request.getSession().invalidate();
              //actual session context will be destroyed from the listener
           }
        }
        finally
        {
            LifecycleEx.clearThreadlocals();
        }
    }
}
[SeamLifecycleEx] : this component is for registering application context into LifecycleEx and ServletLifecycleEx.
package foo.bar;

import java.util.Map;
import javax.servlet.ServletContext;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.Startup;
import org.jboss.seam.contexts.Lifecycle;
import org.jboss.seam.contexts.LifecycleEx;
import org.jboss.seam.contexts.ServletLifecycle;
import org.jboss.seam.contexts.ServletLifecycleEx;
import org.jboss.seam.log.Log;
import org.jboss.seam.log.Logging;

@Name("foo.bar.SeamLifecycleEx")
@Scope(ScopeType.APPLICATION)
@Startup @AutoCreate
public class SeamLifecycleEx {

    private static final Log log = Logging.getLog(SeamLifecycleEx.class);
    
    private String _name;
    
    @Create
    public void create(){
        log.debug("Initial SeamLifecycleEx");
        ServletContext context = ServletLifecycle.getServletContext();
        if(context==null){
            log.warn("servlet context not found, did you initial seam out of WAR moudle?");
            Map<String,Object> currentApplication= Lifecycle.getApplication();
            LifecycleEx.registerApplication(null,currentApplication);
            return;
        }
        _name = context.getContextPath();
        //in mock/test , _name is null
        if(_name!=null && _name.startsWith("/")){
            _name = _name.substring(1);
        }
        log.debug("register servlet application context with name #0 ",_name);
        ServletLifecycleEx.registerApplication(_name,context);
    }
    
    @Destroy
    public void destroy(){
        ServletLifecycleEx.unregisterApplication(_name);
    }
}
Ok, Now you have 3 java class, you have to put first 2 java into seam package (the package level protected issue) and put the seam component to where you want.
I don't want to explain how the code work, since you have my code, you can read it by yourself.
now, following is the example when you want to access Seam component in your servlet and thread.
[Access Seam component in Servlet]
    protected String name;

    public void init() throws ServletException {
        super.init();
        if(name.startsWith("/")){
            name = name.substring(1);
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        ServletLifecycleEx.beginRequest(name,request);
        try{
            Requests.instance().setRequest(request);
            // do some thing.
        }finally{
            ServletLifecycleEx.endRequest(request);
        }
    }

[Access Seam component in Thread]
 // in thread, name is a configured string usually.
public void run() {
    LifecycleEx.beginCall(name,true);
    try{
        //do something
    }finally{
        LifecycleEx.endCall();
    }
}
20100326 Friday March 26, 2010
Got "java.sql.SQLException: You cannot commit with autocommit set!"
[Read More]
Copyright (C) 2003, 閣樓貓的五四三 (About Cat)