Two forms glued when I used div tam.
Originally form and div tag is 100% occupied, but if div and form tag used, it will be shown like a row.

<td norwap align=center>
    <div id="row1" style="float:left;">

     <form id="form_modify_${item.id}" method="post" action="/under/emergency.nhn" style="width: 21px;">
      <fieldset>
       <input type="hidden" name="m" value="edit" />
       <input type="hidden" name="underid" value="${item.id}" />
       <input type="image" src="/alive/userdefinedurl/modify.png" onmousedown="this.form.m.value='edit'" />
      </fieldset>
     </form>
    </div>
    <div id="row2"  style="float:left;">
     <form id="form_delete_${item.id}" method="post" action="/under/emergency.nhn" style="width: 21px;">
      <fieldset>
       <input type="hidden" name="m" value="edit" />
       <input type="hidden" name="underid" value="${item.id}" />
       <input type="image" src="/common/images/remove.gif"  onmousedown="this.form.m.value='delete'" />
      </fieldset>
     </form>
    </div>
   </td>

'Web service' 카테고리의 다른 글

아파치 설정 - if/else then  (0) 2009.08.18
두 form을 한 줄로 보여주기  (0) 2009.07.15
How to support UTF-8 URIEncoding with Tomcat  (0) 2009.06.15
SelectKey in insert statement in mysql  (0) 2009.06.05
Weakness of Java Web Start  (0) 2009.04.27
Posted by '김용환'
,

    <Connector acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" enableLookups="false" maxHttpHeaderSize="8192" maxSpareThreads="75" maxThreads="150" minSpareThreads="25" port="80" redirectPort="8443" URIEncoding="UTF-8"  />


Edit conf/server.xml and find the line where the Coyote HTTP Connector is defined. Add a URIEncoding="UTF-8 like above.

By default, Tomcat uses ISO-8859-1 character encoding. So, you need to change it to use UTF8 uriencoding with Tomcat.

For other information, If you use eclipse IDE, you may fail to use UTF8 tomcat. At the time, you should clean WTP cache.

Posted by '김용환'
,


The order of selectKey tag is important. Below is right, but if selectKey tag located just after insert tag, it can out get index id.

 <insert id="insertUserDefinedURLData" parameterClass="UserDefinedURLData">
  INSERT INTO userdefine_url
   (projectname, url, expected, charset, sms, mail, name, companyID, precallURL)
  VALUES
   (#projectName#, #url#, #expected#, #charset#, #sms#, #mail#, #name#, #companyID#, #precallURL#)
   <selectKey keyProperty="id" resultClass="int">
            SELECT LAST_INSERT_ID()
        </selectKey>  

 </insert>
Posted by '김용환'
,

There are many uncomportable points to use java web start as belows referenced sites.
- user experience is not familar
- detecting java web start is some terrible

Finally they recommand native application launcher.


Reference Sites

http://kylecordes.com/2006/04/08/auto-update-no-web-start/
http://joust.kano.net/weblog/

Posted by '김용환'
,

<상황>
jdk6
ojbdc14.jar (오라클 9i)
commons-dbcp
commons-pool
rac 사용



오라클의 RAC를 사용하면 아래와 같이 connection timeout를 위한 URL을 사용한다.

Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@(DESCRIPTIO
N = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP) (HOST = krtest1) (PORT = 1521)) 
(ADDRESS = (PROTOCOL = TCP) (HOST = krtest2) (PORT = 1521))) (CONNECT_DATA = 
(SERVICE_NAME = MIKE.us.oracle.com))) ", "scott", "tiger");

jdbc-thin driver를 사용할 때, JDBC에서는 리스너가  죽어있으면, 다음 설정으로 연결하게 된다.
즉, host krtest1의 1521포트에 접근했다가 connection time out이 나면, krtest2의 1521번으로 접속하게 된다. 그런데, 문제가 있다..

down이나 connection timeout일 때는 확실하게 문제가 있는데 반해서, session이 한 번 연결되었을 때, 다른 instance로 자동 연결되는 TAF(Transparent Application Failover)를 지원하지 않는다는 점을 유의해야 한다..

만약  비정상적인 종료시에는 tcp 연결중 close ack가 정상적으로 가지 못해서 아래와 같은 에러가 발생할 수 있다. 
java.sql.SQLException: IO 예외 상황: Broken pipe
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:179)
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:333)
at oracle.jdbc.driver.OracleConnection.setAutoCommit(OracleConnection.java:1224)

또는 아래와 같은 비슷한 문제가 일어날 수 있다는 점이다.
java.sql.SQLException: 소켓에서 읽을 데이터가 없습니다
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:179)
at oracle.jdbc.dbaccess.DBError.check_error(DBError.java:1160)
at oracle.jdbc.ttc7.MAREngine.unmarshalUB1(MAREngine.java:963)
at oracle.jdbc.ttc7.MAREngine.unmarshalSB1(MAREngine.java:893)
at oracle.jdbc.ttc7.Ocommoncall.receive(Ocommoncall.java:104)
at oracle.jdbc.ttc7.TTC7Protocol.setAutoCommit(TTC7Protocol.java:559)
at oracle.jdbc.driver.OracleConnection.setAutoCommit(OracleConnection.java:1288)
at org.apache.commons.dbcp.DelegatingConnection.setAutoCommit(DelegatingConnection.java:331)
at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.setAutoCommit(PoolingDataSource.java:317)

또한, DB쪽에서 먼저 session을 끊을 수도 있을 때. 이때도 다음번 ip로 이동하지 않을 수도 있다.

내 생각엔 connection은 있지만, session은 끊어진 황당한 상태라 할 수 있었다. 이 부분에 대한 명확하게 설명해 놓은 자료가 없어서. 소스를 뜯어보면서 생각하고 있다. (다음 번 글에는 정리된 글을 쓸 수 있을 것 같다.)

과거에는 이런 문제를 해결하기 위해서는 idle되는 connection을 네트웍단에서 끊는 작업을 하였다고 한다. 또는 지금도 이렇게 진행하고 있기도 .. 

오라클에서는 이런 문제를 해결하는 솔루션을 제시했는데..
TAF는 OCI 라이브러리를 통해 자동적으로 수행됩니다. 따라서 TAF를 사용하기 위해 애플리케이션 (클라이언트) 코드를 변경할 필요는 없습니다. 하지만 Oracle TNS 파일(tnsnames.ora) 파일에 몇 가지 설정 작업이 필요합니다.
(출처: http://blog.empas.com/myungho/read.html?a=18405273)

이 뒤를 보면 쑈킹하다.
(Java 씬 클라이언트의 경우 아직까지는 tnsnames.ora에 접근하기 위한 기능이 제공되지 않기 때문에 TAF에 참여할 수 없습니다.)

역시 thin client에서는 어쩔 수 없는 한계에 봉착한다. 즉 ora파일 만지는 얘들은 자연스럽게 문제가 쉽게 해결 수 있는 부분이 있다는 것이다.

IBM WebSpere는 이런 부분에서 일찍 고민을 했었다.
(http://www.javaservice.net/~java/bbs/read.cgi?m=appserver&b=was&c=r_p&n=967473008)
고객은 DataBase의 일시적인 장애복구 상황에서도 자동으로 WebSphere의 "DB Pool Connection Recovery" 기능을 요구하고 있습니다...
<중략>
JDBC 1.0 스펙상에는 DB Connection Pooling 기능에 대한 언급이 존재하지 않았습니다.
<중략>
그러나 최근 JDBC 2.0 Specifiaction 이 SunmicroSystem 의해 발표된 후 대부분의 DB Vendor들을 이를 지원하게 되었으며, Oracle의 경우 Version 8.1.6 부터 JDBC 2.0을 지원하고 있습니다.
따라서, DB Connection Pool기능과 그것의 구현과정에서 transparent하게 DB Connection Recovery 기능을 제공해야 하는 책임을 갖고 있는 곳은 이젠 DB Vendor에 달려 있게 됩니다.
<중략>
Oracle의 경우 Oracle 8i Release 2 ( 8.1.6 ) 부터 JDBC 2.0 을 지원하고 있습니다. 그러나, 현재 H은행에서 사용되고 있는 형태인 JDBC Type 4 Thin Driver는 Transparent한 FailOver 기능을 아직 제공하지 않고 있습니다.
<중략>
Transparent한 DB Connection Recovery 기능을 구현하려면 매 호출시마다, Pool에 기연결되어 있는 Connection이 가용한 것인지를 확인하기 위해 SQL Query를 날려보아야 합니다.

그떄의 내용과 달리현재 오라클 JDBC URL에 따르면, Tranparent FailOver지원여부는 안나타나서 모르겠다. 그냥 failover만 지원된다고 나온다. 
http://www.oracle.com/technology/tech/java/sqlj_jdbc/htdocs/jdbc_faq.html
failover supported?

Yes. When you are connecting to a RAC server, Fast Connection Failover provides rapid response to failure events. This new High-Availability feature is driver independent and works in conjunction with the Implicit connection cache and RAC to provide maximum availability of connections in the cache. This is achieved by processing RAC's down events to remove invalid connections and up events to load balance existing connections.

If you are using the OCI driver and all you need is query fail-over, you might consider TAF. TAF primarily facilitates query failover in an application. It is not a general fail-over mechanism. Note that Fast Connection Failover and TAF can't be used together. Only one may be enabled and used at a time. 

* Fast Connection Failover라는 단어가 나왔다. 공부할 것이 생겼다. 대충 글 밑에 보면 이 설명이 있다. 오라클 10g에서는 지원한다.
* JDBC 스펙 2.0을 공부할 필요가 있다. (현재는 JDBC 4.0[2006.11)이 나왔다~) (공부많이 해야 겠다.: http://java.sun.com/products/jdbc/download.html)

과거 문서에 따르면, Tranparent하게 DB connection recovery를 하려면, 호출마다 pool에 연결되어 있는 connection을 체크하는 로직이 바로 TAF라고 한 것이다.

옛날 문서이니 신뢰할 수없다. 혹시 jdbc 2.0 부터는 이런 게 있을 까 확인해봤더니. 존재 한다. ㅎㅎ
결국 thin driver도 내부적으로 지원은 하는 셈이다.

JDBC OCI Application Failover Callbacks--OCIFailOver.java(http://download.oracle.com/docs/cd/A91773_01/ids902dl/web.902/a90211/samapp.htm)

아래 내용을 보자.

JDBC OCI Application Failover Callbacks--OCIFailOver.java

This sample demonstrates the registration and operation of JDBC OCI application failover callbacks.

For information on Transparent Application Failover (TAF) and failover events, see "OCI Driver Transparent Application Failover".

/* 
 * This sample demonstrates the registration and operation of
 * JDBC OCI application failover callbacks
 * 
 * Note: Before you run this sample, set up the following
 *       service in tnsnames.ora: 
 *       inst_primary=(DESCRIPTION=
 *             (ADDRESS=(PROTOCOL=tcp)(Host=hostname)(Port=1521))
 *             (CONNECT_DATA=(SERVICE_NAME=ORCL)
 *                           (FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC))
 *             )
 *           )
 *       Please see the Oracle Net Administrator's Guide for more detail about 
 *       failover_mode
 *
 * To demonstrate the the functionality, first compile and start up the sample,
 *    then log into sqlplus and connect /as sysdba. While the sample is still 
 *    running, shutdown the database with "shutdown abort;". At this moment, 
 *    the failover callback functions should be invoked. Now, the database can
 *    be restarted, and the interupted query will be continued.
 */

// You need to import java.sql and oracle.jdbc packages to use
// JDBC OCI failover callback 

import java.sql.*;
import java.net.*;
import java.io.*;
import java.util.*;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleOCIFailover;


public class OCIFailOver {

  static final String user = "scott";
  static final String password = "tiger";
  static final String driver_class = "oracle.jdbc.OracleDriver";

  static final String URL = "jdbc:oracle:oci8:@inst_primary"; 


  public static void main (String[] args) throws Exception {

    Connection conn = null;
    CallBack   fcbk= new CallBack();
    String     msg = null;
    Statement  stmt = null;
    ResultSet rset = null; 
 
    // Load JDBC driver
    try {
      Class.forName(driver_class);
    }
    catch(Exception e) {
      System.out.println(e);
    }

    // Connect to the database
    conn = DriverManager.getConnection(URL, user, password);

    // register TAF callback function
    ((OracleConnection) conn).registerTAFCallback(fcbk, msg);

    // Create a Statement
    stmt = conn.createStatement ();

    for (int i=0; i<30; i++) {
      // Select the ENAME column from the EMP table
      rset = stmt.executeQuery ("select ENAME from EMP");

      // Iterate through the result and print the employee names
      while (rset.next ()) 
        System.out.println (rset.getString (1));

      // Sleep one second to make it possible to shutdown the DB.
      Thread.sleep(1000);
    } // End for
 
    // Close the RseultSet
    rset.close();

    // Close the Statement
    stmt.close();

    // Close the connection
    conn.close();


  } // End Main()

} // End class jdemofo 


/*
 * Define class CallBack
 */
class CallBack implements OracleOCIFailover {
   
   // TAF callback function 
   public int callbackFn (Connection conn, Object ctxt, int type, int event) {

     /*********************************************************************
      * There are 7 possible failover event
      *   FO_BEGIN = 1   indicates that failover has detected a 
      *                  lost conenction and faiover is starting.
      *   FO_END = 2     indicates successful completion of failover.
      *   FO_ABORt = 3   indicates that failover was unsuccessful, 
      *                  and there is no option of retrying.
      *   FO_REAUTH = 4  indicates that a user handle has been re-
      *                  authenticated. 
      *   FO_ERROR = 5   indicates that failover was temporarily un-
      *                  successful, but it gives the apps the opp-
      *                  ortunity to handle the error and retry failover.
      *                  The usual method of error handling is to issue 
      *                  sleep() and retry by returning the value FO_RETRY
      *   FO_RETRY = 6
      *   FO_EVENT_UNKNOWN = 7  It is a bad failover event
      *********************************************************************/
     String failover_type = null;

     switch (type) {
         case FO_SESSION: 
                failover_type = "SESSION";
                break;
         case FO_SELECT:
                failover_type = "SELECT";
                break;
         default:
                failover_type = "NONE";
     }

     switch (event) {
      
       case FO_BEGIN:
            System.out.println(ctxt + ": "+ failover_type + " failing over...");
            break;
       case FO_END:
            System.out.println(ctxt + ": failover ended");
            break;
       case FO_ABORT:
            System.out.println(ctxt + ": failover aborted.");
            break;
       case FO_REAUTH:
            System.out.println(ctxt + ": failover.");
            break;
       case FO_ERROR:
            System.out.println(ctxt + ": failover error gotten. Sleeping...");
            // Sleep for a while 
            try {
              Thread.sleep(100);
            }
            catch (InterruptedException e) {
               System.out.println("Thread.sleep has problem: " + e.toString());
            }
            return FO_RETRY;
       default:
            System.out.println(ctxt + ": bad failover event.");
            break;
       
     }  

     return 0;

   }
}


이렇게 Oracle JDBC Driver에서는 내부적으로 지원은 한다. 이렇게 oracle에 대해서는 특별히 따로 코드로 형태로 지원이 필요할 것으로 보인다. 
하지만  쓰지 않는다면, 궁금적으로 해결이 어렵지 않나 생각이 든다.


곰곰히 생각해보건데.. 
현재의 Thin driver를 사용할 때는 RAC url을 사용할 때는 Connection time failover(CTF)는 되지만, RAC에서 TAF가 안된다고 우선 결정을 내려야 할 것 같다.
오라클 10g ojdbc thin 드라이버에서는 이걸을 지원하는지 문서를 작성해봐야겠다. 지원은 하는 것처럼 쓰여져 있는데. 된다, 안된다. 이런 의견이 분분하다.

우선, 오라클 10g driver의 특성인 Fast Connection Failover(FCF)는 thin driver에는 지원이 된다. 그리고, TAF만 OCI를 지원하는 케이스이니. 잘 하면 되지 않을 까 싶다. 역시 테스트는 해봐야겠지?

Oracle® Database JDBC Developer's Guide and Reference
10g Release 2 (10.2)

http://download.oracle.com/docs/cd/B19306_01/java.102/b14355/fstconfo.htm#CIHJBFFC

Application-level connection retries

Fast Connection Failover supports application-level connection retries. This gives the application control of responding to connection failovers. The application can choose whether to retry the connection or to rethrow the exception. TAF supports connection retries only at the OCI/Net layer.


그리고, 다음 내용도 훑어볼 필요가 있다.

How It Works

Under Fast Connection Failover, each connection in the cache maintains a mapping to a service, instance, database, and hostname.

When a database generates a RAC event, that event is forwarded to the JVM in which JDBC is running. A daemon thread inside the JVM receives the RAC event and passes it on to the Connection Cache Manager. The Connection Cache Manager then throws SQL exceptions to the applications affected by the RAC event.

A typical failover scenario may work like this:

  1. A database instance fails, leaving several stale connections in the cache.

  2. The RAC mechanism in the database generates a RAC event which is sent to the JVM containing JDBC.

  3. The daemon thread inside the JVM finds all the connections affected by the RAC event, notifies them of the closed connection through SQL exceptions, and rolls back any open transactions.

  4. Each individual connection receives a SQL exception and must retry.


대충 내용을 보면, RAC 이벤트를 java에 받아서 connection을 처리할 수 있도록 한다는 것이다. 구글링을 보면, 명확치는 않다. 테스트가 필요하다.

한편 오라클 9i의 ojdbc14.jar를 쓰고 있는 상황에서 웹 어플리케이션 내에서의 reconnect(TAF처럼) 처리가 되려면, 방법은 오직 하나이다.
commons-dbcp의 testXXX 옵션을 쓰는 것외에는 방법이 없다. 
내부적으로 보면, connenection은 내부적으로 쓰고 있다. 이것을 고칠 방법은 setConnection을 호출해야 된다.

그래서 ValidationQuery, testWhileIdle를 이용하는 것 외에는 그다지 session failover를 이겨낼 방법이 없다. 샘플은 다음과 같다. hard parsing이 아닌 아주 간다한 soft parsing을 하는 select 1 from dual을 쓴다.그리고, testOnBorrow, testOnReturn 은 false로 쿼리 날아갈 때마다 부하를 주지 않도록 한다.
그리고, numTestsPerEvictionRun을 이용하여 3개씩 한번에 1분(timeBetweenEvictionRunsMillis)에 한번씩 체크하도록 한다.

            <property name="validationQuery" value="SELECT 1 FROM dual"/>
            <property name="testOnBorrow" value="false"/>
            <property name="testOnReturn" value="false"/>
            <property name="testWhileIdle" value="true"/>
            <property name="timeBetweenEvictionRunsMillis" value="60000"/>
            <property name="numTestsPerEvictionRun" value="3"/>
            <property name="minEvictableIdleTimeMillis" value="-1"/>
            <property name="maxWait" value="3000"/>
            <property name="queryTimeout" value="7"/>


많이 공부해야겠어..
Posted by '김용환'
,

JSTL을 사용하면 EL이 되어 매우 편하다.

 

<c:out value="<%=request.getParameter("aaa")%>"/> 요런게

<c:out value="${param.aaa}"/> 일케 되니 보기도 좋고 얼마나 편한가!!

 

자신이 만드는 Custom Tags에서도 매우 쉽게 attribute 값을 받을 때 EL을 사용할 수 있다.

단 jstl 의 standard.jar 에 의존적이다.

 

* 입력값으로 null을 허용하지 않는 attribute에 대한 EL처리

   org.apache.taglibs.standard.tag.el.core.ExpressionUtil 사용

   JSTL의 out tag 소스를 살펴보면 다음과 같은 부분이 있다

this.value = ExpressionUtil.evalNotNull(
                    "out",           // 태그명 <c:out 이니까 out
                    "value",        // 속성명 
                    value,          // EL속성으로 넘어온 값(EL표현식)

                    Object.class,  // 반환될 값으로 기대되는 클래스타입
                    this,
                    pageContext)

 

* 입력값으로 null을 허용하는 attribute에 대한 EL처리  

  org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager 사용

   JSTL의 if tag의 소스중에는 다음과 같은 부분이 있다.

Object r = ExpressionEvaluatorManager.evaluate(
                  "test",          // 속성명

                   test,            // EL속성으로 넘어온 값(EL표현식)

                   Boolean.class,  // 반환될 값으로 기대되는 클래스타입

                   this,

                   pageContext);

 

요것이 value값을 받아서 EL 처리 (해당 el 파싱 및 적당한 scope에서 객체 얻어오기) 를 하는거이다.

 

저걸 내 CustomTag의 Attribute별 setter 에 넣어주면 된다.

예를 들자면 다음과 같겠다..

페이징 태그의 현재 페이지 값으로 EL을 사용할 수 있게 한 것이다.

    public void setPage(String page) {
        try {

            // page 값을 el 이라 생각하고 값 찾아봄. 없으면 JspException 이나 NullAttributeException 이 던져질것임
            Integer value = (Integer)ExpressionUtil.evalNotNull(
                                                         "paging",
                                                         "page",
                                                          page,
                                                         Integer.class,
                                                         this,
                                                         pageContext);

             this.cpage = value.intValue();
        } catch (Exception ex) {

            // EL에 실패하면 page값을 el이 아니라 생각하고 할당함

            try {
                this.cpage = Integer.parseInt(page);
            } catch (Exception e) {
                this.cpage = 1;
            }
        }       
    }

 

이렇게 하면 페이징 태그에서 <paging:page page="${qpage}" ..... />

이런식으로 사용가능하다, 물론 el이 알아서 4개 scope를 모두 뒤져서 알아서 찾아주니

qpage라는 name으로 4개 scope어디에 박아넣던 상관없다.

 

Posted by '김용환'
,

build.xml for deploying java servlet on tomcat container

Posted by '김용환'
,

SOA & Web Services Tutorials

(http://www.roseindia.net/webservices/)

 

 

 

SOA & Web Services Tutorials in this site helps you learn more about service-oriented architecture (SOA) and web services. So, why wait learn SOA & Web Services now.
  1. What is SOA (Service Oriented Architecture)?
    An introduction to the Service Oriented Architecture.    
      
  2. Web Services - An Introduction
    The next generation of distributed computing has arrived. A Web service is a unit of managed code that can be remotely invoked using HTTP, that is, it can be activated using HTTP requests.    
       
  3. Why Web Services?
    In this section of WebServices tutorials series we will understand why Web Services are developed and what are the benefits of using Web Services for  the development of  Enterprise applications.   
         
  4. J2EE Web Service Development with Attachments Using Axis
    This article discusses the development of a java web service that takes DIME or MIME attachment as input and returns the output as an appropriate attachment. (Author: Murthy Vaddiparthi)
      
        
    Building a Simple Web Service by Jeevaraj Gnanaselvan Dhanaraj (jeevaraj_1970@yahoo.com)
  5. Developing Simple Web Service
    In this tutorial we will create a simple web service and a client web application using eclipse IDE along with Lomboz plug in. We will also deploy and test the web service on Tomcat 5.5.4 web application server. This application, while simple, provides a good introduction to Web service development and some of the Web development tools available.

     
    Web Services Tutorials by R.S.RAMASWAMY (rs.ramaswamy@gmail.com)
  6. Exposing a javabean (jws)  from Tomcat/Axis
    In this experiment, we attempt  exposing a javabean (jws)  from Tomcat/Axis and consuming that service in an ASP.net program.
       
  7. Understanding Apache Axis
    Apache Axis can be thought of as an improved implementation of Apache SOAP.  While Apache SOAP used DOM for XML parsing, Axis makes use of SAX and hence it is more efficient and fast.  Secondly, it supports automatic generation of WSDL (Web Service Description Language) file.
         
  8. Creating and testing an EJB in WebLogic Server
    In this section you will learn how to create and test an EJB in WebLogic Server.
       
  9. Drop-In Deployment in Apache AXIS
    This tutorial discusses about drop-in deployment in Apache AXIS.
        
  10. Apache AXIS-Deployment using WSDD File
    In this part, we will follow the WSDD method.  We have already created sqlaxisbean.java as explained in the last article.  We used it as sqlaxisbean.jws (drop-in method).  There was no necessity to compile this file.But in WSDD method (web-service deployment descriptor), we should compile this file.Next, we create the WSDD file.  Then, we deploy this bean to tomcat.  We may have to restart the tomcat4.1 webserver.
        
  11. Exposing EJB as XML-Webservice
    In this web service tutorial you will learn how to expose an EJB as XML-Webservice using Axis.
       
  12. Accessing ejb-webservice through WAP
    This tutorial discusses how to Access ejb-webservice  using  WAP (Wireles-Application Protocol) 
       
  13. J2ME CLIENT FOR EJB & EJB-WEBSERVICE
    In  the previous section,we've dealt with how to write WAP client for accessing ejb. In the same way, we are going to see how to write J2ME client for ejb.

    Developing and deploying Web Services on Apache Geronimo Application Server
  14. Understanding Apache Geronimo Application Server
    Apache Geronimo is a open source JavaEE( or J2EE, old name) application server. This section introduces you with the Apacehe Geronimo Application Server.

 

Posted by '김용환'
,

Web Services Tutorials and Links

(http://www.roseindia.net/webservices/web-services-links.shtml)

 

  1. Web services Activity:
    The World Wide Web is more and more used for application to application communication. The programmatic interfaces made available are referred to as Web services. The goal of the Web Services Activity is to develop a set of technologies in order to lead Web services to their full potential. The Web Services Activity Statement explains the W3C's work on this topic in more detail.
      

  2. Web Services Addressing:
    Web Services Addressing 1.0 - Core (WS-Addressing) defines two constructs, message addressing properties and endpoint references, that normalize the information typically provided by transport protocols and messaging systems in a way that is independent of any particular transport or messaging system. A Web service endpoint is a (referenceable) entity, processor, or resource to which Web service messages can be addressed. Endpoint references convey the information needed to address a Web service endpoint. This specification defines a family of message addressing properties that convey end-to-end message characteristics including references for source and destination endpoints and message identity that allows uniform addressing of messages independent of the underlying transport.
      

  3. Web Services Description Language:
    As communications protocols and message formats are standardized in the web community, it becomes increasingly possible and important to be able to describe the communications in some structured way. WSDL addresses this need by defining an XML grammar for describing network services as collections of communication endpoints capable of exchanging messages. WSDL service definitions provide documentation for distributed systems and serve as a recipe for automating the details involved in applications communication. A WSDL document defines services as collections of network endpoints, or ports. In WSDL, the abstract definition of endpoints and messages is separated from their concrete network deployment or data format bindings.
       

  4. Java Web services:
    The Java Web Services Developer Pack (Java WSDP) is a free integrated toolkit you can use to build, test and deploy XML applications, Web services, and Web applications with the latest Web service technologies and standards implementations. With the newest release of the Java WSDP 2.0, developers will be able to: 
    Develop and deploy using the latest XML and Web services technologies slated for inclusion into Sun's deployment platforms. 
    Enhance Web services performance without revising WSDL files or application code with the refreshed Fast Infoset features from Java WSDP 1.6. 
    Create XML and Web service-enabled applications that exploit the enhanced security features with enhanced XWSS features. 
    Continue to enjoy Java interoperability and portability across different platforms and devices. 
    Simplify and lower the cost of legacy application integration, data interchange, and publishing in a Web environment. 
      

  5. Web Services Architect:
    In this article, we have tried to keep a realistic, pragmatic, and balanced approach in determining the return on investment on Web Services. It is worth mentioning that, no matter how promising a new technology is, promoting and encouraging its usage through such articles and papers is not justified until there is a solid business case for its adoption. It is fundamentally important for us to warn about the pitfalls as and where we foresee them, leaving the final decision up to the readers who range from senior management (technical and business), through business analysts, and systems architects, to project managers, and software developers. 
      

  6. Web Services  primer:
    Looking back over the last six years, it is hard to imagine networked computing without the Web. The reason why the Web succeeded where earlier hypertext schemes failed can be traced to a couple of basic factors: simplicity and ubiquity. From a service provider's (e.g. an e-shop) point of view, if they can set up a web site they can join the global community. From a client's point of view, if you can type, you can access services. From a service API point of view, the majority of the web's work is done by 3 methods (GET, POST, and PUT) and a simple markup language. The web services movement is about the fact that the advantages of the Web as a platform apply not only to information but to services. 
      

  7. Web services-Axis:
    Apache Axis is an implementation of the SOAP ("Simple Object Access Protocol") submission to W3C.
    From the draft W3C specification: 
    SOAP is a lightweight protocol for exchanging structured information in a decentralized, distributed environment. It is an XML based protocol that consists of three parts: an envelope that defines a framework for describing what is in a message and how to process it, a set of encoding rules for expressing instances of application-defined data types, and a convention for representing remote procedure calls and responses.
    This project is a follow-on to the Apache SOAP project.
    Please see the Reference Library for a list of technical resources that should prove useful.
       

  8. Getting a Java Web service to work:
    We're deploying an existing Web service application to a new JBoss server by following the "Getting Started with JBoss" manual from www.jboss.org, but the j2eetutorial examples file doesn't seem to match the documentation. The application is ready for deployment, but we can't seem to get the right files in the right places to make things work. Where can we find a JBoss example that works, or some tools to automate the deployment?
    The manual is written for JBoss Version 3.2.3 and Version 1.3.X of the Java Software Development Kit (JSDK). The current production JBoss release is 3.2.4, and using Version 1.4X of the JSDK is recommended. 
      
  9. Web Services ToolKit:
    A software development environment for designing, developing, and executing Web service technologies.WSTK has evolved into the ETTK for Web Services and Autonomic Computing (ETTK-WS). 
    The Emerging technologies team is expanding the scope of the toolkit to include autonomic and grid-related technologies and has therefore rebranded this technology to "ETTK for Web Services and Autonomic Computing" (ETTK-WS) in order to more accurately reflect its role in the new ETTK collection of technologies and prototypes. The ETTK-WS will continue to offer leading-edge prototyping of emerging Web services technologies for recently released specifications. The ETTK-WS can be downloaded here at alphaWorks. The ETTK-WS integrates emerging technologies from IBM Research Labs and IBM Software Groups into a consolidated package to showcase leading-edge technologies that may or may not make it into IBM products. 
      
  10. Internet Web Services:
    Web services are the basis of distributed computing across the Internet. A Web service consumer locates a Web service and invokes the operations it provides. The Web service provider (the application implementing the Web service) can be on the same Java virtual machine as the one using it, or it can be thousands of miles away. Web services use standard Web protocols such as XML, SOAP, and HTTP.
          
  11. What is Web Services resource:
    Many technologies must represent state in a standard fashion in a Web services architecture, such as grid computing and distributed systems management. WSRF is the emerging OASIS Web services standard for modeling and accessing stateful resources using Web services. 
    WSRF for WAS was developed by the WebSphere Application Server (WAS) development team. This technology extends the WAS Web Services run-time environment to support the patterns defined by WSRF, and it enables a Web service to have an association with instances of stateful resources, the composite of which is a stateful "WS-Resource." A WS-Resource has an associated XML document, called a resource properties document, that describes the state of the resource. The resource properties document and the resource it describes may be queried and updated through Web service message exchanges defined in the WSRF specifications. 
    This technology includes a comprehensive sample application illustrating the following: 
    the use of a stateful WS-Resource 
    the means through which its state is queried and updated 
    the well-defined life cycle of the state. 

           
  12. Web Services Language: 
    As expressed in the Statement of Mission and Objectives, the SWSI Language Committee aims to develop computer language technology that will provide a firm, long-term foundation for the future of Web services on the Internet. It is desired that this foundation will support the most general approaches to service deployment and use that are currently technically feasible. 
    The Committee seeks to develop a formal language that allows for rich declarative specification of a wide variety of information about Web services, which will support automation of a broad spectrum of activities related to Web services, such as discovery, selection, composition, negotiation and contracting, invocation, monitoring of progress, and recovery from failure. 
    The committee aims to build on the success of OWL-S, taking the existing language as a starting point, while allowing scope for the revisions and additions necessary to address these new requirements.
                        
  13. WSDL Editor:
    The XMLSpy WSDL editor allows you to create, edit, visualize, and validate any WSDL file. WSDL is a language for describing Web services and is ideally suited as an interface definition language (IDL) for architecting Web services applications. By first building an interface, client and server programmers can implement their respective programming contract using any language or operating system, avoiding interoperability problems. XMLSpy helps you write and validate WSDL documents quickly and easily. The graphical WSDL editor displays the WSDL file structure as well as the WSDL elements grouped by operations, portTypes, bindings, and services. You can manipulate the file by dragging and dropping elements, and context-sensitive windows and entry helpers provide intelligent editing options. 
                        
  14. Feature of WSDL Editor:
    The WSDL Editor offers a rich set of features for programmers looking to create and edit Web Services:
    Intuitive graphical environment for viewing and editing WSDL files 
    Web Services creation wizard that automates the creation of service definitions, port types, binding, template operations, and messages 
    Fully automated wizards for creating and editing XML schema, schema array, complex types, simple types, and enumerations 
    Support for WSDL validation, where WSDL is tested against WSDL Schema 
    Support for WSDL profiling, so WSDL can be validated against customized profiles for specific requirements such as standards compatibility (for example, WS-I) 
    Support for advanced WSDL capabilities such as imports, faults, SOAP headers, multiple bindings, and parameter ordering 
    WSDL 1.1 specification support 
    Retrieval of WSDL from across networks, UDDI repositories, or Internet locations 
    Full support for WSDL documentation 
                                         
  15. Web Services Editor:
    Cape Clear Software has debuted a free service-oriented architecture (SOA) editor. It 뱎rovides programmers with a graphical environment that simplifies the creation of standards-based Web Services, which can be deployed into an SOA-based architecture,?Cape Clear says. The SOA Editor offers easy-to-use tools for building services, including automated wizards for common development tasks, support for Web Services standards, tools for testing code, support for XML Schema, and detailed documentation to help programmers get up and running quickly,?the vendor notes. 밫he SOA Editor is available for download immediately.
                     
  16. X standard version:
    XStandard is the leading standards-compliant plug-in WYSIWYG editor for Windows desktop applications and browser-based content management systems (IE/Mozilla/Firefox/Netscape). The editor generates clean XHTML Strict or 1.1, uses CSS for formatting, and ensures the clean separation of content from presentation. Markup generated by XStandard meets the most demanding accessibility requirements. The editor's cool features include drag & drop file upload, spell checking and an image library that integrates tightly with your CMS.
                                    
  17. XML-Editor:
    XML editor is a Java-based XML editor with support for XML, XSL, TXT, XSD and DTD documents. Oxygen shows that Java should be the base of an XML editor; this can be proved by the development dynamics of Oxygen and by the availability on many platforms. It has Unicode support and the interface messages are translated in English, French, German, Italian and Romanian. The main goal of Oxygen is to be a tool easy to use and to make tasks shorter, thus it offers end tag auto-completion and a powerful code insight that guide the user to write valid XML content. The code insight can follow a DTD structure, an XML schema structure or even can detect the structure of a partial edited document allowing the rest of the document to be created about 5 times faster than before. A very important thing is manipulating XML content and XSLT is the normal way to this, thus XML and XSL documents can be easily associated one with the other and the transformation results can be viewed through different views like text, XML, HTML. An XPath console is present to assist the user in testing the results of XPath expressions.
                                   
  18. Web services with Axis2:
    In simple terms, Axis2 is not just the next version of the Axis 1.x family; rather, it is a revolutionary version of Axis 1.x. Axis2 is no longer bound to request-response Web service invocation. As in the Axis 1.x family, there is no turning point like the "pivot point" in Axis2, and Axis2 is built totally on keeping asynchronous Web service invocation in mind. Axis2 acts as a pipe that carries the SOAP message from one end to other. The entry point to the pipe is a transport receiver, and the end point is a message receiver. After handing over the message to the message receiver, Axis2 does not care about the message. Therefore, it's up to the message receiver to invoke the service and send the response, if any, so service implementation classes) need not always be a Java class; it can be something else as well.
                                         
  19. Secure Web Services via Oriented:
    This article describes the exploitation of the pluggable transport infrastructure provided as part of ASP.NET Web Services, which allows developers to deliver Soap messages built in the document/literal format to be delivered to an end point via mechanisms other than default HTTP transport. In this article, a framework that supports the addition of alternative physical delivery mechanisms is presented, and two such implementations are included ?MSMQ and Websphere MQ are chosen to illustrate a store-forward capability for a more 'guaranteed' Web Services request delivery. The framework that will be developed integrates the Web Services Enhancements (WSE) 1.0 for secure 2-way transport of messages over non-HTTP mechanisms, thereby giving the developer a choice of 'trusted' (clear message) or 'untrusted' (secure message) delivery to the chosen endpoint. 
                         
  20. Microsoft Web Services:
    The Microsoft.com Web service is an XML Web service that will enable you to integrate information and services from MSDN, Technet, other Microsoft.com sites, and Microsoft Support. In order to serve as a test for our new architecture, Version 1.0 of the Microsoft.com Web service is limited to providing information about top downloads from Microsoft.com. Future releases will build on this architecture to provide access to a broader variety of Microsoft content and services. 
                                                 
  21. Web Services to J2EE :
    The Java XML Pack is the first certified release of Web services tools for J2EE (Java 2, Enterprise Edition), the server software platform that is based on the Java programming language. Java developers already have some tools provided by the open-source community that allow them to build XML-based Web services for J2EE, said Karen Shipe, a product manager with Sun's Java XML group. But Sun's release Monday is the first such technology that has gone through the Java certification process.
                              
  22. Open SAML Web Services:
    OpenSAML is a set of open-source libraries in Java and C++ which can be used to build, transport, and parse SAML messages. OpenSAML is able to store the individual information fields that make up a SAML message, build the correct XML representation, and parse XML back into the individual fields before handing it off to a recipient. OpenSAML supports the SOAP binding for the exchange of SAML request and response objects (C++ supports requesting only). It provides additional help in supporting the SAML browser/POST profile for web single sign-on. It does not currently provide any additional support for the artifact profile, but provides the machinery needed to implement it in other software. All core SAML constructs are now supported to some degree.OpenSAML has been produced by Internet2 members as part of their work on the Shibboleth project ( http://shibboleth.internet2.edu/ )
Posted by '김용환'
,

Creating Callback Enabled Clients for Asynchronous Web Services

(http://dev2dev.bea.com/pub/a/2005/03/callback_clients.html)

 

 

Published on dev2dev (http://dev2dev.bea.com/)
 http://dev2dev.bea.com/pub/a/2005/03/callback_clients.html
 See this if you're having trouble printing code examples

Creating Callback Enabled Clients for Asynchronous Web Services

by Reza Shafii
03/14/2005

Abstract

Web services are a promising technology that play an important role in Service Oriented Architectures (SOA). A key, emerging aspect of this technology is the ability to provide asynchronous services. Although today’s web service standards contain specifications for providing such asynchronous services, the details on using them from a client application perspective can be confusing and unclear. Web services callbacks are an important element in the realization of these asynchronous services. This article provides a practical guide to the creation of client applications for web services that contain callback operations. All code segments shown in this article are from the included example, which you can download. The example contains the complete implementation of these code segments and usage guidelines.

Terminology

Before starting a discussion on callback-enabled clients, it is important that we clarify the terminology involved. The following diagram shows the main entities involved when a client uses a Web service with a callback operation.

Figure 1
Figure 1. A client making a call to a web service

This figure depicts a client making a call to a web service. The web service can then respond, at some later time, by making a call back to the client. Therefore, a client of a web service that contains a callback operation is special in that the client itself must provide an endpoint. We call this the callback endpoint and define an endpoint as a unique address identified by a URI to which SOAP request messages can be sent.

The client itself starts the interaction with the web service by sending a SOAP message to the web service endpoint. The correlated request messages sent by the client to the web service and their associated response messages form the client initiated operations. As mentioned, the client can process the request messages sent by the web service to its own callback endpoint. Together, the correlated request and response messages are referred to as a callback operation.

With this terminology in mind, let's take a closer look at the concept of web service callbacks and their relationship to conversational web services and asynchronous web service invocation.

Asynchronous vs. Callbacks vs. Conversational

The concept of an asynchronous web service invocation is sometimes confused with the idea of web service callbacks and conversational web services. Although related, the three concepts are different.

An asynchronous web service invocation means that the client is able to send a SOAP message request without blocking to receive the corresponding response message from the server. The process of making such asynchronous web service calls on BEA WebLogic Platform 8.1 web services is already comprehensively documented and is therefore not discussed further in this article.

Web service callbacks refer to scenarios that involve the web service provider sending a SOAP message back to its clients. The Web Services Description Language (WSDL) specifications define such operations as being of the type “solicit/response.” Clients of web services that support callback operations must have a web service endpoint themselves, which the web service can use for sending callback requests at any point in time, or, in other words, asynchronously. Note that this is unrelated to the concept of asynchronous invocation discussed earlier.

A web service is conversational if the series of messages going back and forth between the two endpoints are tracked with a unique conversation ID with specific operations flagged to start and end the flow of messages. Web services that provide callbacks are also, by definition, conversational. This is because in order for the web service to be able to make a callback call on a client, it has to have its callback endpoint information. This is only possible after an initial invocation has been made by the client. Therefore, at the very least, the initial operation initiated by the client and the callback operation made by the web service are related to each other and must be tracked with a unique conversation ID. If this is not done, there is no way for the client to differentiate between callback operations relating to different initiating calls.

We will now take these considerations into account and create callback-enabled clients. As we've just seen, these clients form the basis of solicit-response and conversational web services.

Creating Callback-Enabled Clients

As discussed earlier, callback-enabled web service clients need to provide a callback endpoint capable of asynchronously receiving and processing callback operation messages. To avoid the complications of having to provide a callback endpoint, a technique known as polling can be used as an alternative. However, this technique requires the client to periodically call the server to check for callback events. The overhead of these calls can be significant if the event in question does not occur frequently. This overhead can be avoided by having the client provide a callback endpoint and process the callback operations directly.

It should also be noted that although it is possible to create callback-enabled clients by using a web service over JMS (if such binding is offered), this approach has some limitations, one of the important ones being that it forces the client to use the same JMS implementation as the web service provider. We will therefore concentrate on accomplishing our task over the HTTP transport. There are two areas that require attention in creating such a client: the creation of proper client-initiated SOAP messages, and the handling of callback operations.

When our client initiates operations of a web service containing a callback, it needs to somehow include the URI of the callback endpoint on which it is listening within the request message. The Web Services Addressing and the SOAP Conversation Protocol specifications both define a SOAP header element that allows you to achieve this goal. Ideally, the specification used in specifying the callback endpoint would not matter. However, most web services containers, including BEA WebLogic Server 8.1, do not yet contain an implementation of the Web Services Addressing specifications. Currently, BEA WebLogic Workshop 8.1 web services support the SOAP Conversation Protocol specifications and that is the example used within our example client.

According to the SOAP Conversation Protocol, the required SOAP headers differ depending on the phase of the conversation. For the first client-initiated (start) operation within the conversation, we need to provide the web service with our callback endpoint through the callbackLocation header element. All operations, including the first one, will also require a unique ID that will be used in our SOAP messages throughout the dialogue. This is achieved through the conversationID element. The following is an example of a SOAP request message that starts a callback-enabled conversation:

<soapenv:Envelope soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:env="http://schemas.xmlsoap.org/soap/envelop/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"> <soapenv:Header> <con:StartHeader soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0" xmlns:con="http://www.openuri.org/2002/04/soap/conversation/"> <con:conversationID>[123456]:192.168.1.100:8181</con:conversationID> <con:callbackLocation> http://192.168.1.100:8181/StockNotificationCallback </con:callbackLocation> </con:StartHeader> </soapenv:Header> <soapenv:Body> <n1:registerForThresholdNotif xmlns:n1="http://www.openuri.org/"> <n1:stockTicker>CCC</n1:stockTicker> <n1:threshold>10</n1:threshold> </n1:registerForThresholdNotif> </soapenv:Body> </soapenv:Envelope>

Most of the existing Java web service toolkits (for example, BEA WebLogic’s clientgen, Apache Axis, and JWSDP) allow you to create a proxy library that can be used by client applications to easily invoke web services operations. However, none of these frameworks supports callback operations with the main issue being that their proxies do not generate the required headers. Until such support is provided, it would be highly desirable to be able to use all the benefits of these frameworks (for example, complex type XML mapping) by extending them with support for callback operations. One technique for achieving this result is the use of a SOAP message handler.

All the web services toolkits named above can support SOAP message handlers. A message handler is a Java class that implements the javax.xml.rpc.handler.GenericHandler interface and contains methods called right before sending out (or after receiving) a SOAP message. We can introduce a message handler within our client that is able to find out the current phase of a particular conversation and accordingly extend the outgoing request message with the required headers.

It is important to note that the client SOAP message handler must be able to determine the phase of the conversation that the message in question belongs to so that the appropriate header elements are created. The generation of the conversation ID is also a task that is left up to the client handler.

Once the extended request message is received by the web service endpoint, it will then send request messages to the callback endpoint specified by the callbackLocation element of the start message. In most cases, the client process itself needs to provide this endpoint and handle the callback messages appropriately. If our client is running within a web service container, this could be accomplished by deploying a web service with the callback operation within the same container. However, if the client is not running within a container, the job can be accomplished by implementing the callback endpoint within a lightweight container embedded in the client process itself. This gives us the ability to invoke the client generated operations and handle the incoming callback operations within the same process context. Note that the processing entity behind the callback endpoint (and within the client) needs to be able to handle the XML mapping of the message parameters as well as the dispatching of the operation to the right area of code.

Off course the client could also choose to specify a callback endpoint living within a container separate from the calling process by simply setting the callbackLocation header element appropriately.

As we have seen, the creation of clients for web services containing callback operations is not trivial and contains complex elements including the handling of SOAP messages, management of the conversation (both in terms of phases and IDs), mapping of parameters, and dispatching of operations. These complexities are all abstracted when the web service in question is accessed through a BEA WebLogic Workshop Service Control, which automatically performs all these operations for the user.

Creating Callback-Enabled Client Using a Service Control

The accessing of web services through a WebLogic Workshop Service Control is already well-documented. This solution is by far the simplest way to use callback-enabled web services if the client entity is able to use controls (that is, it is a Java Process Definition business process or another control; Page Flows are not able to use control callbacks). All the complexities involved in accessing callback-enabled web services are abstracted by this method.

Example Stock Notification Service

The example included in this article contains a Stock Notification conversational web service and a sample client illustrating the concepts discussed here. The web service provides operations allowing clients to register stock tickers and an associated threshold price. The service then monitors the stock, and every time the price passes that threshold, notifies the client through a callback (onThresholdPassed()).

Figure 2
Figure 2. This diagram illustrates the configuration for our example

It is clear that a polling technique is not an optimal solution for the creation of our client: Stock prices could pass their associated thresholds on a frequent basis or very seldom. A short polling interval could therefore lead to many unnecessary calls whereas a long polling interval could result in the client being notified of a threshold crossing long after the fact.

The implementation of a callback endpoint within the client application seems like a better choice. Let's first look at how the example client sends operations to the StockNotification web service. We have implemented the client using two distinct techniques. The first technique uses the WebLogic Workshop-generated proxy library and is implemented by the makeCallUsingBEAProxy() method of the StockNotificationClient class:

public void makeCallUsingBEAProxy() { try { // Get the proxy instance so that we can start calling the web service operations StockNotificationSoap sns = null; StockNotification_Impl snsi = new StockNotification_Impl(); sns = snsi.getStockNotificationSoap(); // Register our conversational handler so that it can properly set our // our conversation headers with a callback location QName portName = new QName("http://www.openuri.org/", "StockNotificationSoap"); HandlerRegistry registry = snsi.getHandlerRegistry(); List handlerList = new ArrayList(); handlerList.add(new HandlerInfo(ClientConversationHandler.class, null, null)); registry.setHandlerChain(portName, handlerList); // Register, call some methods, then sleep a bit so that our callback // location can receive some notifications and finally finish the conversation. sns.registerForThresholdNotif("AAAAA", "100"); sns.addToRegistration("BBBBB", "5"); StockList stocks = sns.getAllRegisteredStocks(); ... sns.endAllNotifications(); } catch (Exception e) { throw new RuntimeException(e); } }

As you can see in this code segment, we are able to use the classes generated by clientgen as we would normally. The only thing that stands out in this code as compared to the invocation of a web service without callbacks is the instantiation and registration of a client-side SOAP message handler at the beginning of the method. This handler intercepts the outgoing SOAP messages and adds the necessary conversational headers. Every time a SOAP request message is sent from the client process the handleRequest() method of our message handler is called with a MessageContext object containing information about the outgoing SOAP request. Below is a code segment of our example client’s message handler:

package weblogic.webservice.core.handler; ... public class ClientConversationHandler extends GenericHandler { public boolean handleRequest(MessageContext ctx) { ... if (phase.equals("START")) { headerElement = (SOAPHeaderElement) header .addChildElement("StartHeader", "con", "http://www.openuri.org/2002/04/soap/conversation/"); headerElement.addChildElement("con:callbackLocation") .addTextNode(CALLBACK_URI); } else if (phase.equals("CONTINUE") || phase.equals("FINISH")) { headerElement = (SOAPHeaderElement) header .addChildElement("ContinueHeader", "con", "http://www.openuri.org/2002/04/soap/conversation/"); } headerElement.addChildElement("con:conversationID").addTextNode(convID); ... } }

The proxy library generated by the BEA clientgen tool already uses a default client-side SOAP message handler that creates the conversational StartHeader header element. Unfortunately, currently clientgen output does not support callback operations and therefore the default handler does not create the required callbackLocation sub-element. We therefore have to ensure that our own message handler overrides the default conversational handler so as to manage the extra task of creating the callbackLocation header. We do this by ensuring that our handler is created within the same package as the default handler, namely weblogic.webservice.core.handler, and that it has the exact same class name as ClientConversationHandler. Note that this technique involves overriding the existing conversation message handler and therefore is not guaranteed to be forward-compatible. This example, however, does show how a message handler could be used for the creation of the callback headers and this concept can be used with any other web services framework supporting SOAP message handlers.

An alternative to the technique of using SOAP message handlers along with proxy classes is to use the JAXM API to directly create the SOAP request messages and send them to the web service. This is the second technique used by our example client and is implemented within the makeCallsUsingJAXM() and callMethodFromFile() methods of the StockNotificationClient class:

public void makeCallsUsingJAXM() { callMethodFromFile("C:\\registerForNotifSOAP.xml"); ... callMethodFromFile("C:\\endAllNotifSOAP.xml"); } private void callMethodFromFile(String fileName) { try { // Create a SOAP connection object SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance(); SOAPConnection conn = scf.createConnection(); // Create the SOAP request message from the specified file MessageFactory mf = MessageFactory.newInstance(); SOAPMessage msg = mf.createMessage(); SOAPPart sp = msg.getSOAPPart(); // Read the file content into a string and replace the conversation ID with // the current one. String fileContent = readFileIntoString(fileName); fileContent = fileContent.replaceFirst(CONV_ID_HOLDER, ConvIDGenerator.getInstance(). getConversationID()); StreamSource prepMsg = new StreamSource(new StringBufferInputStream( fileContent)); sp.setContent(prepMsg); msg.saveChanges(); // Make the actual call conn.call(msg, TARGET_SERVICE_URI); conn.close(); } catch (Exception ex) { throw new RuntimeException(ex); } }

The callMethodFromFile() method reads the SOAP message from the specified file, replaces the message’s conversation ID with the client’s current conversation ID, and finally makes the actual call. When using the JAXM approach, the Java to XML mapping of operation parameters and return values must be implemented by the client. We have avoided this task by using pre-generated SOAP messages (that already contain the required parameter values) from the file. Although this approach serves as a good conceptual illustration, it is most likely not a feasible solution for clients containing a reasonable level of complexity. Such clients must create the messages programmatically from scratch using JAXM along with a Java to XML mapping API.

Now that we have reviewed the areas of our client responsible for creating the web service operations, let's turn to the implementation of the client’s callback endpoint and the processing of the callback messages coming from the web service. Since our callback endpoint needs to be able to handle the incoming HTTP requests, a servlet could be a logical choice. Further, it would be highly desirable to have a servlet that is able to extract the SOAP messages included within the incoming HTTP requests and provide it to us in an easy-to-use form. The ReqRespListener interface and the JAXMServlet class of the javax.xml.messaging package provide us with this functionality. Once properly deployed, servlets that use this interface and class will have all targeted HTTP post requests automatically converted to SOAPMessage instances passed to us through the onMessage() method. The following code shows the onMessage() method implementation for our example client.

public class CallBackHandlerServlet extends JAXMServlet implements ReqRespListener { public SOAPMessage onMessage(SOAPMessage message) { try { // We have just received a SOAP message at the callback // endpoint. In this example we will just assume that // the message received is in fact the onThresholdPassed // callback request. However, a servlet handling // multiple callbacks cannot make this assumption and // should process the SOAP message to see what callback // it relates to and do as appropriate for each. String stockTicker = extractOnThresholdPassedArgument(message); System.out.println("[DEV2DEV CALLBACK EXAMPLE]: Received treshold notification for: " + stockTicker); // Now we have to create a proper response to the callback // request. Returning this response as part of the onMessage() // method will ensure that the SOAP response gets back to the server. SOAPMessage response = createThresholdPassedResponse(); return response; } catch (Exception e) { throw new RuntimeException(e); } } ... }

Once a callback request message is received by the onMessage() method, our client then extracts the stock ticker argument, prints it to the standard output, and creates the correlated response message that is returned to the web service by our servlet. Clients that use web services that contain more than a single callback operation will also need to dispatch the incoming request to an appropriate area of client code based on the corresponding callback operation.

Although our servlet contains the appropriate code for the processing of incoming onThresholdPassed() callback messages from the web services, it needs to be deployed within a servlet container listening on the callback URI to complete the implementation of the callback endpoint. The Jetty open source project contains a lightweight servlet container that can be embedded within our client. The deployment of the CallBackHandlerServlet servlet within an embedded Jetty container allows us to have the callback endpoint reside within the client Java process. The StockNotificationCallbackProcessor class is a utility class used by our client to start the Jetty server and deploy the CallBackHandlerServlet servlet:

public class StockNotificationCallbackProcessor { public static final String CALLBACK_SERVER_PORT = ":8181"; public static final String CALLBACK_SERVLET_CLASS = "asynchwsconsumer.CallBackHandlerServlet"; public static final String CALLBACK_SERVLET_NAME = "CallBackHandlerServlet"; private HttpServer server; public StockNotificationCallbackProcessor() {} public void startListening() { try { // Configure the server so that we listen on the callback URI server = new Server(); server.addListener(CALLBACK_SERVER_PORT); ServletHttpContext context = (ServletHttpContext) server.getContext("/"); context.addServlet(CALLBACK_SERVLET_NAME, "/*", CALLBACK_SERVLET_CLASS); // Start the http server server.start(); } catch (Exception e) { throw new RuntimeException(e); } } public void stopListening() { try { server.stop(); } catch (Exception e) { throw new RuntimeException(e); } } }

The startListening() method deploys the CallBackHandlerServlet on port 8181 and configures the embedded servlet container so that all HTTP requests are directed to this port. This method also starts the embedded servlet container.

Now that we have examined both the creation of the web service operations and the processing of the callback operations, let's see how the main() method of our example client uses these elements:

public static void main(String[] args) { StockNotificationClient snClient = new StockNotificationClient(); snClient.snCallbackProcessor.startListening(); snClient.makeCallUsingBEAProxy(); ConvIDGenerator.getInstance().resetConversationID(); snClient.makeCallsUsingJAXM(); snClient.snCallbackProcessor.stopListening(); }

As you can see, the method starts by setting up the callback endpoint (which, as we saw before, involves starting the embedded servlet container and deploying the callback processing servlet to it). The method then uses the BEA clientgen proxy to make calls on the stock notification web service. Given that this interaction with the web services completes the conversation by calling the endAllNotifications() end operation, the client needs to change the conversation ID to start a new conversation. Our client uses the ConvIDGenerator singleton class to manage conversation IDs, and that class uses the java.rmi.dgc.VMID class to create properly formatted unique conversation IDs.

Once the conversation ID has been changed, the client then uses JAXM to once again make calls on the stock notification web service. Finally, the client stops the embedded servlet container and the process ends.

We have now completed our analysis of the example client that can be downloaded as part of this article. When you run this client against the stock notification web services, both the client and the web service will display messages to the standard output describing the various phases of the conversation including the processing of the callback operations.

Conclusion

This article shows the steps involved in the creation of a stand-alone client process for web services containing callback operations. Such a client needs to manage the conversational aspects of the web service calls and provide an endpoint that can be used by the web service for callback operations.

Download

CallbackExample.zip (1.7Mb) - This file contains the complete example application described in this article.

References

Reza Shafii works for BEA Systems professional services.


Return to dev2dev.

 

Posted by '김용환'
,