'분류 전체보기'에 해당되는 글 539건

  1. 2005.04.08 Paging in J2EE: Manage Large Result Sets Efficiently 1
  2. 2005.04.08 Hibernate Annotations 1
  3. 2005.04.04 [사설] 오픈프로젝트로 얻어지는 것과 잃는 것
  4. 2005.04.01 [공지] 토론/정보/사실 게시판 오픈
  5. 2005.03.27 [Note] JDK5.0 에서의 성능향상 부분 요약
  6. 2005.03.27 [Note] J2SETM 5.0에서의 Image I/O
  7. 2005.03.27 [Note] java.nio.charset.Charset 에서 지원되는 인코딩 1
  8. 2005.03.27 [Note] JDK5.0에 새로 추가된 StringBuilder
  9. 2005.03.25 Design Better Software with the Inversion of Control Pattern
  10. 2005.03.25 Working with Object-Orientation in UML
  11. 2005.03.25 UML Sequence Diagrams
  12. 2005.03.25 UML Class Diagrams for Java Programmers
  13. 2005.03.25 Working with Class Diagrams
  14. 2005.03.14 Designing Web Services with the J2EE(TM) 1.4 Platform
  15. 2005.03.10 Ease of Development in Enterprise JavaBeans Technology3
  16. 2005.03.10 Ease of Development in Enterprise JavaBeans Technology2
  17. 2005.03.10 Ease of Development in Enterprise JavaBeans Technology1
  18. 2005.03.09 JDBC Performance Best Practices
  19. 2005.03.08 Roadmap to Agile methods and tools
  20. 2005.03.03 RCP (Rich Client Platform)
  21. 2005.03.03 Introduction to Web Services Metadata 1
  22. 2005.03.01 XML Security Learning Guide
  23. 2005.03.01 BPEL Learning Guide
  24. 2005.02.16 [javacan] Hibernate 소개
  25. 2005.02.16 PMD for Eclipse install instructions 2
  26. 2005.02.14 [IBM] 서비스 지향 모델링과 아키텍쳐
  27. 2005.02.13 Simplifying EJB Development with EJB 3.0
  28. 2005.02.13 NetBeans IDE 4.1 - Develop and Test Web Services 1
  29. 2005.02.12 [javaworld] Getting around JSF: The role of JSP
  30. 2005.02.12 [javaworld] Service-context propagation over RMI


Paging in J2EE: Manage Large Result Sets Efficiently





































DevX HomePage

 
http://www.devx.com Printed from http://www.devx.com/Java/Article/21383
 












Paging in J2EE: Manage Large Result Sets Efficiently



Learn how to manage paging for unbounded queries over large result sets—without blowing up your server. Strike the right balance between resource utilization and response-time requirements to satisfy your user demands. 









Pagination is the simplest and most common way to break up large amounts of data into more manageable chunks. Pagination is a key part of Web site design, both from the UI perspective (to manage limited screen real estate) and from the server perspective (to process large result sets efficiently, without causing resource spikes or servicing delays). In J2EE, efficient pagination (and good UI design) are essential for handling large query result sets in a resource-pooled environment.


Specifically, the following conditions make pagination necessary:


  • Screen real estate is limited. Your JSP/client UI may have insufficient space to display the entire results at once and your user may not be able to find what he or she wants quickly in a very large data set.

  • Your resources are pooled or constrained. Result sets are too large to be managed reasonably within your connection and memory limitations.



Paging Strategies That Work

Basic querying and paging strategies can start out simple but quickly lead to disaster if you fail to consider query evolution and data growth. Open-ended or unbounded queries that perform well over small test data sets may degrade sharply against real data. If you don't manage your precious DBMS and memory resources, your problems will only compound under load.


Efficient data retrieval and paging is a trade-off between memory usage and response-time requirements. Broadly speaking, most roll-your-own J2EE paging mechanisms fall into two basic categories:


  • Cache based: Results are cached for fast access in subsequent pages.

  • Query based: Results are fetched from the DBMS on demand as the user pages.



Cache-based approaches cache the query results over and above what the database provides, in an intermediate tier (on the HTTP session, in the server using a Stateful Session Bean or in a home-grown cache). Subsequent page requests hit the cache rather than the database. Such cache-based mechanisms are memory intensive and work well for low-volumes, recurring queries, and small to medium-sized result sets. The cache-hit rates are high and the I/O overheads are low, yielding good response times.


Query-based approaches don't use caches. They deliver pages on demand, direct from the DBMS to the client. They service additional pages by issuing more queries to the DBMS rather than pulling data from a cache. These approaches discard or skip unwanted rows from previous or future pages using low-level JDBC functions and context information from the last fetched page. Query-centric paging is memory efficient but requires additional round trips to the database, leading to slightly slower response times overall.


More sophisticated mechanisms adopt a hybrid approach. They constrain cache sizes by caching a fixed number of pages ahead, maintaining bounded cache windows, and using efficient query mechanisms and offline threads to backfill the results transparently to the client.


Caching vs. Query Trade-offs

Cache-based approaches are fast, but they have a few pitfalls. For example, unbounded or open-ended queries for large result sets can lead to uncontrolled memory growth as the results are serialised and cached. Large result sets take a long time to service and take up valuable connection and session resources. Whenever a connection is consumed for long periods of time, the number of connections available in your J2EE shared connection pool is effectively reduced. To cope with high load, your system should aim to service your requests as quickly as possible. If your requests take a long time to process, your overall throughput will drop. You don't want to occupy your resources with long-lived queries, because you won't have any connections and threads left to do anything else.


Long-lived queries can also lead to connection timeouts if your query takes more time to execute than your preset JDBC connection time limit allows. Avoid this in cache-based strategies by narrowing or constraining your search criteria so that your DBMS queries (and results) are bounded.


Caching is most beneficial when the cached data is hit repeatedly. However, if your user searches are consistently yielding distinct results, your caches can't be reused across requests. Worse, if the user rarely pages beyond the first page, your caching within the session is for naught. You should carefully manage caches so that they don't grow too large and they expire promptly when they're no longer required.


Hybrid or query-based approaches are more reliable than cache-based alternatives. They have slightly slower response times but can scale transparently for large result sets and high request volumes. An unbounded query will take a long time to execute but won't exceed your memory constraints or take too long to execute. The DBMS connection is relinquished once the required data (usually the first one or two pages) has been fetched. This means that the connection is held for the bare minimum before being returned to the connection pool. The only downside is that additional context information must be passed back and forth on your page requests.


Table 1 lists the issues you need to consider when deciding on a paging approach.

































Conditions for Pagination Cache-based Approach Hybrid/Query-based Approach
Is your result data bounded or unbounded? Applicable for fixed or bounded result sizes; search criteria is fixed or constrained Applicable for unbounded results sets (such as searches with loose criteria) since the implementation inherently limits result size
How big are your result sets? Good for small to medium-sized Good for medium-sized to large
What are your response-time requirements? When response time is critical When response time is less critical
How often is the query issued? Do you fetch the same data repeatedly, or is your result data different for each request? Applicable for when the same data is requested repeatedly Applicable for when the search criteria and results vary from request to request
How volatile is your (static vs. dynamic)? What are your requirements? Unchanging or static data can be serviced reliably from caches If data is dynamic, query every time to return the most up-to-date data

Table 1. Cache-based vs. Hybrid/Query-based Paging Strategies























Query-based Paging Strategies

The key to implementing efficient query-based paging is to limit the I/O to the database so that you fetch only the exact page(s) that you need. Simple approaches query for the entire result set and then iterate over it until they reach the target page, or they use JDBC to fetch from a given row, for example by using the JDBC method ResultSet::absolute(). This guarantees that the only data they serve to the client is the requested page. The ValueListHandler pattern from Sun Microsystems adopts this approach. But beware, you may not incur the cost of serializing redundant data into the application server but the DBMS will have to assemble your results temporarily so that it can move/cursor to the target start row.


One way to guarantee that you never assemble or read redundant data is to manipulate the WHERE clause on your search query to explicitly exclude data that you don't need. In other words, you narrow the query to the requested page. This approach requires that you pass additional context information back and forth on your page requests. This is so that the paging mechanism can adjust the queries automatically to account for data that's already been fetched.


Your page query should be carefully constructed to account for the following:


  • Paging direction: Forward/next or back/previous

  • Search criteria: Whether entered by the user or as part of your normal business use case

  • The target page: Return rows for the requested page only

  • Page size: Number of rows in a page



Paging direction is important if you want to be able to scroll both forwards and backwards across your result data. Caching as you go can provide back functionality. However, this works well only for static data. If your data is volatile, your cache data may be out of date by the time you page back. The only way to guarantee correct results is to issue another query to fetch the previous page of data. For cacheless paging, this means using SQL ORDER BY and WHERE clauses. If one or more ORDER BY columns specify the forward paging order, you can page backwards by reversing the ORDER BY directions in conjunction with the appropriate WHERE clause.


Basic business data searches usually entail some sort of dynamic WHERE clause construction so that user-entered criteria may be incorporated in the query. With query-based paging, the WHERE clause includes the search criteria as well as additional semantics to narrow the result set to the correct page. Use row identifiers to limit and qualify your page (see Figure 1). A row identifier uniquely identifies a row in a result set and consists of one or more columns from the result set. Think of it as a logical index into you result set.





Figure 1: Query-based Paging Using Row Identifiers


Typically, your row ID can be a primary key. However, depending on the data, it may be a combination of primary key columns and/or other columns. A page is denoted by a start and end row ID pair: the first row and last row in the page, respectively. To page forward (next), adjust the query to fetch all rows where the row ID is greater than the last row ID of the current page. To page back, query for all rows where the row ID is less than the first row ID of the current page.


This mechanism works fine for single-column, simple row IDs and ascending forward paging order, but searches are rarely that simple. In some cases, the row ID is a combination of columns and normal forward paging direction is a mixture of ascending (ASC) and descending (DESC) ORDER BY columns. The trick is to ensure that all your ORDER BY columns are included in the WHERE clause (including the row ID columns) and all the row ID columns are included in the ORDER BY, adjusted for forwards (paging next) and backwards (paging back) ordering.


Row-ID-based Paging Algorithm

Take a basic query example that selects three columns, col1 (VARCHAR), col2 (INTEGER), and col3 (TIMESTAMP), from table foo. To fetch the first page, issue the following SQL:


SELECT col1,
col2,
col3
FROM foo
WHERE col1=?
ORDER BY col2 ASC ,col3 DESC


In this example, the search criteria supplied by the user is applied to col1. The row ID is comprised of col1 and col2, and the normal forward paging order is defined as col2 ascending and col3 descending.


JDBC provides a function to limit the number of rows returned for a query, Statement::setMaxRows(int max). To fetch the first page, simply issue the basic query and set the max rows to your page size. Use this for every paging query as it guarantees that you fetch only one page of data for any given request. For optimum performance, use Statement::setFetchSize(int rows) to set the fetch size to match the page size. This guarantees that the page will be fetched in one low-level IO request between the driver and the DBMS.


To fetch the next page, adjust the WHERE clause to exclude the first page by fetching all rows that match the search criteria and that are logically greater than the last row ID of the first page. The row ID part of the WHERE clause is constructed from the specified row ID columns (col2 and col3) for the query, and the row ID values are substituted from the first page.


Fetch the next page:

SELECT col1,
col2,
col3
FROM foo
WHERE col1=? AND
( (col2 > ? ) OR (col2 = ? AND col3 < ? ) )
ORDER BY col2 ASC ,col3 DESC


To fetch the previous page, flip the ORDER BY's to fetch backwards and adjust the WHERE clause to exclude unwanted rows by fetching rows that are logically less than the row ID of the first row of the current page.


Fetch the previous page:

SELECT col1,
col2,
col3
FROM foo
WHERE col1=? AND ( (col2 < ? ) OR (col2 = ? AND col3 > ? ) )
ORDER BY col2 DESC ,col3 ASC


In your Java code, ensure that you reorder the results to normal forward ordering before serving the page to the client.


This paging algorithm works seamlessly for very large result sets and arbitrarily complicated or unbounded queries, provided you use the JDBC Statement::setMaxRows() function and construct the WHERE and ORDER BY clauses appropriately. For optimum performance, insure that your WHERE clause columns are indexed.

























Put Query-based Paging into Practice

Once you have established your basic query-based paging algorithm, put it into practice by creating a generic, reusable paging component that can be used for any arbitrary simple or complex query. Your paging framework should provide a clear interface, a simple API, and it should encapsulate the low-level internals of the paging implementation and algorithm. It should handle data fetching, transport, row IDs and parameter passing, query manipulation, as well as simple search criteria parameter substitution.


One way to set up this framework is to adopt a configuration-driven or declarative approach in which you pre-define the search as a logical paginated view in a properties file and supply the actual search parameters at runtime with the request. In your configuration file, you can make the view explicitly identify the row IDs, ORDER BY columns, and any other information deemed necessary for your paging implementation. To issue a search, the caller doesn't have to do any fancy SQL footwork. It just identifies and loads the desired view using the view's unique identifier and then issues the search/fetch request along with any user-supplied criteria.


A view is just a logical window across one or more physical DBMS tables and views. A paginated view is a view that contains additional discriminating information (such as row IDs) that enables it to be paged. Configure your paginated view in a properties file and define the forward paging direction (ORDER BY's) and row ids.


The following steps walk you through the creation of a paging component. For a complete package of all the required Java classes, download the source code.


Step 1. Create/configure your paginated view


# Example view
example.view=foo
example.pagesize=5
example.where=col1=?
example.rowids=col2 ASC,col3 DESC


Step 2. Create a class to represent your view, PageDefn


Create a Java class (PageDefn) to represent your paginated view. You can either load it from your properties file or create it on the fly in your code. Configuration is the preferred approach, as the caller doesn't have to know about the view internals or table meta-data. Your PageDefn contains all the information relevant to your paginated view and is responsible for handling the SQL construction details:


public class PageDefn extends ViewDefn {

public interface PageAction {
public static final int FIRST = 0;
public static final int NEXT = 1;
public static final int PREVIOUS = 2;
public static final int CURRENT = 3;
}

protected int pageSize;
protected ColumnDesc[] rowIds;


public PageDefn() {
super();
rowIds = null;
pageSize = 50;


}

public PageDefn(String viewname) {
super(viewname);
rowIds = null;
pageSize = 50;
}

...

}


Step 3: Create a paging data access object (DAO)


Create a special-purpose PagingDAO (see Listing 1: PageDefn.java) that supports parameter substitution and uses Prepared statements. Prepared statements are faster than normal queries as they can be pre-compiled by the DBMS. Your PagingDAO executes the paging query and handles the results. The actual SQL construction is delegated to the PageDefn. This separation of concerns allows you to evolve the PageDefn and its subclasses to support more sophisticated query configuration independently of the DAO.


Ensure that your DAO closes all database resources (ResultSets, Statements, and Connections) once the query has been executed. Put your close code inside a FINALLY clause so that your resources will close even when an exception is thrown.


Step 4. Create a PageContext and Page command


Create a PageCommand class to encapsulate your page request and hold the results. Client servlets and actions will use the PageCommand to interact with your paging framework. Your command should provide methods to do the following:


  • Specify the target view (PageDefn)

  • Supply optional search criteria (query parameters)

  • Specify the page action (FIRST, CURRENT, NEXT, or BACK)

  • Access the page results



In addition, your PageCommand should encapsulate any context information required by the paging implementation to support your paging algorithm. Create a context object that holds your paging request action and results, and encapsulates your paging internals:


public class PageContext implements Serializable {

protected Object page; // results
protected Object firstEntry; // first row ID
protected Object lastEntry; // last row id
protected int action; // paging action
protected PageContext prevContext; // previous context state


public PageContext() {
this.page = new Object[0];
this.firstEntry = null;
this.lastEntry = null;
this.action = PageDefn.PageAction.FIRST;
}

public Object[] getPage() {
return ((Collection) page).toArray();
}

public void setPage(Object page) {
this.page = page;
}

public int getAction() {
return action;
}


public void setAction(int action) {
this.action = action;
}
}


Ensure that your PageContext object is Serializable, as it will be passed on the wire back and forth between the Servlet and middle tiers.


Create your PageCommand class to encapsulate your paging requests, and include the PageContext as a member variable:


public class PageCommand extends ViewCommand {

protected PageContext context;

...

}


The PageCommand class is just a data transfer object (DTO) that conveys request parameters and holds page results. Page data and row-IDs are held inside the PageContext object. The caller doesn't have to know about the PageContext attribute directly except to remember to re-use it across page requests for a given read request.


Step 5. Create a PagingService


Create a specialized paging service (see The COR Pattern Puts Your J2EE Development on the Fast Track for more information on COR services and configuration) for handling PageCommand requests. It will process PageCommands and pass them to the PagingDAO for processing:


public class PageService implements Service {


public Command process(Command command) throws ServiceException {
if (!command.getClass().equals(PageCommand.class)) {
return null;
}

PageCommand pcmd = (PageCommand) command;

PageContext context = pcmd.getContext();
PageDefn desc = (PageDefn) pcmd.getDefn();

// Get A DAO
PagingDAO dao = PagingDAO.get();
// Issue Query, results are set into the context by the DAO
try {

dao.executeQuery(desc, context, true);
return pcmd;
} catch (DAOException e) {
throw new ServiceException(e);
}

}

}


Step 6. Exercise your Page command!


To fetch the first page, create an instance of PageCommand, load your target view, set any user-supplied parameters and page action, and issue the command to the CORManager. The CORManager will transparently route the command to the PageService to handle:


// load view and set user supplied criteria
PageDefn d = PageDefnFactory.getPDF().createPageDefn(bundle,view);
d.setParams(new Object[] { criteria });
PageCommand cmd = new PageCommand(d);

// fetch the first page
cmd.setAction(PageDefn.PageAction.FIRST);
cmd = (PageCommand) CORManager.get().process(cmd);

// process results
PageContext context = cmd.getContext();

// Process results
Object[] rows = cmd.getContext().getPage();
if (rows == null) return;
for (int i = 0; i < rows.length; ++i) {
System.out.println("ROW(" + i + ") " + rows[i].toString());
}

// cache context to be reused for subsequent pages..
getServletContext().setAttribute("context",cmd.getContext());


To fetch the next page, insure that you reuse the PageContext from the previous request. The PageContext contains all the information the paging mechanism needs for qualifying your queries. If you're managing the paging from the servlet tier, cache the PageCommand/PageContext object on the HttpSession so that you can reuse it when the user pages forward or back:


// Create PageDefintion
..
PageDefn d = PageDefnFactory.getPDF().createPageDefn(bundle, view);

// Retrieve context from ServletContext
PageContext c = (PageContext) getServletContext().getAttribute("context");

// Create Page Command
PageCommand cmd = new PageCommand(d,c);
cmd.setAction(PageDefn.PageAction.NEXT);
cmd = (PageCommand) CORManager.get().process(cmd);

// cache result on servlet context
getServletContext().setAttribute("context",cmd.getContext());
...

























Current Page Number and Total Page Count

You may want to keep track of the current page number and the total page count. You can display this information to the user, as well as prevent paging past the first or last page. For query-based paging, the simplest approach is to use SQL to count up the total number of rows in the result using the SQL function COUNT(*) or COUNT(column name). You can derive the total number of pages by dividing the number of rows by the page size. You can issue the count query every time you request a page, but this may be too much. Underneath the covers, the DBMS will have to assemble your entire result set to count the results. As a compromise, issue the count query when the first page is requested. This way, the cost is incurred once per search/read request for the first page. In most databases, you will be able to append the COUNT(*) to your column list in your query for the first page. For the databases that don't allow this (like MySQL), issue a separate count query.


The first page will be slightly slower to fetch than other pages. However, your UI will be able to accurately show the total number of pages returned, as well as the current page number. If page count isn't important or the data is so volatile that the total page count isn't reliable, avoid the overhead altogether by skipping the count query.


To add page number and total page count support to your paging mechanism, extend the PageContext object to store and maintain page counts and extend the PagingDAO to issue an additional count query on receipt of a FIRST page request.


Paging in Perspective

Searching and querying over data is an integral part of most Web sites. Paging is an ideal way to manage limited server resources, large result sets, and congested UI real estate. The approach you chose, whether cache-based, query-based, or hybrid, depends on your use cases and data characteristics. Regardless, you should limit your memory and connection usage so that your paging architecture can scale efficiently to meet your performance targets.



Lara D'Abreo is an independent consultant with over 10 years experience in commercial product development in the US, Japan, and the UK. She's currently based out of Sydney, Australia and spends her time trying to make J2EE systems run faster.

















































DevX is a division of Jupitermedia Corporation

© Copyright 2005 Jupitermedia Corporation. All Rights Reserved. Legal Notices










Posted by 아름프로


EJB3 and Hibernate3 Annotations






Hibernate Annotations


EJB3 and Hibernate3 mapping metadata with JDK 5.0 Annotations




Version: 3.0 Preview beta1, 07 04 2005






Please note that this documentation is based on a preview release
of the Hibernate Annotations and implements the Early Draft Release 2 of
EJB 3.0/JSR-220 persistence annotations. However, we expect that this work is already
very close to the final concepts in the new specification. Our goal is to provide
a complete set of ORM annotations, including EJB3 standard annotations as well as
Hibernate3 extensions for cases not covered by the specification. See the href="#gen37">Compliance and Limitations section for more
information.



1. Introduction



Hibernate, like all other object/relational mapping tools, requires metadata that
governs the transformation of data from one representation to the other (and vice
versa). In Hibernate 2.x, mapping metadata is most of the time declared in XML text
files. Another option is XDoclet, utilizing Javadoc source code annotations and a
preprocessor at compile time. The same kind of annotation support is now available in
the standard JDK, although more powerful and better supported by tools. IntelliJ IDEA,
and Eclipse for example, supports auto-completion and syntax highlighting of JDK 5.0
annotations.
The new revision of the EJB specification (JSR-220) uses JDK 5.0 annotations as the
primary metadata mechanism. Hibernate3 implements the EntityManager of JSR-220
(the persistence API). The Hibernate Annotations package contains the EJB3 and Hibernate3
extension annotations and their internal binding to the Hibernate core.



2. Requirements




  • Download and unpack hibernate-annotations-3.0beta1 from the Hibernate website

  • Download and unpack hibernate-3.0 from the Hibernate website



  • Make sure you have JDK 5.0 installed.
    You can of course continue using XDoclet and get some of the benefits of
    annotation-based metadata with older JDK versions. Note that this document only
    describes JDK 5.0 annotations and you have to refer to the XDoclet documentation for
    more information.



    3. Setup and configuration



    First, set up your classpath (after you have created a new project in your favorite IDE):



  • Copy all Hibernate3 core and required 3rd party library files (see lib/README.txt in Hibernate).

  • Copy hibernate-annotations.jar and lib/ejb-3.0-edr2.jar from the
    Hibernate Annotations distribution to your classpath as well.

    We also recommend a small wrapper class to startup Hibernate in a static initializer block,
    known as HibernateUtil. You might have seen this class in various forms in other
    areas of the Hibernate documentation. For Annotation support you have to enhance this
    helper class as follows:





    package hello;

    import org.hibernate.*;
    import org.hibernate.cfg.*;
    import test.*;
    import test.animals.Dog;

    public class HibernateUtil {

    private static final SessionFactory sessionFactory;

    static {
    try {

    sessionFactory = new AnnotationConfiguration()

    .addPackage("test")
    .addAnnotatedClass(Flight.class)
    .addAnnotatedClass(Sky.class)
    .addAnnotatedClass(Person.class)
    .addAnnotatedClass(Dog.class)

    .buildSessionFactory();
    } catch (Throwable ex) {
    // Log exception!
    throw new ExceptionInInitializerError(ex);
    }
    }

    public static Session getSession()
    throws HibernateException {
    return sessionFactory.openSession();
    }
    }



    Interesting here is the use of AnnotationConfiguration and the declaration
    of a package and persistent classes.


    Alternatively, you can declare your annotated packages and classes in your usual
    XML configuration file (usually hibernate.cfg.xml). Here is the equivalent of the
    above declaration




    <!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

    <hibernate-configuration>
    <session-factory>
    <mapping resource="test/Boat.hbm.xml"/>
    <mapping package="test"/>
    <mapping class="test.Flight"/>
    <mapping class="test.Sky"/>
    <mapping class="test.Person"/>
    <mapping class="test.animals.Dog"/>

    </session-factory>
    </hibernate-configuration>


    This kind of declaration is certainly a preferred way. Note that you can mix the the hbm.xml use
    and the new annotation one.



    There is no other difference in the way you use Hibernate APIs with Annotations, expect for
    this change in the startup routine or in the configuration file. You can use your favorite
    configuration method for other properties (hibernate.properties, hibernate.cfg.xml, programmatic
    APIs, etc). You can even mix annotated persistent classes and classic hbm.cfg.xml
    declarations with the same SessionFactory. You can however not declare a class several
    times (whether annotated or through hbm.xml). For annotated classes, the classes have to be added
    before their subclasses (this limitation will likely be removed soon), e.g.:





    cfg.addAnnotatedClass(Animal.class);
    cfg.addAnnotatedClass(Dog.class); // OK

    cfg.addAnnotatedClass(Dog.class);
    cfg.addAnnotatedClass(Animal.class); // AnnotationException!



    4. Mapping with EJB3 Annotations



    EJB3 entity beans are plain POJOs. Actually they represent the exact same concept as the
    Hibernate entities. Their mappings are defined through the JDK 5.0
    annotation feature (an XML descriptor syntax hasn't been finalized in the specification).
    Annotations come in two categories, the logical mapping annotations (allowing you to
    describe the object model, the class associations, etc.) and the physical mapping
    annotations (decribing the physical schema, tables, columns, indexes, etc). We will
    mix annotations from both categories in the following code examples.


    Annotations are in the javax.persistence.* package. IntelliJ is know to work well on it.



    4.1 Declaring an entity bean



    Every bound persistent POJO class is an entity bean and is declared using the
    @Entity annotation (at the class level):





    @Entity
    public class Flight implements Serializable {
    Long id;

    @Id
    public Long getId() { return id; }

    public setId(Long id) { this.id = id; }
    }



    For a full example, see Flight.java
    of the test suite.



    @Entity declares the class as an entity bean (i.e. a persistent POJO class),
    @Id declares the identifier property of this entity bean. The other mapping
    declarations are implicit. This configuration by exception concept is central to the
    new EJB3 specification and a major improvement. The class Flight is mapped to
    the Flight table, using the column id as its primary key column.



    The @Entity annotation allows you to define whether an entity bean should be
    accessed through its getters/setters methods (default) or wheher the entity manager should
    access the fields of the object directly:




    @Entity(access = AccessType.PROPERTY)
    or
    @Entity(access = AccessType.FIELD)



    The EJB3 spec requires that you declare annotations on the artefact
    that will be used, i.e. the getter method if you use PROPERTY access, the
    field if you use FIELD access.



    4.1.1 Defining the table



    @Table is set at the class level; it allows you to define the table,
    catalog, and schema names for your entity bean mapping. If no @Table is
    defined the default values are used: the unqualified class name of the entity.





    @Entity(access=AccessType.FIELD)
    @Table(name="tbl_sky")
    public class Sky implements Serializable {
    ...



    You can also define unique constraints to the table using the @UniqueConstraint annotation
    in conjunction with @Table (for a unique constraint bound to a sincle column, refer to @column).
    For a full example, see Sky.java
    of the test suite.



    4.1.2 Versioning for optimistic locking



    You can add optimistic locking capability to an entity bean using the
    @Version annotation:





    @Entity()
    public class Flight implements Serializable {
    ...
    @Version
    @Column(name="OPTLOCK")

    public Integer getVersion() { ... }
    }



    The version property will be mapped to the OPTLOCK column,
    and the entity manager will use it to detect conflicting updates (preventing lost
    updates you might otherwise see with the last-commit-wins strategy).



    4.1.3 Entity specific extensions


    To empower the EJB3 capabilities, hibernate provides specific annotations that
    match hibernate features. The org.hibernate.annotations package contains
    all these annotations extensions. Pleaser refer to the
    Hibernate Annotations API
    for a complete list.


    @org.hibernate.annotations.Entity extends @javax.persistence.Entity :


    • mutable: whether this entity is mutable or not

    • dynamicInsert: allow dynamic SQL for inserts

    • dynamicUpdate: allow dynamic SQL for updates

    • selectBeforeUpdate: Specifies that Hibernate should never perform an
      SQL UPDATE unless it is certain that an object is actually modified.

    • polymorphism: whether the entity polymorphism is of
      PolymorphismType.IMPLICIT (default) or PolymorphismType.IMPLICIT

    • persister: allow the overriding of the default persister implementation

    • optimisticLock: optimistic locking strategy (VERSION, NONE, DIRTY or ALL)


    @org.hibernate.annotations.BatchSize allows you to define the batch size when fetching
    instances of this entity ( eg. @BatchSize(size=4) )

    @org.hibernate.annotations.Proxy defines the lazyness attributes of the entity.
    lazy (default to true) define whether the class is lazy or not. proxyClassName
    is the interface to use for the lazy initializing proxies.

    @org.hibernate.annotations.Where defines an optional SQL WHERE clause used when
    instances of this class is retrieved.

    @org.hibernate.annotations.Check defines an optional check constraints defined
    at the class level.

    @org.hibernate.annotations.Cache defines the caching strategy and region of the class.
    This annotation is defined at the root entity (not the subentities).



    @org.hibernate.annotations.Filter or @Filters define filter(s) to an entity.
    A filter is defined by a name() and by a SQL condition()
    (with potential parameters).

    @org.hibernate.annotations.FilterDef or @FilterDefs define filter
    definition(s) used by filter(s) using the same name. A filter definition has a name()
    and an array of parameters(). A @ParamDef has a name and a type. A @FilterDef(s)
    can be defined at the class or package level.




    @Entity
    @BatchSize(size=5)
    @org.hibernate.annotations.Entity(
    selectBeforeUpdate = true,
    dynamicInsert = true, dynamicUpdate = true,
    optimisticLock = OptimisticLockType.ALL,
    polymorphism = PolymorphismType.EXPLICIT)
    @Where(clause="1=1")
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    @FilterDef(name="minLength", parameters={ @ParamDef( name="minLength", type="integer" ) } )
    @Filters( {
    @Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length"),
    @Filter(name="minLength", condition=":minLength <= length")
    } )
    public class Forest {



    Please refer to the test suite's
    entity package for more
    working examples.



    4.2 Mapping simple properties



    4.2.1 Declaring basic property mappings



    By default, every property of an entity bean is mapped persistent, unless you
    annotate it as @Transient. Not having an annotation for your property is
    equivalent to an appropriate basic annotation (see 4.2.4 for more details).
    The @Basic annotation allows
    you to declare the fetching strategy for a property:





    @Transient
    String getLengthInMeter() { ... }

    String getName() {... } // persistent property

    @Basic
    int getLength() { ... } // persistent property

    @Basic(fetch = FetchType.LAZY)
    String getDetailedComment() { ... }



    The lengthInMeter property is mapped transient and will be ignored by the
    entity manager. The name and the length properties are mapped persistent
    and eagerly fetched (the default for simple properties). The detailedComment
    property value will be lazily fetched from the database once a lazy property of the entity
    is accessed for the first time. The compiled code of your class has to be instrumented for
    this feature, please refer to the Hibernate reference documentation. Usually you don't need
    lazy simple property fetching (not to be confused with lazy association fetching) and can avoid
    any build-time bytecode instrumentation with Hibernate. Hibernate will silently disable lazy
    property fetching if you don't instrument the compiled class.


    @Serialized indicates that the property should be persisted as a serialized
    bytestream.


    @Lob indicates that the property should be persisted in a Blob or a Clob depending
    the of LobType. java.sql.Clob, Character[], char[] and String
    can be persisted in a Clob. java.sql.Blob, Byte[] and byte[]
    can be persisted in a Blob.



    	@Serialized
    public Country getCountry() {
    ...
    }

    @Lob(type=LobType.CLOB)
    public String getFullText() {
    return fullText;
    }

    @Lob(type = LobType.BLOB)
    public byte[] getFullCode() {
    return fullCode;
    }



    4.2.2 Declaring column attributes



    The columns use for a property mapping can be defined using the @Column annotation.
    Use it to override default values (see the EJB3 specification for more information on the
    defaults). You can use this annotation at the property level for properties that are, not annotated
    at all, annotated with @Basic, @Version, @Serialized
    and @Lob:





    @Entity()
    public class Flight implements Serializable {
    ...
    @Column(updatable = false, name = "flight_name", nullable = false, length=50)
    public String getName() { ... }



    The name property is mapped to the flight_name column, which is
    not nullable, has a length of 50 and is not updatable (making the property immutable).
    For more attributes of @Column please refer to the EJB3 spec.



    4.2.3 Embedded objects (components)



    It is possible to declare an embedded component inside an entity and even override its
    column mapping. Component classes (also known as user-defined value types) have to be
    annotated at the class level with the @Embeddable annotation. It is
    possible to override the column mapping of an embedded object for a particular entity
    using the @Embedded annotation in the associated property:





    @Entity(access = AccessType.FIELD)
    public class Person implements Serializable {

    // Persistent component using defaults
    Address homeAddress;

    @Embedded({
    @AttributeOverride(name="iso2", column = @Column(name="bornIso2") ),
    @AttributeOverride(name="name", column = @Column(name="bornCountryName") )
    })

    Country bornIn;
    ...
    }







    @Embeddable(access = AccessType.FIELD)
    public class Address implements Serializable {
    String city;
    Country nationality;
    }







    @Embeddable
    public class Country implements Serializable {
    private String iso2;
    private String name;

    public String getIso2() { return iso2; }
    public void setIso2(String iso2) { this.iso2 = iso2; }

    @Column(name="countryName")
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    ...
    }



    The Person entity bean has two component properties, homeAddress and
    bornIn. Note that the homeAddress property has not been annotated.
    Hibernate will guess that it is a persistent component after looking for the
    @Embeddable in the Address class. We also override the mapping of
    a column name (to bornCountryName) with the @Embedded and
    @AttributeOverride annotations for each mapped attribute of Country.
    As you can see, Country is also nested component of Address, again using
    auto-detection by Hibernate and EJB3 defaults. Overriding columns of dependent objects
    of dependent objects is currently not supported in the EJB3 spec (user feedbacks are welcome).



    4.2.4 Non annotated property


    • If the property is of a single type, it is mapped as @Basic

    • Otherwise, if the type of the property is annotated as @Embeddable

    • Otherwise, if the type of the property is Serializable, it is mapped as
      @Serialized

    • Otherwise, if the type of the property is java.sql.Clob or
      java.sql.Blob, it is mapped as @Lob with the appropriate
      LobType



    4.2.5 Property specific extensions


    @org.hibernate.annotations.Type overrides the default hibernate type used: this
    is generally not necessary since the type is correctly inferred by Hibernate.
    Please refer to the Hibernate reference guide for more informations on the Hibernate types.

    @org.hibernate.annotations.TypeDef and @org.hibernate.annotations.TypeDefs
    allows you to define type defintions. These annotations are placed at the class or package level.
    Note that these definitions will be global for the session factory (even at the class level)
    and that type definition has to be defined before any usage.




    @TypeDefs(
    {
    @TypeDef(
    name="caster",
    typeClass = CasterStringType.class,
    parameters = {
    @Parameter(name="cast", value="lower")
    }
    )
    }
    )
    package org.hibernate.test.annotations.entity;

    ...
    public class Forest {
    @Type(type="caster")
    public String getSmallText() {
    ...
    }



    4.3 Mapping identifier properties



    The @Id annotation lets you define which property is the identifier of your
    entity bean. It also allows you to define the identifier generation strategy:




    • AUTO - either identity column or sequence depending the underlying DB
    • TABLE - table holding the id
    • IDENTITY - identity column
    • SEQUENCE - sequence
    • NONE - the application has the responsability to set the id


    The following example shows a sequence generator using the SEQ_STORE
    configuration (see below):





    @Id(generate=GeneratorType.SEQUENCE, generator="SEQ_STORE")
    public Integer getId() { ... }



    The next example uses the identity generator:





    @Id(generate=GeneratorType.IDENTITY)
    public Integer getId() { ... }



    The AUTO generator is the preferred type for portable applications (accross several dB vendors).
    The identifier generation configuration can be shared for several @Id mappings
    with the generator attribute. There are several configurations available through
    @SequenceGenerator, @TableGenerator and @GeneratorTable. The scope
    of a generator can be the application or the class. Class-defined generators are not visible outside
    the class and can override application level generators. Application level generators are
    defined at package level
    (see package-info.java):






    @javax.persistence.GeneratedIdTable(
    name="GEN_TABLE",
    table = @Table(name="GENERATOR_TABLE"),
    pkColumnName = "key",
    valueColumnName = "hi"
    )
    @javax.persistence.TableGenerator(
    name="EMP_GEN",
    tableName="GEN_TABLE",
    pkColumnValue="EMP",
    allocationSize=20
    )
    @javax.persistence.SequenceGenerator(
    name="SEQ_GEN",
    sequenceName="my_sequence"
    )

    package org.hibernate.test.metadata;



    If cfg.addPackage("org.hibernate.test.metadata") is used to initialize the
    Hibernate config, EMP_GEN and SEQ_GEN are application level generators.
    EMP_GEN defines a table based id generator using the hilo algorithm with a
    max_lo of 20 and keeping the hi value in a row of a table defined by the GEN_TABLE
    @GeneratorTable. The row has EMP as a primary key value. The table (described by
    the @GeneratorTable) is GENERATOR_TABLE, had the column key
    (which hold the primary key) and the column hi (which hold the next hi value used).


    SEQ_GEN defines a sequence generator using a sequence
    named my_sequence. Note that this version of Hibernate Annotations does not
    handle initialValue and allocationSize parameters in the SequenceGenerator.

    The next example shows the definition of a sequence generator in a class scope:





    @Entity
    @javax.persistence.SequenceGenerator(
    name="SEQ_STORE",
    sequenceName="my_sequence"
    )

    public class Store implements Serializable {
    private Long id;

    @Id(generate=GeneratorType.SEQUENCE, generator="SEQ_STORE")
    public Long getId() { return id; }
    }



    This class will use a sequence named my_sequence and the SEQ_STORE
    generator is not visible in other classes. Note that you can Have a look at the Hibernate Annotations
    tests in the org.hibernate.test.metadata.id package for more examples.



    You can define a composite primary key through several syntaxes:

  • annotate the component property as @Id and make the component class @Embeddable

  • annotate the component property as @EmbeddedId

  • annotate the class as @IdClass (this mapping is currently not supported by the
    implementation).

    Have a look at Child.java and
    Parent.java for some
    examples.



    4.3 Mapping inheritance



    EJB3 supports the three types of inheritance:



    • Table per Class Strategy: the <class> element in Hibernate
    • Single Table per Class Hierarchy Strategy: the <subclass> element in Hibernate
    • Joined Subclass Strategy: the <joined-subclass> element in Hibernate


    The chosen strategy is declared at the class level using the @Inheritance annotation.

    4.3.1 Table per class



    This strategy has many drawbacks (esp. with polymorphic queries and associations)
    explained in the EJB3 spec,the Hibernate reference documentation, Hibernate in Action,
    and many other places. It is commonly used for the top level of an inheritance
    hierarchy:





    @Entity()
    @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
    public class Flight implements Serializable {



    You have to declare inheritance on the leave classes (note: this is an
    interpretation of the spec and is subject to change).



    4.3.2 Single table per class hierarchy



    All properties of all super- and subclasses are mapped to the same table, instances
    are distinquished with a special discriminator column:





    @Entity()
    @Inheritance(
    strategy=InheritanceType.SINGLE_TABLE,
    discriminatorType=DiscriminatorType.STRING,
    discriminatorValue="Plane"
    )
    @DiscriminatorColumn(name="planetype")

    public class Plane { ... }

    @Entity()
    @Inheritance(
    discriminatorValue="A320"
    )

    public class A320 extends Plane { ... }



    Plane is the superclass, it defines the inheritance strategy
    InheritanceType.SINGLE_TABLE, the discriminator type DiscriminatorType.STRING,
    and the discriminator value used for planes, "Plane". It also defines the
    discriminator column through the @DiscriminatorColumn(name="planetype"). Most of
    these atttributes have sensible default values. The default name of the discriminator column
    is TYPE, and (for Hibernate) the default discriminator value is the fully qualified
    class name. A320 is a subclass; you only have to define discriminatorValue
    if you won't accept the default. The strategy and the discriminator type is implicit.



    4.3.2 Joined subclasses



    This strategy has to be declared on all the subclasses. The @InheritanceJoinColumn
    and @InheritanceJoinColumns annotations define the primary key(s) of the joined
    subclass table. Note that the current implementation does not support implicit
    @InheritanceJoinColumns:





    @Entity()
    @Inheritance(strategy=InheritanceType.JOINED )
    public class Boat implements Serializable { ... }

    @Entity()
    @Inheritance(strategy=InheritanceType.JOINED)
    public class Ferry extends Boat { ... }

    @Entity(access=AccessType.FIELD)
    @Inheritance(strategy=InheritanceType.JOINED)
    @InheritanceJoinColumn(name="BOAT_ID")

    public class AmericaCupClass extends Boat { ... }



    Every entity bean declares the JOINED strategy, the Ferry
    table is joined with the Boat table using the same primary key names. The
    AmericaCupClass table is joined with Boat using the join
    condition Boat.id = AmericaCupClass.BOAT_ID.



    4.4 Mapping entity bean associations



    4.4.1 One-to-one



    You can associate entity beans with a one-to-one relationship using @OneToOne.
    There are two cases for one-to-one associations: either the associated entities share the
    same primary keys values or a foreign key is held by one of the entities (note that this FK
    column in the database should be constrained unique to simulate one-to-one multiplicity).



    First, we map a real one-to-one association using shared primary keys:





    @Entity
    public class Body {
    @Id
    public Long getId() { return id; }

    @OneToOne(cascade = CascadeType.ALL, usePKasFK=true)
    public Heart getHeart() {
    return heart;
    }
    ...
    }







    @Entity
    public class Heart {
    @Id(generate = GeneratorType.NONE)
    public Long getId() { ...}
    }



    Unfortunatly, in the current release of Hibernate Annotations, the Heart
    identifier value has to be set manually by the application developer. Support for a
    Hibernate-style "foreign" identifier generator will be added soon.



    In the following example, the associated entities are linked through a foreign key
    column :





    @Entity
    public class Customer implements Serializable {
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="passport_fk")
    public Passport getPassport() {
    ...
    }

    @Entity
    public class Passport implements Serializable {
    @OneToOne(mappedBy = "passport")
    public Customer getOwner() {
    ...
    }



    A Customer is linked to a Passport, with a foreign key column named
    passport_fk in the Customer table. The join column is declared with the
    @JoinColumn annotation which looks like the @Column annotation. It has
    one more parameter named referencedColumnName. This parameter declares the column
    in the targetted entity that will be used to the join. The current implementation does not
    support the referencedColumnName attribute, so Hibernate will join to the primary
    key (default value in the specification).


    The association may be bidirectional. In a bidirectional relationship, one of the side
    has to be the owner : the owner is responsible for the association column(s) update. To
    declare a side as non responsible for the relationship, the attribute mappedBy
    is used. mappedBy refers the property name of the association on the owner side.
    In our case, this is 'passport'. As you can see, you don't have to (must not) declare the
    joining column since it is already on the other side.


    If no @JoinColumn is declared on the owner side, the defaults apply. A join
    column(s) will be created in the owner table and its name will be the concatenation of the
    name of the relationship in the owner side, '_' (underscore), and the name of the primary
    key column(s) in the owned side. In this example 'passport_id' because the property name is
    passport and the column id of Passport is 'id'.



    4.4.2 Many-to-one



    Many-to-one associations are declared at the property level with the annotation
    @ManyToOne; it has a parameter named targetEntity which describes the
    target entity name. You usually don't need this parameter since the default value (the
    type of the property that stores the association) is good in almost all cases:





    @Entity()
    public class Flight implements Serializable {
    @ManyToOne( cascade = {CascadeType.CREATE, CascadeType.MERGE} )
    @JoinColumn(name="COMP_ID")
    public Company getCompany() {
    return company;
    }
    ...
    }



    The @JoinColumn attribute is optional, the default value(s) is like in one to one,
    the concatenation of the
    name of the relationship in the owner side, '_' (underscore), and the name of the primary
    key column in the owned side. In this example 'company_id' because the property name is
    company and the column id of Company is 'id'.


    In case of a bidirectional, a many to one is always the owner side.



    4.4.3 One-to-many



    One-to-many associations are declared at the property level with the annotation
    @OneToMany. In the current EJB3 specification, you can map Collection
    and Set (Map and List are not defined in the spec so far).
    Unless the collection is a generic, you'll have to defined targetEntity. One to many
    associations may be bidirectional.



    4.4.3.1 Bidirectional

    Since many to one are always the owner side of a bidirectional relationship in the EJB3 spec,
    the one to many association is annotated by @OneToMany( mappedBy=... )


    @Entity
    public class Troop {
    @OneToMany(mappedBy="troop")
    public Set<Soldier> getSoldiers() {
    ...
    }

    @Entity
    public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk")
    public Troop getTroop() {
    ...


    Troop has a bidirectional one to many relationship with Soldier
    through the 'troop' property. You don't have to (must not) define any physical
    mapping in the mappedBy side.



    4.4.3.2 Unidirectional

    A unidirectional one to many using a foreign key column in the owned entity is not
    so common and not really recommanded. We strongly advise you to use a join table
    for this kind of association (as explained in the next section). This kind of
    association is described through a @JoinColumn



    @Entity
    public class Customer implements Serializable {
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    @JoinColumn(name="CUST_ID")
    public Set<Ticket> getTickets() {
    ...
    }

    @Entity
    public class Ticket implements Serializable {
    ... //no bidir
    }


    Customer describes a unidirectional relationship with Ticket using the
    join column 'CUST_ID'.



    4.4.3.3 Unidirectional with join table

    A unidirectional one to many with join table is much preferred. This association
    is described through a @AssociationTable.


    @Entity()
    public class Trainer {
    @OneToMany
    @AssociationTable(
    table=@Table(name="TrainedMonkeys"),
    joinColumns = { @JoinColumn( name="trainer_id") },
    inverseJoinColumns = @JoinColumn( name="monkey_id")
    )
    public Set<Monkey> getTrainedMonkeys() {
    ...
    }

    @Entity
    public class Monkey {
    ... //no bidir
    }


    Trainer describes a unidirectional relationship with Monkey using the
    join table 'TrainedMonkeys', with a foreign key 'trainer_id' to Trainer (joinColumns)
    and a foreign key 'monkey_id' to Monkey (inversejoinColumns).



    4.4.3.4 Default values


    Without describing any physical mapping, a unidirectional one to many
    with join table is used. The table name is the concatenation of the owner
    table name, '_', and the other side table name. The foreign key name(s) referencing
    the owner table is the concatenation of the owner table, '_', and the owner
    primary key column(s) name. The foreign key name(s) referencing the other side is the
    concatenation of the owner property name, '_', and the other side primary key
    column(s) name. A unique constraint is added to the foreign key referencing the
    other side table to reflect the one to many.




    @Entity()
    public class Trainer {
    @OneToMany
    public Set<Tiger> getTrainedTigers() {
    ...
    }

    @Entity
    public class Tiger {
    ... //no bidir
    }


    Trainer describes a unidirectional relationship with Tiger using the
    join table 'Trainer_Tiger', with a foreign key 'trainer_id' to Trainer
    (table name, '_', trainer id) and a foreign key 'trainedTigers_id' to Monkey
    (property name, '_', Tiger primary column).



    4.4.4 Many-to-many



    4.4.4.1 description


    A many-to-many association is defined logically using the @ManyToMany annotation.
    You also have to describe the association table and the join conditions using the
    @AssociationTable annotation. If the association is bidirectional, one side has to be
    the owner and one side has to be the inverse end (ie. it will be ignored when updating the
    relationship values in the association table):





    @Entity()
    public class Employer implements Serializable {
    @ManyToMany(
    targetEntity="org.hibernate.test.metadata.manytomany.Employee",
    cascade={CascadeType.CREATE, CascadeType.MERGE}
    )
    @AssociationTable(
    table=@Table(name="EMPLOYER_EMPLOYEE"),
    joinColumns={@JoinColumn(name="EMPER_ID")},
    inverseJoinColumns={@JoinColumn(name="EMPEE_ID")}
    )

    public Collection getEmployees() {
    return employees;
    }
    ...
    }







    @Entity()
    public class Employee implements Serializable {
    @ManyToMany(
    cascade={CascadeType.CREATE, CascadeType.MERGE},
    mappedBy="employees"
    )
    public Collection getEmployers() {
    return employers;
    }
    }



    We've already shown the many declarations and the detailed attributes for associations.
    We'll go deeeper in the @AssociationTable description, it defines a @Table,
    an array of join columns (an array in annotation is defined using { A, B, C }),
    and an array of inverse join columns. The latter ones are the columns of the association
    table which refer to the Employee primary key (the "other side"). Note that the current implementation
    mandates that you join the entity primary keys, referencedColumnName for
    other non pk columns is not supported.


    As seen previously, the other side don't have to (must not) describe the physical
    mapping: a simple mappedBy argument containing the owner side property name bind
    the two.



    4.4.4.1 Default values


    As any other annotations, most values are guessed in a many to many relationship.
    Without describing any physical mapping in a unidirectional many to many
    the following rules applied. The table name is the concatenation of the owner
    table name, '_' and the other side table name. The foreign key name(s) referencing the owner
    table is the concatenation of the owner table name, '_' and the owner primary key
    column(s). The foreign key name(s) referencing the other side is the concatenation of
    the owner property name, '_', and the other side primary key column(s). These are
    the same rules used for a unidirectional one to many relationship.





    @Entity()
    public class Store {
    @ManyToMany(cascade = CascadeType.PERSIST)
    public Set<City> getImplantedIn() {
    ...
    }

    @Entity()
    public class City {
    ... //no bidirectional relationship
    }


    A 'Store_Table' is used as the join table. The 'Store_id' column is a foreign key
    to the 'Store' table. The 'implantedIn_id' column is a foreign key to the 'City' table.


    Without describing any physical mapping in a bidirectional many to many
    the following rules applied. The table name is the concatenation of the owner
    table name, '_' and the other side table name. The foreign key name(s) referencing the owner
    table is the concatenation of the other side property name, '_', and the owner primary
    key column(s). The foreign key name(s) referencing the other side is the concatenation of
    the owner property name, '_', and the other side primary key column(s). These are
    the same rules used for a unidirectional one to many relationship





    @Entity()
    public class Store {
    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    public Set<Customer> getCustomers() {
    ...
    }

    @Entity()
    public class Customer {
    @ManyToMany(mappedBy="customers")
    public Set<Store> getStores() {
    ...
    }


    A 'Store_Customer' is used as the join table. The 'stores_id' column is a foreign key
    to the 'Store' table. The 'customers_id' column is a foreign key to the 'City' table.


    Check the unit tests contained in the manytomany package,

    4.4.5 Transitive persistence with cascading



    You probably have noticed the cascade taking an array of CascadeType as a value.
    The cascade concept in EJB3 is very is similar to the transitive persistence and cascading
    of operations in Hibernate, but with slighty different semantics and cascading types:




    • CascadeType.PERSIST: cascades the persist (create) operation to associated entities persist() is called or if the entity is managed
    • CascadeType.MERGE: cascades the merge operation to associated entities if merge() is called or if the entity is managed
    • CascadeType.REMOVE: cascades the remove operation to associated entities if delete() is called
    • CascadeType.REFRESH: cascades the refresh operation to associated entities if refresh() is called
    • CascadeType.ALL: all of the above


    Please refer to the chapter 6.3 of the EJB3 specification for more information on
    cascading and and create/merge semantics.



    4.4.6 Association fetching



    You have the ability to either eagerly or lazily fetch associated entities. The fetch
    parameter can be set to FetchType.LAZY or FetchType.EAGER. EAGER will
    try to use an outer join select to retrieve the associated object, while LAZY is the
    default and will only trigger a select when the associated object is accessed for the first time.



    4.4.7 Collection specific extensions


    It is possible to set

    • the batch size for collections using @BatchSize

    • the where clause, using @Where

    • the check clause, using @Check

    • the caching strategy through the @Cache annotation.


    Please refer to the previous descriptions of these annotations
    for more informations



    4.5 Mapping composite primary and foreign keys



    Composite primary keys use a component class as the primary key representation, so you'd use
    the @Id and @Embeddable annotations. Alternatively, you can use the
    @EmbeddedId annotation. Note that the dependent class has to be
    serializable. This implementation only support composite identifiers with component classes.





    @Entity
    public class RegionalArticle implements Serializable {

    @Id(generate = GeneratorType.NONE)
    public RegionalArticlePk getPk() { ... }
    }

    @Embeddable(access = AccessType.FIELD)
    public class RegionalArticlePk implements Serializable { ... }


    or alternatively




    @Entity
    public class RegionalArticle implements Serializable {

    @EmbeddedId()
    public RegionalArticlePk getPk() { ... }
    }

    public class RegionalArticlePk implements Serializable { ... }



    @Embeddable can define either a field or a property access strategy for the
    component. Composite foreign keys (if not using the default sensitive values) are defined
    on associations using the @JoinColumns element, which is basically an array
    of @JoinColumns. It is considered a good practice
    to express referencedColumnNames explicitely. Otherwise, Hibernate will suppose
    that you use the same order of columns as in the primary key declaration.





    @Entity(access = AccessType.FIELD)
    public class Parent implements Serializable {
    @Id
    public ParentPk id;
    public int age;

    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumns ({
    @JoinColumn(name="parentCivility", referencedColumnName = "isMale"),
    @JoinColumn(name="parentLastName", referencedColumnName = "lastName"),
    @JoinColumn(name="parentFirstName", referencedColumnName = "firstName")
    })

    public Set<Child> children; //unidirectional
    ...
    }







    @Entity(access = AccessType.FIELD)
    public class Child implements Serializable {
    @Id(generate = GeneratorType.AUTO)
    public Integer id;

    @ManyToOne()
    @JoinColumns ({
    @JoinColumn(name="parentCivility", referencedColumnName = "isMale"),
    @JoinColumn(name="parentLastName", referencedColumnName = "lastName"),
    @JoinColumn(name="parentFirstName", referencedColumnName = "firstName")
    })

    public Parent parent; //unidirectional
    }







    @Embeddable(access = AccessType.FIELD)
    public class ParentPk implements Serializable {
    String firstName;
    String lastName;
    ...
    }





    Note the explicit usage of the referencedColumnName.



    A many-to-many association works the same way, you can find an example in
    Man.java,
    ManPk.java,
    Woman.java,
    WomanPk.java

    4.6 Mapping secondary tables



    You can map a single entity bean to several tables using the @SecondaryTable
    or @SecondaryTables class level annotations. To express that a column is in
    a particular table, use the secondaryTable parameter of @Column or
    @JoinColumn. You can find some examples in
    Cat.java,
    Life.java,
    Death.java

    5. Mapping Queries


    You can map EJBQL/HQL queries using annotations. @NamedQuery and
    @NamedQueries can be defined at the class or at the package level.
    However their definition is global to the session factory scope.
    A named query is defined by its name and the actual query string.



    @javax.persistence.NamedQueries(
    @javax.persistence.NamedQuery(name="plane.getAll", queryString="select p from Plane p")
    )
    package org.hibernate.test.annotations.query;

    ...

    @Entity
    @NamedQuery(name="night.moreRecentThan", queryString="select n from Night n where n.date >= :date")
    public class Night {
    ...
    }

    public class MyDao {
    doStuff() {
    Query q = s.getNamedQuery("night.moreRecentThan");
    q.setDate( "date", aMonthAgo );
    List results = q.list();
    ...
    }
    ...
    }



    5. Compliance and limitations




    3.0 Preview beta1 (07-04-2005) based on the EJB3 Early Draft 2
    --------------------------------------------------------------
    * support parameters in @Type (HBX-197)
    * support @TypeDef at package and class level
    * HBX-166 support @Lob for Character[],char[], String, byte[] and Byte[] (experimental)
    * HBX-159/HBX-140 add @Filter(s) and @FilterDef(s) (Matthew Inger, Magnus Sandberg)
    * HBX-44 @OneToOne support composite PK
    * @OneToOne is supported except for true bidirectional @OneToOne
    * Add @Cache annotation: allow to define caching on root entities and on collections (,eg @Cache(usage=CacheConcurrencyStrategy.TRANSACTIONAL, region="specificCacheRegion") )
    * Support @OneToMany default (ie using an association table)
    * HBX-164 insertable/updatable of @JoinColumn now work in @ManyToOne processing (Mario Ivankovits, Emmanuel Bernard)
    * HBX-153 @Id(generate=GeneratorType.AUTO, generator="my_potential_sequence") now work (Pablo Nussembaum)
    * Support @ManyToMany wo @AssociationTable (ie defaults)
    * Support @ManyToMany(mappedBy)
    * Support @OneToMany(mappedBy) (no JoinColumn needed on the @OneToMany side)
    * Appropriate default value when no @JoinColumn is defined in a ManyToOne
    * rename @GeneratorTable to @GeneratedIdTable
    * rename CREATE to PERSIST, add REFRESH cascade style
    * support Mapping Defaults for Non-Relationship Fields or Properties algorithm as defined in the EJB3 spec
    * support @Serialized
    * support @Lob for java.sql.Clob and java.sql.Blob
    * allow embedded object declaration wo @Embeddable (if @Embedded or @EmbeddedId is present in the property)
    * support for @EmbeddedId
    * rename DependentAttribute to AttributeOverride, Dependent to Embedded and DependentObject to Embeddable
    * support @ManyToOne in embedded objects
    * support for @NamedQuery and @NamedQueries (EJBQL)
    * move javax.ejb.* into javax.persistence.* and update copyright header

    3.0alpha3 (28-02-2005)
    ----------------------
    * HBX-116 Support for Where clause in classes and collections @Where(clause="")
    * HBX-115 Support for class proxying configuration: @Proxy(lazy=false, proxyClassName="my.Interface")
    * HBX-88 Support for hibernate type abstraction through @Type (only on basic properties for now)
    * HBX-108 Support @BatchSize(size=n) for entities and collections
    * HBX-107 implements @org.hibernate.annotations.Entity
    * HBX-103 handle abstract classes
    * HBX-83 precision & scale support for column (Bogdan Ghidireac)

    3.0alpha2 (25-01-2005)
    ----------------------
    * HBX-61 Support for @UniqueConstraint (except primaryKey=true)
    * HBX-60 Support for a proper @TableGenerator (using MultipleHiLoPerTableGenerator)
    * HBX-63 Support @GeneratorTable
    * HBX-68 Add declarative configuration of annotated classes
    * HBX-74 Rollback the HB-1315 fix: dialect no longer have to be set in hibernate.properties


    Hibernate-annotations-3.0alpha1 based on the EJB3 Early Draft 1 (6.01.2005)
    ---------------------------------------------------------------------------
    * Support for EJB3 annotations:
    - @Transient
    - @Column (not primaryKey)
    - @JoinColumn (referencedColumnName - only for a reference to a PK, not primaryKey)
    - @Version
    - @Basic
    - @Entity
    - @Table (not uniqueConstraints)
    - @AccessType
    - @Id
    - @CascadeType
    - @FetchType
    - @GeneratorType (NONE, IDENTITY, TABLE, SEQUENCE)
    - @TableGenerator (with scope visibility)
    - @SequenceGenerator (with scope visibility, does not support initialValue() and allocationSize())
    - *not* @GeneratorTable (will have to write a new TableHiloGenerator, but it can wait)
    - @ManyToOne (not optional)
    - @OneToMany (Set and Collection, generics version or not, JoinColumn not guessed)
    - @OneToOne
    but not optional
    no composite PK/FK
    - @ManyToMany
    - @AssociationTable (Has to be on both sides)
    - @Inheritance
    - @InheritanceType (has to be defined on every classes of the hierarchy for JOINED strategy,
    not very clear about the TABLE_PER_CLASS strategy)
    - @DiscriminatorColumn
    - @DiscriminatorType
    - @InheritanceJoinColumn
    - @InheritanceJoinColumns
    this annotation for Composite PK Entities has to be explicit, I do not respect the implicit semantic of the EJB3 spec
    - @SecondaryTable (@OneToMany @JoinColumn(secondaryTable="..." does not work yet due to H3 core issue HHH-36
    - @SecondaryTables
    this annotation for Composite PK Entities has to be explicit, I do not respect the implicit semantic of the EJB3 spec
    - @DependentObject
    - @Dependent
    - @DependentAttribute (only for basic properties as per the spec)
    - @Id in conjunction with @DependentObject (composite primary keys)
    - @JoinColumns in conjunction with @ManytoOne, @OneToMany, @ManytoMany
    - note that the composite FK columns have to be in the same table (no != secondary tables). This is probably a weird case and certainly a not recommanded one.


    Still missing or incomplete features compared to the EJB3 spec
    --------------------------------------------------------------
    - use of referencedColumnName for column other than the PK ones (HX-62)
    - better semantic of cascade (HBX-47)
    - Support for a true bidirectional one to one relationship (HBX-177)
    - inheritance declaration parsing should be more robust (HBX-186)
    - annotations inheritance and superclasses (HBX-157) (to be addressed by the next draft)
    - appropriate fetching mode on queries (HBX-87)
    - implicit join column declaration in inheritance with composite PK (HBX-75)
    - @UniqueConstraint(primaryKey=true) (HBX-82)
    - support for initialValue and allocationSize in @SequenceGenerator (HBX-59)
    - finish support of optional=false (HBX-190)
    - @IdClass (HBX-213)


    6. Useful links



    Hibernate Annotations API

    The EJB3 Specification

    The EJB3 JBoss tutorial

    The Hibernate reference guide

    Hibernate In Action



  • Posted by 아름프로
    최근 자바진형은 붐이라고 할 정도로 오픈소스 프로젝트에 많은 정성과 노력들을 쏳고 있다.
    벤더들 마져 이를 지원하며 IBM의 eclipse, Sun의 netBeans, BEA의 Beehive 등은 이러한 추세에
    더욱 불을 지피고 있다.

    몇년간은 수없이 쏳아져나오는 오픈소스로 인하여 즐겁기도 했지만, 한편으로는 이들을 선별하는데
    있어서 너무도 어려움이 있을 만큼의 어려움을 겪기도 했었다.
    하지만, 최근에는 이러한 것에서 벗어나 성능과 안정성을 입증 받은 오픈소스의 경우는 상당히 큰
    커뮤니티를 형성하며 조직적인 모습을 갖추어 나가고 있다.
    대표적인 것들로는 apache 프로젝트의 대다수의 프로젝트들, Springframework, HIbernate, Xdoclet,
    iBaits, webwork, jboss .. 등을 들 수가 있다.

    시간의 흐름에 따라 이렇듯 좋은 솔루션들이 선별됨에 따라 개발자에게는 기존의 여러 솔루션을
    테스트하고 시행착오을 겪던 것을 많이 줄 일 수 있게 되어 큰 도움이 되고 있다.

    하지만, 이러한 장점만이 나타주면 좋으련만 단점 또한 나타나고 있는 듯하다.

    첫째, 한가지 솔루션에 대한 맹신으로 다른 솔루션을 배척하는 이가 생겨나기 시작하고,
    둘째, 어떤 솔루션이든 그것이 등장하기에는 그 사상과 이유가 있어서 였다는 것을 잊을 채, 그 솔루션의
            기능적인 측면만을 공부하고 익히려는 경향이 나타나고 있으며,
    세째, 새로운 것을 스스로 만들거나, 찾으려하는 노력이 줄어들고 있으며
    네째, 다른이가 만든 것에 대한 불신이 팽배해지고 있다.
             (특정 단체나 검증을 거치지 않은 것에 대해서는 무조건 불신하는 태도를 뜻한다.)
            
    오픈소스...
    잘쓰면 보약과도 같지만, 그렇지 않으면 자칫 독이 될 수도 있다는 것을 개발자 스스로가 한번쯤은 되집어 봐야될 것 같다.

    기능을 확실히 익히면서도 그 사상적인 이해가 곁들여져야할 것이며,
    이를 사용함에 있어서는 주위의 사람들의 의견이나 생각들도 함께 잘 어울어져야만
    할 것이다.
    Posted by 아름프로

    사이트의 성격이 너무 기록을 남기기만 하는거 같아서
    생각도 함께 남기는 차원에서 새로운 게시판을 오픈해 봅니다.

    얼마나 많은 이야기들이 채워질지는 모르겠지만,
    좋은 공간이 되었으면 합니다.

    방문하시는 모든 분들에게 오픈되는 공간이기도하니
    많은 글 올려주세요.

    단, 질문의 글은 사양합니다.
    Posted by 아름프로
    크게 네부분에서의 성능 향상이 있었습니다.
    이중에서 일반 개발자 관점에서의 주목되는 부분은 StringBuffer 클래스의 등장과 어플리케이션 개발 차원에서의 2D쪽과 Image I/O 향상이네요.


    Enhancements in JDK 5.0



    The following are some of the enhancements made for improved
    program execution speed in JDK 5.0.

    • Garbage collection ergonomics - Provides for the automatic
      detection and choice of the client or server runtime compiler,
      which enhances performance on server-class machines.
      See "Server-Class Machine Detection" and "Garbage Collection
      Ergonomics" at Java
      Virtual Machines
      for more information.



    • StringBuilder class - The addition of a new class
      StringBuilder
      that works essentially as an unsynchronized StringBuffer for performance
      enhancement. You should replace all StringBuffer uses with StringBuilder
      unless you need the synchronization (which you almost certainly don't).
      StringBuilder is almost always faster than StringBuffer.



    • Java 2DTM technology -
      These Java 2D performance enhancements have spin-off performance
      benefits in other areas of functionality such as Swing/JFC.
      Examples include improved acceleration for BufferedImage objects,
      support for hardware-accelerated rendering using OpenGL,
      and improved text-rendering performance.
      See New Java 2D Features
      for more information.



    • Image I/O - Performance and memory usage improvements have been
      made when reading and writing JPEG images. See "Improved Performance" at
      Image I/O Features.



    Posted by 아름프로
    Image I/O Support for BMP and WBMP Formats

    BMP와 WBMP 포멧의 읽기 쓰기가 가능해졌습니다.

    javax.imageio 패키지를 통해서 JPEG, PNG, BMP, WBMP의 읽기 쓰기가 가능해졌고,
    GIF이미지는 읽기기능이 가능해졌습니다.

    이 변경에 관련하는 버그 리포트: 4339462 및 4339384


    성능 향상 부분

    Image I/O API 에 영양을 미치지 않으면서, JPEG 이미지의 읽기, 쓰기 상의 성능과 메모리 향상이 되었습니다.

    이 변경에 관련하는 버그 리포트: 4827358 ,4867874 , 및 4868479

    Posted by 아름프로
    1.4에서 추가된 java.nio 패키지에서의 Charset 지원현황입니다.

    기본 인코딩 세트 (lib/rt.jar 에 포함되어 있다)



    summary="Basic encoding set">















































    java.nio API 용의 정 준명


    java.io 및 java.lang API 용의 정 준명


    설명


    ISO-8859-1


    ISO8859_1


    ISO 8859-1, 라틴 알파벳 No. 1


    ISO-8859-2


    ISO8859_2


    라틴 알파벳 No. 2


    ISO-8859-4


    ISO8859_4


    라틴 알파벳 No. 4


    ISO-8859-5


    ISO8859_5


    라틴/키릴 문자 알파벳


    ISO-8859-7


    ISO8859_7


    라틴/그리스 문자 알파벳


    ISO-8859-9


    ISO8859_9


    라틴 알파벳 No. 5


    ISO-8859-13


    ISO8859_13


    라틴 알파벳 No. 7


    ISO-8859-15


    ISO8859_5


    라틴 알파벳 No. 9


    KOI8-R


    KOI8_R


    KOI8-R, 러시아어


    US-ASCII


    ASCII


    American Standard Code for Information Interchange


    UTF-8


    UTF8


    8 비트 UCS Transformation Format


    UTF-16


    UTF-16


    16 비트 UCS Transformation Format, 옵션의 바이트순서 마크에 의해 식별되는 바이트순서


    UTF-16BE


    UnicodeBigUnmarked


    16 비트 Unicode Transformation Format, 빅 endian 바이트순서


    UTF-16LE


    UnicodeLittleUnmarked


    16 비트 Unicode Transformation Format, little endian 바이트순서


    windows-1250


    Cp1250


    Windows 동구


    windows-1251


    Cp1251


    Windows 키릴 문자


    windows-1252


    Cp1252


    Windows 라틴 문자-1


    windows-1253


    Cp1253


    Windows 그리스 문자


    windows-1254


    Cp1254


    Windows 터키어


    windows-1257


    Cp1257


    Windows 발트제어


    이용할 수 없다


    UnicodeBig


    16 비트 Unicode Transformation Format, 빅 endian 바이트순서, 바이트순서 마크 첨부


    이용할 수 없다


    UnicodeLittle


    16 비트 Unicode Transformation Format, little endian 바이트순서, 바이트순서 마크 첨부

     



    확장 인코딩 세트 (lib/charsets.jar 에 포함되어 있다)



    summary="extended encoding set">





























































































































































































































































    java.nio API 용의 정 준명


    java.io 및 java.lang API 용의 정 준명


    설명


    Big5


    Big5


    Big5, 중국어 (번체자)


    Big5-HKSCS


    Big5_HKSCS


    Big5 (홍콩의 확장 첨부), 중국어 (번체자, 2001 개정을 짜넣어)


    EUC-JP


    EUC_JP


    JISX 0201, 0208, 0212, EUC 인코딩, 일본어


    EUC-KR


    EUC_KR


    KS C 5601, EUC 인코딩, 한국어


    GB18030


    GB18030


    중국어 (중공에서 정식으로 쓰는 약자체?), 중화 인민 공화국 표준


    GB2312


    EUC_CN


    GB2312, EUC 인코딩, 중국어 (중공에서 정식으로 쓰는 약자체?)


    GBK


    GBK


    GBK, 중국어 (중공에서 정식으로 쓰는 약자체?)


    IBM-Thai


    Cp838


    IBM 타이 확장 SBCS


    IBM00858


    Cp858


    Cp850 의 확장으로 유로 문자를 포함한다


    IBM01140


    Cp1140


    Cp037 의 확장으로 유로 문자를 포함한다


    IBM01141


    Cp1141


    Cp273 의 확장으로 유로 문자를 포함한다


    IBM01142


    Cp1142


    Cp277 의 확장으로 유로 문자를 포함한다


    IBM01143


    Cp1143


    Cp278 의 확장으로 유로 문자를 포함한다


    IBM01144


    Cp1144


    Cp280 의 확장으로 유로 문자를 포함한다


    IBM01145


    Cp1145


    Cp284 의 확장으로 유로 문자를 포함한다


    IBM01146


    Cp1146


    Cp285 의 확장으로 유로 문자를 포함한다


    IBM01147


    Cp1147


    Cp297 의 확장으로 유로 문자를 포함한다


    IBM01148


    Cp1148


    Cp500 의 확장으로 유로 문자를 포함한다


    IBM01149


    Cp1149


    Cp871 의 확장으로 유로 문자를 포함한다


    IBM037


    Cp037


    미국, 캐나다 (2 개국어, 프랑스어), 네델란드, 포르투갈, 브라질, 오스트레일리아


    IBM1026


    Cp1026


    IBM 라틴 문자-5, 터키


    IBM1047


    Cp1047


    라틴 문자-1 (EBCDIC 호스트용)


    IBM273


    Cp273


    IBM 오스트리아, 독일


    IBM277


    Cp277


    IBM 덴마크, 노르웨이


    IBM278


    Cp278


    IBM 핀란드, 스웨덴


    IBM280


    Cp280


    IBM 이탈리아


    IBM284


    Cp284


    IBM 카타로니아어/스페인, 스페인어권라틴 아메리카


    IBM285


    Cp285


    IBM 영국, 아일랜드


    IBM297


    Cp297


    IBM 프랑스


    IBM420


    Cp420


    IBM 아라비아어


    IBM424


    Cp424


    IBM 헤브라이어


    IBM437


    Cp437


    MS-DOS 미국, 오스트레일리아, 뉴질랜드, 남아프리카


    IBM500


    Cp500


    EBCDIC 500V1


    IBM775


    Cp775


    PC 발트제어


    IBM850


    Cp850


    MS-DOS 라틴 문자-1


    IBM852


    Cp852


    MS-DOS 라틴 문자-2


    IBM855


    Cp855


    IBM 키릴 문자


    IBM857


    Cp857


    IBM 터키어


    IBM860


    Cp860


    MS-DOS 포르투갈어


    IBM861


    Cp861


    MS-DOS 아이슬랜드어


    IBM862


    Cp862


    PC 헤브라이어


    IBM863


    Cp863


    MS-DOS 캐나다계 프랑스어


    IBM864


    Cp864


    PC 아라비아어


    IBM865


    Cp865


    MS-DOS 북유럽


    IBM866


    Cp866


    MS-DOS 러시아어


    IBM868


    Cp868


    MS-DOS 파키스탄


    IBM869


    Cp869


    IBM 근대 희랍어


    IBM870


    Cp870


    IBM 다언어 라틴 문자-2


    IBM871


    Cp871


    IBM 아이슬랜드


    IBM918


    Cp918


    IBM 파키스탄 (우르두어)


    ISO-2022-CN


    ISO2022CN


    ISO 2022 CN 형식의 GB2312 및 CNS11643, 중공에서 정식으로 쓰는 약자체? 및 번체자 중국어 (Unicode 에의 변환만)


    ISO-2022-JP


    ISO2022JP


    ISO 2022 형식의 JIS X 0201, 0208, 일본어


    ISO-2022-KR


    ISO2022KR


    ISO 2022 KR, 한국어


    ISO-8859-3


    ISO8859_3


    라틴 알파벳 No. 3


    ISO-8859-6


    ISO8859_6


    라틴/아라비아어 알파벳


    ISO-8859-8


    ISO8859_8


    라틴/헤브라이어 알파벳


    Shift_JIS


    SJIS


    Shift-JIS, 일본어


    TIS-620


    TIS620


    TIS620, 타이


    windows-1255


    Cp1255


    Windows 헤브라이어


    windows-1256


    Cp1256


    Windows 아라비아어


    windows-1258


    Cp1258


    Windows 베트남어


    windows-31j


    MS932


    Windows 일본어


    x-Big5_Solaris


    Big5_Solaris


    Big5 (Solaris zh_TW.BIG5 로케일용의 7 개의 추가 Hanzi 표의 문자 매핑 첨부)


    x-euc-jp-linux


    EUC_JP_LINUX


    JISX 0201, 0208, EUC 인코딩, 일본어


    x-EUC-TW


    EUC_TW


    CNS11643 (Plane 1-7, 15), EUC 인코딩, 중국어 (번체자)


    x-eucJP-Open


    EUC_JP_Solaris


    JISX 0201, 0208, 0212, EUC 인코딩, 일본어


    x-IBM1006


    Cp1006


    IBM AIX 파키스탄 (우르두어)


    x-IBM1025


    Cp1025


    IBM 다언어 키릴 문자: 불가리아, 보스니아, 헤르체고비나, 마케도니아 ( 구유고슬라비아 마케도니아 공화국)


    x-IBM1046


    Cp1046


    IBM 아라비아어 - Windows


    x-IBM1097


    Cp1097


    IBM 이란 (현대 페르시아어)/페르시아어


    x-IBM1098


    Cp1098


    IBM 이란 (현대 페르시아어)/페르시아어 (PC)


    x-IBM1112


    Cp1112


    IBM 라트비아, 리투아니아


    x-IBM1122


    Cp1122


    IBM 에스토니아


    x-IBM1123


    Cp1123


    IBM 우크라이나


    x-IBM1124


    Cp1124


    IBM AIX 우크라이나


    x-IBM1381


    Cp1381


    IBM OS/2, DOS 중국 (중화 인민 공화국)


    x-IBM1383


    Cp1383


    IBM AIX 중국 (중화 인민 공화국)


    x-IBM33722


    Cp33722


    IBM-eucJP - 일본어 (5050 의 슈퍼 세트)


    x-IBM737


    Cp737


    PC 그리스 문자


    x-IBM856


    Cp856


    IBM 헤브라이어


    x-IBM874


    Cp874


    IBM 타이


    x-IBM875


    Cp875


    IBM 희랍어


    x-IBM921


    Cp921


    IBM 라트비아, 리투아니아 (AIX, DOS)


    x-IBM922


    Cp922


    IBM 에스토니아 (AIX, DOS)


    x-IBM930


    Cp930


    UDC 4370 문자를 포함한 일본어 카타카나 한자, 5026 의 슈퍼 세트


    x-IBM933


    Cp933


    UDC 1880 문자를 포함한 한국어, 5029 의 슈퍼 세트


    x-IBM935


    Cp935


    UDC 1880 문자를 포함한 중공에서 정식으로 쓰는 약자체? 중국어 호스트, 5031 의 슈퍼 세트


    x-IBM937


    Cp937


    UDC 6204 문자를 포함한 번체자 중국어 호스트, 5033 의 슈퍼 세트


    x-IBM939


    Cp939


    UDC 4370 문자를 포함한 일본어 라틴 문자 한자, 5035 의 슈퍼 세트


    x-IBM942


    Cp942


    IBM OS/2 일본어, Cp932 의 슈퍼 세트


    x-IBM942C


    Cp942C


    Cp942 의 확장


    x-IBM943


    Cp943


    IBM OS/2 일본어, Cp932 및 Shift-JIS 의 슈퍼 세트


    x-IBM943C


    Cp943C


    Cp943 의 확장


    x-IBM948


    Cp948


    OS/2 중국어 (대만), 938 의 슈퍼 세트


    x-IBM949


    Cp949


    PC 한국어


    x-IBM949C


    Cp949C


    Cp949 의 확장


    x-IBM950


    Cp950


    PC 중국어 (홍콩, 대만)


    x-IBM964


    Cp964


    AIX 중국어 (대만)


    x-IBM970


    Cp970


    AIX 한국어


    x-ISCII91


    ISCII91


    인도어파 ISCII91 인코딩


    x-ISO2022-CN-CNS


    ISO2022_CN_CNS


    ISO 2022 CN 형식의 CNS11643, 번체자 중국어 (Unicode 로부터의 변환만)


    x-ISO2022-CN-GB


    ISO2022_CN_GB


    ISO 2022 CN 형식의 GB2312, 중공에서 정식으로 쓰는 약자체? 중국어 (Unicode 로부터의 변환만)


    x-iso-8859-11


    x-iso-8859-11


    라틴/타이어 알파벳


    x-JISAutoDetect


    JISAutoDetect


    Shift-JIS, EUC-JP, ISO 2022 JP 의 검출 및 변환 (Unicode 에의 변환만)


    x-Johab


    x-Johab


    한국어, Johab 캐릭터 세트


    x-MacArabic


    MacArabic


    Macintosh 아라비아어


    x-MacCentralEurope


    MacCentralEurope


    Macintosh 라틴 문자-2


    x-MacCroatian


    MacCroatian


    Macintosh 크로아티아어


    x-MacCyrillic


    MacCyrillic


    Macintosh 키릴 문자


    x-MacDingbat


    MacDingbat


    Macintosh Dingbat


    x-MacGreek


    MacGreek


    Macintosh 희랍어


    x-MacHebrew


    MacHebrew


    Macintosh 헤브라이어


    x-MacIceland


    MacIceland


    Macintosh 아이슬랜드어


    x-MacRoman


    MacRoman


    Macintosh Roman


    x-MacRomania


    MacRomania


    Macintosh 루마니아


    x-MacSymbol


    MacSymbol


    Macintosh 심볼


    x-MacThai


    MacThai


    Macintosh 타이


    x-MacTurkish


    MacTurkish


    Macintosh 터키어


    x-MacUkraine


    MacUkraine


    Macintosh 우크라이나


    x-MS950-HKSCS


    MS950_HKSCS


    Windows 번체자 중국어 (홍콩의 확장 첨부)


    x-mswin-936


    MS936


    Windows 중공에서 정식으로 쓰는 약자체? 중국어


    x-PCK


    PCK


    Solaris 판의 Shift_JIS


    x-windows-874


    MS874


    Windows 타이어


    x-windows-949


    MS949


    Windows 한국어


    x-windows-950


    MS950


    Windows 번체자 중국어

    Posted by 아름프로
    1.5 Tiger에 새롭게 포함된 녀석입니다.

    이녀석은
    비동기 방식으로 StringBuffer보다 더 빠른 속도를 제공해줍니다.

    내용으로는 크게
    append 메소드와 insert 메소드가 있는데..

    append 는 주어진 문장이나 단어에 제일 끝에 추가가 됩니다.
    insert는 주어진 문자이나 단어의 중간의 원하는 곳에 추가를 합니다.

    예)

    z가 「start」를 포함한 string builder object 라면..
    z.append("le")  :  결과는 "startlet"
    z.insert(4, "le") : 결과는 "starlet"
    가 됩니다.

    더 자세한 사항은 API를 참조하세요.
    Posted by 아름프로











    Design Better Software with the Inversion of Control Pattern




    The Inversion of Control pattern facilitates reuse, loose coupling, and easy testing of software components. Learn how to use it in your software design.

    he Inversion of Control (IoC) pattern, also known as Dependency Injection, has recently become popular in the J2EE community. Several open source projects, including Spring, PicoContainer, and HiveMind, use the IoC pattern to develop lightweight J2EE Containers.


    IoC is not a new concept, however. It has been around for several years now. Using object-oriented design principles and features such as interface, inheritance, and polymorphism, the IoC pattern enables better software design that facilitates reuse, loose coupling, and easy testing of software components. This article discusses IoC and demonstrates how to use this pattern in your software design without having to implement any of the open source frameworks.


    IoC Design Pattern

    Assume Class A has a relationship with Class B: it wants to use the services of Class B. The usual way to establish this relationship is to instantiate Class B inside Class A. Though this approach works, it creates tight coupling between the classes. You can't easily change Class B without modifying Class A. To eliminate the coupling, you can have a Configurator inject the instance of Class B (Object "b") to the instance of Class A (Object "a"). If you want to change the implementation of Class B later on, you simply change the Configurator object. So, the control of how Object "a" gets the reference of Object "b" is inverted. Object "a" is not responsible for getting the reference to Object "b". Instead, the Configurator is responsible for it. This is the basis for the IoC design pattern.





    Figure 1. Object "a" Directly Creates Object "b"


    To demonstrate the benefits of the Configurator object in this case, the following examples show a simple design without IoC and one with IoC (click here to download the sample code for this article).


    Listing 1 and Figure 1 are simple examples in which Class A uses Class B:


    public class A{
    private B b;

    public A(){
    b=new B();
    }

    Listing 1. Class A Directly Refers Class B


    Listing 1 assumes the following design decisions:


    1. Class A needs a reference to Class B.

    2. Class B is a concrete class that has a default constructor.

    3. Class A owns the instance of class B.

    4. No other class can access the instance of Class B.






    Figure 2. Object "a" First Creates Object "c" and Then Object "b" by Passing Object "c"


    If any one of the above design decisions change, then the code in Listing 1 must be modified. For example, if Class B changed to have a non-default constructor, which takes Class C (see Figure 2), then Listing 1 would change to Listing 2.


    public class A{
    private B b;

    public A(){
    C c=new C();
    b=new B(c);
    }

    Listing 2. Class A Directly Refers Class B and Class C


    Once again, Listing 2 assumes certain design decisions. Now Object "a" owns both Object "b" and Object "c". If Class B or Class C changes at all, then Class A needs to change as well. In essence, a simple design of a simple class with implicit design assumptions becomes a maintenance nightmare in the future. Consider how difficult making changes would be if you had this scenario in a typical application with several classes.


    Alternatively, if you use a framework that uses the IoC pattern, the responsibility of creating Object "b" moves from Object "a" to the IoC framework, which creates and injects Object "b" into Object "a". This insulates Class A from the changes in Class B. Before Object "a" is used, it needs the reference to Object "b". The IoC framework will inject Object "b" into Object "a".





    Figure 3. IoC Framework Creates Object "b" and Sets It to Object "a"


    Listing 3 shows Class A from the previous listings modified to use the IoC pattern.


    public class A{
    private B b;

    public A(){
    }

    public setB(B b){
    this.b=b;
    }

    }

    Listing 3. Class A Gets the Reference to Class B via setB


    Listing 3 assumes the following design decisions:


    1. A needs a reference to B, and it doesn't need to know how B is instantiated.

    2. B can be an interface, an abstract class, or a concrete class.

    3. Before the instance of Class A is used, it needs a reference to the instance of Class B.



    From the above design decisions, you can see that there is no tight coupling between Class A and Class B. Both can be changed independently without affecting each other. Of course, if there is any change in the public methods of Class B, Class A needs to change as well. But how Object "b" is created and managed is not decided in the implementation of Object "a". Instead, the IoC framework uses the setB() method in Object "a" to inject Object "b" (see Figure 3).



















    IoC Frameworks

    Several open source IoC frameworks like Spring, PicoContainer, and HiveMind support the IoC pattern. While the general IoC principle is simple, each of these frameworks supports different implementations and offers different benefits. The IoC pattern can be implemented in three ways: setter based, constructor based, and interface based. This section briefly discusses each of them. For more in-depth details, refer to the frameworks' home pages.


    Setter-Based IoC

    This type of IoC uses a setter method to inject the referenced object into a referring object. This is the most common type of IoC, and both Spring and PicoContainer implement it. Setter-based IoC is good for objects that take optional parameters and objects that need to change their properties many times during their lifecycles. Its main disadvantage is that you need to expose all the properties of an object to the outside world when using a setter method. This breaks one of the key OO principles: data encapsulation and information hiding.


    Constructor-Based IoC

    This type of IoC uses a constructor to set the reference of the object. Its main advantage is that only the creator knows about the referenced object. Once the object is created, the client code that uses the object is unaware of the referenced object. This approach may not work in all types of applications, however. For example, if you use an external API that needs a default constructor, then you need to go with a setter-based IoC. A constructor-based IoC is the main type of implementation in Spring.


    Interface-Based IoC

    In this type of IoC, objects implement a specific interface from the IoC framework, which the IoC framework will use to properly inject the objects. One of the main advantages of this type is that it doesn't need an external configuration file to configure the object references. Since you need to use the IoC framework's marker interface, the IoC framework knows how to glue the objects together. It is similar to using EJB. Any EJB container knows how to instantiate your objects and hook them with itself. The main disadvantage of this approach is that the marker interface ties your application to a specific IoC framework. Apache Avalon is based on this approach but this project has been closed.


    An Example of IoC

    If you are starting a new project, you can choose any of the open source IoC frameworks based on your needs. If you want to use the IoC pattern in your existing project then you need to write your own classes that support IoC. Though the open source frameworks offer off-the-shelf components and may provide many more features than your own implementation, you can still develop a set of classes that support the IoC pattern. This section demonstrates how.


    Say you want to write a CustomerService object to process customer data. Assume customer data is stored in two different places: a relational database and an XML file. You also want to have CustomerService create Customer objects by reading data from either the database or the XML file. Now, say you want to accomplish this without changing the source code of CustomerService to switch between the database and XML file.


    DataSource

    First, design an interface (see Listing 4) and define common methods, which you will use to retrieve and store customer data. Both XMLDataSource and JDBCDataSource classes implement this interface.


    public interface DataSource {
    public Object retrieveObject();
    public void setDataSourceName(String name);
    public String getDataSourceName();
    public void storeObject(Object object);
    }

    Listing 4. Common Interface to Customer Data


    XMLDataSource

    Listing 5 shows a class that implements DataSource and provides an implementation that uses an XML file to retrieve and store customer data.


    public class XMLDataSource implements DataSource {
    private String name;

    /**
    * Default Constructor
    */
    public XMLDataSource() {
    super();
    }

    /**
    * Retrieve Customer data from XML Source and construct
    * Customer object
    */
    public Object retrieveObject() {
    //get XML data, parse it and then construct
    //Customer object
    return new Customer("XML",10);
    }

    /**
    * Set the DataSource name
    */
    public void setDataSourceName(String name) {
    this.name=name;
    }

    /**
    * Return DataSource name
    */
    public String getDataSourceName() {
    return name;
    }

    /**
    * Store Customer into XML file
    */
    public void storeObject(Object object) {
    //Retrieve customer data and store it in
    //XML file

    }

    }

    Listing 5. Class to Retrieve Customer Data from XML File


    RelationalDataSource

    The class in Listing 6 also implements DataSource and provides the same implementation as XMLDataSource with only one difference: this class retrieves and stores customer data using a relational database.


    public class RelationalDataSource implements DataSource {
    private String name;

    /**
    * Default constructor
    */
    public RelationalDataSource() {
    super();
    }

    /**
    * Using the DataSource retrieve data for Customer and build a
    * Customer object to return it to the caller
    */
    public Object retrieveObject() {
    //get data for Customer object from DB and create a
    //Customer object
    return new Customer("Relational",10);
    }

    /**
    * Set the DataSource name
    */
    public void setDataSourceName(String name) {
    this.name=name;
    }

    /**
    * Return the name of the DataSource
    */
    public String getDataSourceName() {
    return name;
    }

    /**
    * Store Customer into relational DB
    */
    public void storeObject(Object object) {
    //store the customer data into Relational DB

    }

    }


    Listing 6. Class to Retrieve Customer Data from Relational DB


















    Customer

    The simple class in Listing 7 holds customer data, which either the XMLDataSource or RelationalDatSource object will construct.

    public class Customer {
    private String name;
    private int age;

    /**
    * Default Constructor
    */
    public Customer(String name, int age) {
    this.name=name;
    this.age=age;

    }

    /**
    * @return Returns the age.
    */
    public int getAge() {
    return age;
    }
    /**
    * @param age The age to set.
    */
    public void setAge(int age) {
    this.age = age;
    }
    /**
    * @return Returns the name.
    */
    public String getName() {
    return name;
    }
    /**
    * @param name The name to set.
    */
    public void setName(String name) {
    this.name = name;
    }
    }

    Listing 7. Class That holds Customer Data


    CustomerService

    This class in Listing 8 has a reference to DataSource, which it uses to retrieve and store Customer objects. The actual implementation of DataSource will be either XMLDataSource or RelationalDataSource, which will be injected into the CustomerService object. The constructor of the CustomerService object accepts a concrete implementation of the DataSource object and uses it to retrieve and store customer data.


    public class CustomerService {
    private DataSource dataSource;
    private Customer customer;

    /**
    * Constructor in which DataSource object is injected. Based on the
    * ioc.properties this object can either refer to RelationlDataSource or
    * XMLDataSource
    */
    public CustomerService(DataSource dataSource) {
    super();
    this.dataSource=dataSource;
    customer=(Customer)dataSource.retrieveObject();
    }

    /**
    * Modify Customer name
    * @param name
    */
    public void updateCustomerName(String name) {
    customer.setName(name);
    }

    /**
    * Modify Customer age
    * @param age
    */
    public void updateCustomerAge(int age){
    customer.setAge(age);
    }

    /**
    *
    * @return Customer name
    */
    public String getCustomerName(){
    return customer.getName();
    }

    /**
    *
    * @return Customer age
    */
    public int getCustomerAge(){
    return customer.getAge();
    }

    }

    Listing 8. CustomerService Class That Gets DataSource Reference via ServiceConfigurator





    Figure 4. IoC Using ServiceConfigurator


    ServiceConfigurator

    The ServiceConfigurator in Listing 9 is a main class that uses the IoC pattern to inject the concrete implementation of DataSource into the CustomerService object. It reads the configuration parameters (see Figure 4) from the ioc.properties file and decides to create either an XMLDataSource or a RelationalDataSource object. The DataSource object is created using its default Constructor, and the name of the DataSource is set using its setter method. The created DataSource object is injected into CustomerService using its constructor, which accepts a DataSource reference. The created CustomerService object is stored in the ServiceConfigurator registry so that it will be returned when a subsequent request comes for the CustomerService object.


    Figure 4 shows the inner workings of ServiceConfigurator, and Figure 5 shows the UML diagram for all of the classes explained previously. You can switch between XMLDataSource and RelationalDataSource just by editing the ioc.properties file.


    public class ServiceConfigurator {
    public static final String IoC_CONFIG_FILE="ioc.properties";
    private Properties props;
    private HashMap serviceRegistery;
    private static ServiceConfigurator thisObject;

    /**
    * This method first checks if there is a ServiceConfigurator instance
    * exist, if not creates a one, stored it and returns it
    * @return
    */
    public static ServiceConfigurator createServiceConfigurator(){
    if(thisObject==null){
    thisObject=new ServiceConfigurator();
    }
    return thisObject;
    }

    /**
    * Private Constructor makes this class singleton
    */
    private ServiceConfigurator() {
    props = new Properties();
    serviceRegistery=new HashMap();
    loadIoCConfig();
    createServices();
    }

    /**
    * Load the IoC_CONFIG_FILE properties file
    *
    */
    public void loadIoCConfig(){
    InputStream is = this.getClass().getClassLoader().getResourceAsStream(IoC_CONFIG_FILE);
    try {
    props.load(is);
    is.close();
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    /**
    * Create the CustomerService by getting the DataSource name from the
    * properties file. The CustomerService object is stored in the
    * serviceRegistery so that it will be retrieved when requested.
    * During the construction of CustomerService the DataSource object
    * is injected into it. So the CustomerService can access the DataSource
    * to retrieve the Customer.
    *
    */
    public void createServices(){
    String dataSourceName=props.getProperty("dataSource");
    DataSource dataSource=null;
    if(dataSourceName!=null){
    try {
    dataSource=(DataSource)Class.forName(dataSourceName).newInstance();
    } catch (InstantiationException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
    }
    //name of the DataSource is retrieved from the properties file
    dataSource.setDataSourceName(props.getProperty("name"));
    CustomerService customerService=new CustomerService(dataSource);
    serviceRegistery.put(CustomerService.class,customerService);
    }
    /**
    * Stored Service is retrieved from serviceRegistery for the given
    * Class object
    *
    * @param classObj
    * @return
    */
    public Object getService(Class classObj){
    return serviceRegistery.get(classObj);
    }

    }


    Listing 9. ServiceConfigurator that Uses IoC to Inject DataSource into CustomerService





    Figure 5. ServiceConfigurator UML Class Diagram



    The ServiceConfigurator is a simple class that supports the IoC pattern. You can modify it to add more features such as simultaneously supporting multiple DataSource objects, dynamically injecting the DataSource into CustomerService, and life cycle management.


    CustomerServiceTester

    The class in Listing 10 is a JUnit test that uses CustomerService. It uses ServiceConfigurator to retrieve the CustomerService object, which is used to change the Customer name and age.


    public class CustomerServiceTester extends TestCase{
    private ServiceConfigurator serviceConfig;

    /**
    *Default Constructor
    */
    public CustomerServiceTester() {
    super();
    }

    /**
    * Create ServiceConfigurator
    */
    public void setUp() throws Exception{
    super.setUp();
    serviceConfig=ServiceConfigurator.createServiceConfigurator();
    }
    /**
    * Test CustomerService and check for Customer
    * @throws Exception
    */
    public void testCustomerService() throws Exception{
    CustomerService custService=(CustomerService)serviceConfig.getService(CustomerService.class);
    assertNotNull(custService);
    custService.updateCustomerAge(30);
    custService.updateCustomerName("Mani");
    assertEquals(30,custService.getCustomerAge());
    assertEquals("Mani",custService.getCustomerName());


    }


    Listing 10. JUnit Test that Uses CustomerService


















    Service Configurator vs. Service Locator

    The implementation of ServiceConfigurator in Listing 9 may lead you to think that there is no difference between the ServiceConfigurator class that uses IoC and one that uses the Service Locator pattern. In fact, you can modify the CustomerService in Listing 8 to use a Service Locator, which will give the CustomerService class either an XMLDataSource or a RelationalDataSource object, based on the Service Locator's internal implementation. By changing the internal implementation of Service Locator, you can switch the DataSource from which CustomerService gets its Customer. In this context, both Service Locator and ServiceConfigurator provide the same functionality to CustomerService. The main difference is how CustomerService gets the DataSource reference. In Service Locator, CustomerService must get the DataSource reference directly from Service Locator, while in ServiceConfigurator, CustomerService gets the DataSource indirectly through ServiceConfigurator.


    So, what is the advantage of using Service Locator instead of ServiceConfigurator? ServiceConfigurator frees CustomerService from either acquiring or instantiating the DataSource directly. This makes CustomerService easy to test: simply inject the appropriate DataSource into it. More over, as explained previously in Listing 1 and Listing 2, because you do not make any assumptions about how CustomerService will get the DataSource reference, you can reuse the CustomerService object in different applications. This is the main advantage of using Service Configurator over Service Locator.


    What to Inject?

    In Figure 5, you see that CustomerService has a relationship with both the DataSource and the Customer classes. Yet this discussion has been about how to inject DataSource into CustomerService. Why not inject Customer into CustomerService? In fact, it is perfectly legitimate to make the ServiceConfigurator inject the Customer object into CustomerService by creating an interface for Customer and referencing it in CustomerService. It all depends on your application requirements and how you want to design the CustomerService class. The previous example made DataSource responsible for creating and storing the Customer object and created a tight coupling between DataSource and Customer. In the future, any change in the Customer class will require changes to all of the implementations of DataSource. However, the design decision was made with the assumption that the public methods of Customer would not undergo any changes, and if any changes occurred in the internals of Customer, then they will not affect the DataSource.


    The only anticipated change is how the Customer data is retrieved and stored. Currently, the Customer data is stored in a relational database or in an XML file. Perhaps in the future, it might be stored in an object database or retrieved via a Web service. In either scenario, you can have new classes retrieve and store Customer data. So, based on these assumptions, the example injects only the DataSource into CustomerService, which is used to retrieve and store Customer data.


    Add on to Simple Example

    This article discussed the IoC pattern and briefly discussed open source frameworks that use it. It also discussed how you could incorporate the IoC pattern in your existing applications using the ServiceConfigurator example. Though simple, the ServiceConfigurator class supports the IoC pattern and provides all of its benefits. You can modify the ServiceConfigurator to add more features as you need for your applications.



    Mani Malarvannan is a consultant at Cybelink Systems. He has been developing Web-based applications using object-oriented methodologies and software patterns for several years.






    Posted by 아름프로


    Working with Object-Orientation in UML


                                    Date: Jun 25, 2004 By Joseph Schmuller.
                                    Sample Chapter is provided courtesy of Sams.
                                            
    Are you trying to learn about object-oriented programming (or at least how to make the most of it) while you're also coming up to speed with UML? In this sample book chapter, you'll firm up your knowledge of object-orientation as you learn more about the UML. Learn about attributes, operations, visualization, and classes.

    What You'll Learn in This Hour:



        
    • How to model a class

    •   
    • How to show a class's features, responsibilities, and constraints

    •   
    • How to discover classes


    Now it's time to put the UML together with the object-oriented concepts
      you learned in the last hour. In this hour, you'll firm up your knowledge
      of object-orientation as you learn more about the UML.


    Visualizing a Class


    As I pointed out in the first hour, a rectangle is the icon that represents
      a class in the UML. From Hours 1, "Introducing the UML," and 2, "Understanding
      Object-Orientation," recall that the name of the class is, by convention,
      a word with an initial uppercase letter. It appears near the top of the rectangle.
      If your class has a two-word name, join the two words together and capitalize
      the first letter of the second word (as in WashingMachine in Figure
      3.1
    ).


    Another UML construct, the package, can play a role in the name of a class.
      As I pointed out in Hour 1, a package is the UML's way of organizing a
      diagram's elements. As you might recall, the UML represents a package as
      a tabbed folder. The package's name is a text string (see Figure
      3.2
    ).


    Figure 3.1Figure
      3.1
    The UML class icon.



    Figure 3.2Figure
      3.2
    A UML package.



    If the WashingMachine class is part of a package called Household,
      you can give it the name Household::WashingMachine. The double colons
      separate the package name on the left from the classname on the right. This
      type of classname is called a pathname (see Figure
      3.3
    ).


    Figure 3.3Figure
      3.3
    A class with a pathname.




    Attributes


    An attribute is a property of a class. It describes a range of values that
      the property may hold in objects (that is, in instances) of that class.
      A class may have zero or more attributes. By convention, a one-word attribute
      name is written in lowercase letters. If the name consists of more than one
      word, the words are joined and each word other than the first word begins with
      an uppercase letter. The list of attribute names begins below a line separating
      them from the classname, as Figure 3.4
      shows.


    Figure 3.4Figure
      3.4
    A class and its attributes.



    Every object of the class has a specific value for every attribute. Figure
      3.5
    presents an example. Note that an object's name begins with a lowercase
      letter, precedes a colon that precedes the classname, and the whole name is
      underlined.



    Naming Objects . . . or Not


    The name myWasher:WashingMachine is a
    named instance. It's also possible to have an anonymous instance like
    :WashingMachine.



      

    Figure 3.5Figure
      3.5
    An object has a specific value for every one of its class's attributes.



      

    The UML gives you the option of indicating additional information for attributes.
        In the icon for the class, you can specify a type for each attribute's
        value. Possible types include string, floating-point number, integer, and
        Boolean (and other enumerated types). To indicate a type, use a colon to separate
        the attribute name from the type. You can also indicate a default value for
        an attribute. Figure 3.6 shows these
        ways of specifying attributes.


      

    Figure 3.6Figure
      3.6
    An attribute can show its type as well as a default value.




    Naming Values


    An enumerated type is a data type defined by a list of named values. Boolean,
    for instance, is an enumerated type because it consists of the values
    "true" and "false." You can define your own enumerated types
    like State, which consists of the values "solid," "liquid,"
    and "gas."




    Operations


    An operation is something a class can do, and hence it is something that you
      (or another class) can ask the class to do. Like an attribute name, an operation's
      name is all in lowercase if it's one word. If the name consists of more
      than one word, join the words and begin all words after the first with an uppercase
      letter. The list of operations begins below a line that separates the operations
      from the attributes, as in Figure 3.7.


    Figure 3.7Figure
      3.7
    The list of a class's operations appears below a line that separates
      them from the class's attributes.



    Just as you can indicate additional information for attributes, you can
    indicate additional information for operations. In the parentheses that follow
    an operation name, you can show the parameter that the operation works on, along
    with that parameter's type. One kind of operation, the function, returns a
    value after it finishes doing its work. For a function, you can show the value
    it returns and that value's type.


    These pieces of information about an operation are called the operation's
      signature. Figure 3.8 shows a couple
      of ways to represent the signature. The first two operations show the type of
      the parameter. The third and fourth show the type of the return value.


    Figure 3.8Figure
      3.8
    Signatures for operations.




    Attributes, Operations, and Visualization


    We've been dealing with classes in isolation thus far and showing all
      the attributes and operations of a class. In practice, however, you'll
      show more than one class at a time. When you do that, it's typically not
      useful to always display all the attributes and operations. To do so might make
      the diagram way too busy. Instead, you can just show the classname and leave
      either the attribute area or the operation area empty (or leave them both empty),
      as Figure 3.9 shows.


    Figure 3.9Figure
      3.9
    In practice, you don't always show all of a class's attributes
      and operations.



    Sometimes it might be helpful to show some (but not all) of the attributes
      or operations. To indicate that you've only shown some of them, you follow
      the list of the ones you've shown with three dots ". . . ". This
      is called an ellipsis, and omitting some or all of the attributes or operations
      is called eliding a class. Figure 3.10
      shows the use of an ellipsis.


    Figure 3.10Figure
      3.10
    An ellipsis indicates that the displayed attributes or operations aren't
      the whole set.



    If you have a long list of attributes or operations, you can use a keyword
      to organize in ways that will make the list comprehensible. As I mentioned in
      Hour 1, a keyword is enclosed inside two pairs of small angle brackets called
      guillemets. For an attribute list, you can use a keyword as a heading
      for a subset of the attributes, as in Figure
      3.11
    .


    Figure 3.11Figure
      3.11
    You can use a keyword to organize a list of attributes or operations.












    Responsibilities and Constraints


    The class icon enables you to specify still another type of information about
    a class. In an area below the operations list, you can show the class's
    responsibility. The responsibility is a description of what the class has to
    do—that is, what its attributes and operations are trying to accomplish. A
    washing machine, for example, has the responsibility of taking dirty clothes as
    input and producing clean clothes as output.


    In the icon, you indicate responsibilities in an area below the area that contains
      the operations (see Figure 3.12).


    Figure 3.12Figure
      3.12
    In a class icon, you can write the class's responsibilities in
      an area below the operations list area.



    The idea here is to include enough information to describe a class in an
    unambiguous way. Indicating the class's responsibilities is an informal way
    to eliminate ambiguity.


    A slightly more formal way is to add a constraint, a free-form text enclosed
      in curly brackets. The bracketed text specifies one or more rules the class
      follows. For example, suppose in the WashingMachine class you wanted
      to specify that the capacity of a washer can be only 16, 18, or 20 pounds (and
      thus "constrain" the WashingMachine class's capacity
      attribute). You would write {capacity = 16 or 18 or 20 lbs} near the
      WashingMachine class icon. Figure
      3.13
    shows how to do it.


    Figure 3.13Figure
      3.13
    The rule in curly brackets constrains the capacity attribute to be
      one of three possible values.




    More on Constraints



    The UML works with still another—and much more formal—way of adding
    constraints that make definitions more explicit. It's an entire language
    called Object Constraint Language (OCL). An advanced and sometimes useful tool,
    OCL has its own set of rules, terms, and operators. The Web site of the Object
    Management Group
    (http://www.omg.org) provides
    documentation on OCL.




    Attached Notes


    Above and beyond attributes, operations, responsibilities, and constraints,
    you can add still more information to a class in the form of notes attached to
    the class.


    You'll usually add a note to an attribute or operation. Figure
      3.14
    shows a note referring to a government standard that tells where to
      find out how serial numbers are generated for objects in the WashingMachine
      class.


    Figure 3.14Figure
      3.14
    An attached note provides further information about the class.



    Bear in mind that a note can contain a graphic as well as text.



    Classes—What They Do and  How to Find Them


    Classes are the vocabulary and terminology of an area of knowledge. As you
    talk with clients, analyze their area of knowledge, and design computer systems
    that solve problems in that area, you learn the terminology and model the terms
    as classes in the UML.


    In your conversations with clients, be alert to the nouns they use to
    describe the entities in their business. Those nouns will become the classes in
    your model. Be alert also to the verbs that you hear because these will
    constitute the operations in those classes. The attributes will emerge as nouns
    related to the class nouns. After you have a core list of classes, question the
    clients as to what each class is supposed to do within the business. Their
    answers will tell you the class responsibilities.


    Suppose you're an analyst building a model of the game of basketball,
    and you're interviewing a coach in order to understand the game. The
    conversation might go something like this:


    Analyst: "Coach, what's basketball all about?"


    Coach: "The goal of the game is to shoot the ball through the
    basket and score more points than your opponent. Each team consists of five
    players: two guards, two forwards, and a center. Each team advances the ball
    toward the basket with the objective of ultimately shooting the ball through the
    basket."


    Analyst: "How does it advance the ball?"


    Coach: "By dribbling and passing. But the team has to take a shot
    at the basket before the shot clock expires."


    Analyst: "Shot clock?"


    Coach: "Yes. That's 24 seconds in the pros, 30 seconds in
    international play, and 35 seconds in college to take a shot after a team gets
    possession of the ball."


    Analyst: "How does the scoring work?"


    Coach: "Each basket counts two points, unless the shot is from
    behind the three-point line. In that case, it's three points. A free throw
    counts one point. A free throw, by the way, is the penalty a team pays for
    committing a foul. If a player fouls an opponent, play stops and the opponent
    gets to shoot at the basket from the free-throw line."


    Analyst: "Tell me a little more about what each player
    does."


    Coach: "The guards generally do most of the dribbling and
    passing. They're typically shorter than the forwards, and the forwards are
    usually shorter than the center. All the players are supposed to be able to
    dribble, pass, shoot, and rebound. The forwards do most of the rebounding and
    intermediate-range shooting, while the center stays near the basket and shoots
    from close range."


    Analyst: "How about the dimensions of the court? And by the way,
    how long does a game last?"


    Coach: "In international play, the court is 28 meters long by 15
    meters wide. The basket is 10 feet off the ground. In the pros, a game lasts 48
    minutes, divided into four 12-minute quarters. In college and international
    play, it's 40 minutes divided into two 20-minute halves. A game clock keeps
    track of the time remaining."


    This could go on and on, but let's stop and take stock of where we are.
    Here are the nouns you've uncovered: ball, basket, team, players, guards,
    forwards, center, shot, shot clock, three-point line, free throw, foul,
    free-throw line, court, and game clock.


    Here are the verbs: shoot, advance, dribble, pass, foul, and rebound. You
    also have some additional information about some of the nouns—like the
    relative heights of the players at each position, the dimensions of the court,
    the total amount of time on a shot clock, and the duration of a game.


    Finally, your own commonsense knowledge could come into play as you generate
    a few attributes on your own. You know, for example, that the ball has
    attributes like volume and diameter.


    Using this information, you can create a diagram like the one in Figure
      3.15
    . It shows the classes, and provides some attributes, operations, and
      constraints. The diagram also shows responsibilities. You could use this diagram
      as a foundation for further conversations with the coach, to uncover more information.


    Figure 3.15Figure
      3.15
    An initial class diagram for modeling the game of basketball.




    Summary


    The rectangle is the UML icon for representing a class. The name, attributes,
    operations, and responsibilities of the class fit into areas within the
    rectangle. You can use a stereotype to organize lists of attributes and
    operations. You elide a class by showing just a subset of its attributes and
    operations. This makes a class diagram less busy.


    You can show an attribute's type and an initial value, and you can show
    the values an operation works on and their types as well. For an operation, this
    additional information is called the signature.


    To reduce the ambiguity in a class description, you can add constraints. The
    UML also allows you to say more about a class by attaching notes to the
    rectangle that represents it.


    Classes represent the vocabulary of an area of knowledge. Conversations with
    a client or an expert in that area reveal nouns that can become classes in a
    model and verbs that can become operations. You can use a class diagram as a way
    of stimulating the client to talk more about his or her area and reveal
    additional knowledge.



    Q&A



        

    1.     

      You mention using "commonsense" knowledge to round out
            the class diagram for basketball. That's all well and good, but what
            happens when I have to analyze an area that's new to me—where
            common sense won't necessarily help?


        



        

    1.     

      Typically, you'll be thrust into an area that's new for you.
            Before you meet with a client or with an expert in the field, try to become
            a "subexpert." Prepare for the meeting by reading as much related
            documentation as possible. Ask your interviewee for some papers or manuals
            they might have written. When you've finished reading, you'll
            know some of the fundamentals and you'll be able to ask pointed questions.


        



        

    1.     

      At what point will I want to show an operation's signature?


        



        

    1.     

      Probably after the analysis phase of a development effort, as you get
            into design. The signature is a piece of information that programmers will
            find helpful.


        



        

    1.     

      I've been working for my company for a long time and have in-depth
            knowledge of its business. Do I still have to create a class model of the
            business area the company works in?


        



        

    1.     

      It's a good idea to do that. When you have to model your knowledge,
            you may be surprised at what you don't know.


        



    Workshop


    To review what you've learned about object-orientation, try your hand at
    these quiz questions. The answers appear in Appendix A, "Quiz
    Answers."


    Quiz



    1. How do you represent a class in the UML?


    2. What information can you show on a class icon?


    3. What is a constraint?


    4. Why would you attach a note to a class icon?



    Exercises



        

    1.     

      Here's a brief (and incomplete) description of hockey:


        

    2.   

      A hockey team consists of a center, a goalie, two wings, and two defensemen.
          Each player has a stick, which he uses to advance a puck on the ice. The objective
          is to use the stick to shoot the puck into a goal. Hockey is played on a rink
          with maximum dimensions of 100 feet wide by 200 feet long. The center's
          job is to pass the puck to the wings, who are typically the better shooters
          on the team. The defensemen try to stop the opposing players from getting
          into position to shoot the puck into the goal. The goalie is the last line
          of defense, blocking opposition shots. Each time he stops the puck from getting
          into the goal, he's credited with a "save." Each goal is worth
          one point. A game lasts 60 minutes, divided into three periods of 20 minutes
          each.


        

      Use this information to come up with a diagram like the one in Figure
          3.15
      . If you know more about hockey than I've put in the description,
          add that information to your diagram.


        

    3.     

      If you know more about basketball than I've put in Figure
            3.15
      , add information to that diagram.


        

    4.   

    5.     

      Go back to the conversation between the analyst and the basketball coach.
            Take a look at the coach's responses and find at least three areas
            where you could pursue additional lines of questioning. For example, at
            one point the coach mentions a "three-point line." Further questioning
            would reveal the specifics of that term.


        

    6.   

    7.     

      Here's a preview of what's next: If you had to draw some connections
            among the classes in Figure 3.15, what
            might they look like?


        





    Posted by 아름프로




    UML Sequence Diagrams



    Date: Mar 26, 2004 By Martin Fowler.
    Sample Chapter is provided courtesy of Addison Wesley Professional.
    Typically, in UML, a sequence diagram captures the behavior of a single scenario. The diagram shows a number of example objects and the messages that are passed between these objects within the use case. This book chapter explains what they're all about, when to use them—plus how to create and delete participants, use loops, conditionals, and the best way to treat synchronous and asynchronous calls.



    Interaction diagrams describe how groups of objects collaborate in some behavior. The UML defines several forms of interaction diagram, of which
    the most common is the sequence diagram.



    Typically, a sequence diagram captures the behavior of a single scenario. The diagram shows a number of example objects and
    the messages that are passed between these objects within the use case.



    To begin the discussion, I’ll consider a simple scenario. We have an order and are going to invoke a command on it to calculate
    its price. To do that, the order needs to look at all the line items on the order and determine their prices, which are based
    on the pricing rules of the order line’s products. Having done that for all the line items, the order then needs to compute
    an overall discount, which is based on rules tied to the customer.



    Figure 4.1 is a sequence diagram that shows one implementation of that scenario. Sequence diagrams show the interaction by showing each
    participant with a lifeline that runs vertically down the page and the ordering of messages by reading down the page.



    04fig01.gifFigure 4.1. A sequence diagram for centralized control



    One of the nice things about a sequence diagram is that I almost don’t have to explain the notation. You can see that an instance
    of order sends getQuantity and getProduct messages to the order line. You can also see how we show the order invoking a method on itself and how that method sends
    getDiscountInfo to an instance of customer.



    The diagram, however, doesn’t show everything very well. The sequence of messages getQuantity, getProduct, getPricingDetails, and calculateBasePrice needs to be done for each order line on the order, while calculateDiscounts is invoked just once. You can’t tell that from this diagram, although I’ll introduce some more notation to handle that later.



    Most of the time, you can think of the participants in an interaction diagram as objects, as indeed they were in UML 1. But
    in UML 2, their roles are much more complicated, and to explain it all fully is beyond this book. So I use the term participants, a word that isn’t used formally in the UML spec. In UML 1, participants were objects and so their names were underlined,
    but in UML 2, they should be shown without the underline, as I’ve done here.



    In these diagrams, I’ve named the participants using the style anOrder. This works well most of the time. A fuller syntax is name : Class, where both the name and the class are optional, but you must keep the colon if you use the class. (Figure 4.4, shown on page 58, uses this style.)



    Each lifeline has an activation bar that shows when the participant is active in the interaction. This corresponds to one
    of the participant’s methods being on the stack. Activation bars are optional in UML, but I find them extremely valuable in
    clarifying the behavior. My one exception is when exploring a design during a design session, because they are awkward to
    draw on whiteboards.



    Naming often is useful to correlate participants on the diagram. The call getProduct is shown returning aProduct, which is the same name, and therefore the same participant, as the aProduct that the getPricingDetails call is sent to. Note that I’ve used a return arrow for only this call; I did that to show the correspondance. Some people
    use returns for all calls, but I prefer to use them only where they add information; otherwise, they simply clutter things.
    Even in this case, you could probably leave the return out without confusing your reader.



    The first message doesn’t have a participant that sent it, as it comes from an undetermined source. It’s called a found message.



    For another approach to this scenario, take a look at Figure 4.2. The basic problem is still the same, but the way in which the participants collaborate to implement it is very different.
    The Order asks each Order Line to calculate its own Price. The Order Line itself further hands off the calculation to the
    Product; note how we show the passing of a parameter. Similarly, to calculate the discount, the Order invokes a method on
    the Customer. Because it needs information from the Order to do this, the Customer makes a reentrant call (getBaseValue) to the Order to get the data.



    04fig02.gifFigure 4.2. A sequence diagram for distributed control



    The first thing to note about these two diagrams is how clearly the sequence diagram indicates the differences in how the
    participants interact. This is the great strength of interaction diagrams. They aren’t good at showing details of algorithms,
    such as loops and conditional behavior, but they make the calls between participants crystal clear and give a really good
    picture about which participants are doing which processing.



    The second thing to note is the clear difference in styles between the two interactions. Figure 4.1 is centralized control, with one participant pretty much doing all the processing and other participants there to supply data. Figure 4.2 uses distributed control, in which the processing is split among many participants, each one doing a little bit of the algorithm.



    Both styles have their strengths and weaknesses. Most people, particularly those new to objects, are more used to centralized
    control. In many ways, it’s simpler, as all the processing is in one place; with distributed control, in contrast, you have
    the sensation of chasing around the objects, trying to find the program.



    Despite this, object bigots like me strongly prefer distributed control. One of the main goals of good design is to localize
    the effects of change. Data and behavior that accesses that data often change together. So putting the data and the behavior
    that uses it together in one place is the first rule of object-oriented design.



    Furthermore, by distributing control, you create more opportunities for using polymorphism rather than using conditional logic.
    If the algorithms for product pricing are different for different types of product, the distributed control mechanism allows
    us to use subclasses of product to handle these variations.



    In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for
    overriding and variation. This style is very confusing to people used to long procedures; indeed, this change is the heart
    of the paradigm shift of object orientation. It’s something that’s very difficult to teach. It seems that the only way to really understand it
    is to work in an OO environment with strongly distributed control for a while. Many people then say that they get a sudden
    "aha" when the style makes sense. At this point, their brains have been rewired, and they start thinking that decentralized
    control is actually easier.




    Creating and Deleting Participants



    Sequence diagrams show some extra notation for creating and deleting participants (Figure 4.3). To create a participant, you draw the message arrow directly into the participant box. A message name is optional here
    if you are using a constructor, but I usually mark it with "new" in any case. If the participant immediately does something
    once it’s created, such as the query command, you start an activation right after the participant box.



    04fig03.gifFigure 4.3. Creation and deletion of participants



    Deletion of a participant is indicated by big X. A message arrow going into the X indicates one participant explicitly deleting
    another; an X at the end of a lifeline shows a participant deleting itself.



    In a garbage-collected environment, you don’t delete objects directly, but it’s still worth using the X to indicate when an
    object is no longer needed and is ready to be collected. It’s also appropriate for close operations, indicating that the object
    isn’t usable any more.




    A common issue with sequence diagrams is how to show looping and conditional behavior. The first thing to point out is that
    this isn’t what sequence diagrams are good at. If you want to show control structures like this, you are better off with an
    activity diagram or indeed with code itself. Treat sequence diagrams as a visualization of how objects interact rather than
    as a way of modeling control logic.



    That said, here’s the notation to use. Both loops and conditionals use interaction frames, which are ways of marking off a piece of a sequence diagram. Figure 4.4 shows a simple algorithm based on the following pseudocode:



    04fig04.gifFigure 4.4. Interaction frames



    procedure dispatch
    foreach (lineitem)
    if (product.value > $10K)
    careful.dispatch
    else
    regular.dispatch
    end if
    end for
    if (needsConfirmation) messenger.confirm
    end procedure

    In general, frames consist of some region of a sequence diagram that is divided into one or more fragments. Each frame has
    an operator and each fragment may have a guard. (Table 4.1 lists common operators for interaction frames.) To show a loop, you use the loop operand with a single fragment and put the basis of the iteration in the guard. For conditional logic, you can use an alt operator and put a condition on each fragment. Only the fragment whose guard is true will execute. If you have only one region,
    there is an opt operator.



    Interaction frames are new in UML 2. As a result, you may see diagrams prepared before UML 2 and that use a different approach;
    also, some people don’t like the frames and prefer some of the older conventions. Figure 4.5 shows some of these unofficial tweaks.



    04fig05.gifFigure 4.5. Older conventions for control logic



    UML 1 used iteration markers and guards. An iteration marker is a * added to the message name. You can add some text in square brackets to indicate the basis of the iteration. Guards are a conditional expression placed in square brackets and indicate that the message is sent only if the guard is true. While
    these notations have been dropped from sequence diagrams in UML 2, they are still legal on communication diagrams.



    Table 4.1. Common Operators for Interaction Frames












































    Operator



    Meaning



    alt



    Alternative multiple fragments; only the one whose condition is true will execute (Figure 4.4).



    opt



    Optional; the fragment executes only if the supplied condition is true. Equivalent to an alt with only one trace (Figure 4.4).



    par



    Parallel; each fragment is run in parallel.



    loop



    Loop; the fragment may execute multiple times, and the guard indicates the basis of iteration (Figure 4.4).



    region



    Critical region; the fragment can have only one thread executing it at once.



    neg



    Negative; the fragment shows an invalid interaction.



    ref



    Reference; refers to an interaction defined on another diagram. The frame is drawn to cover the lifelines involved in the
    interaction. You can define parameters and a return value.



    sd



    Sequence diagram; used to surround an entire sequence diagram, if you wish.




    Although iteration markers and guards can help, they do have weaknesses. The guards can’t indicate that a set of guards are
    mutually exclusive, such as the two on Figure 4.5. Both notations work only with a single message send and don’t work well when several messages coming out of a single activation
    are within the same loop or conditional block.



    To get around this last problem, an unofficial convention that’s become popular is to use a pseudomessage, with the loop condition or the guard on a variation of the self-call notation. In Figure 4.5, I’ve shown this without a message arrow; some people include a message arrow, but leaving it out helps reinforce that this
    isn’t a real call. Some also like to gray shade the pseudomessage’s activation bar. If you have alterative behavior, you can
    show that with an alternative marker between the activations.



    Although I find activations very helpful, they don’t add much in the case of the dispatch method, whereby you send a message and nothing else happens within the receiver’s activation. A common convention that I’ve
    shown on Figure 4.5 is to drop the activation for those simple calls.



    The UML standard has no graphic device to show passing data; instead, it’s shown by parameters in the message name and return
    arrows. Data tadpoles have been around in many methods to indicate the movement of data, and many people still like to use them with the UML.



    All in all, although various schemes can add notation for conditional logic to sequence diagrams, I don’t find that they work
    any better than code or at least pseudocode. In particular, I find the interaction frames very heavy, obscuring the main point
    of the diagram, so I prefer pseudomessages.




    If you’re exceptionally alert, you’ll have noticed that the arrowheads in the last couple of diagrams are different from the
    arrowheads earlier on. That minor difference is quite important in UML 2. In UML 2, filled arrowheads show a synchronous message,
    while stick arrowheads show an asynchronous message.



    If a caller sends a synchronous message, it must wait until the message is done, such as invoking a subroutine. If a caller sends an asynchronous message, it can continue processing and doesn’t have to wait for a response. You see asynchronous calls in multithreaded applications
    and in message-oriented middleware. Asynchrony gives better responsiveness and reduces the temporal coupling but is harder
    to debug.



    The arrowhead difference is very subtle; indeed, rather too subtle. It’s also a backward-incompatible change introduced in
    UML 1.4, before then an asynchronous message was shown with the half-stick arrowhead, as in Figure 4.5.



    I think that this arrowhead distinction is too subtle. If you want to highlight asynchronous messages, I would recommend using
    the obsolete half-stick arrowhead, which draws the eye much better to an important distinction. If you’re reading a sequence
    diagram, beware of making assumptions about synchrony from the arrowheads unless you’re sure that the author is intentionally
    making the distinction.




    You should use sequence diagrams when you want to look at the behavior of several objects within a single use case. Sequence
    diagrams are good at showing collaborations among the objects; they are not so good at precise definition of the behavior.



    If you want to look at the behavior of a single object across many use cases, use a state diagram (see Chapter 10). If you want to look at behavior across many use cases or many threads, consider an activity diagram (see Chapter 11).



    If you want to explore multiple alternative interactions quickly, you may be better off with CRC cards, as that avoids a lot of drawing and erasing. It’s often handy to have a CRC card session to explore design alternatives and then use sequence diagrams to capture any interactions that you want to refer
    to later.



    Other useful forms of interaction diagrams are communication diagrams, for showing connections; and timing diagrams, for showing
    timing constraints.





    CRC Cards



    One of the most valuable techniques in coming up with a good OO design is to explore object interactions, because it focuses
    on behavior rather than data. CRC (Class-Responsibility-Collaboration) diagrams, invented by Ward Cunningham in the late 1980s, have stood the test of time
    as a highly effective way to do this (Figure 4.6). Although they aren’t part of the UML, they are a very popular technique among skilled object designers.



    04fig06.gifFigure 4.6. A sample CRC card



    To use CRC cards, you and your colleagues gather around a table. Take various scenarios and act them out with the cards, picking them
    up in the air when they are active and moving them to suggest how they send messages to each other and pass them around. This
    technique is almost impossible to describe in a book yet is easily demonstrated; the best way to learn it is to have someone
    who has done it show it to you.



    An important part of CRC thinking is identifying responsibilities. A responsibility is a short sentence that summarizes something that an object should do: an action the object performs, some knowledge the
    object maintains, or some important decisions the object makes. The idea is that you should be able to take any class and
    summarize it with a handful of responsibilities. Doing that can help you think more clearly about the design of your classes.



    The second C refers to collaborators: the other classes that this class needs to work with. This gives you some idea of the links between classes—still at a high
    level.



    One of the chief benefits of CRC cards is that they encourage animated discussion among the developers. When you are working through a use case to see how
    classes will implement it, the interaction diagrams in this chapter can be slow to draw. Usually, you need to consider alternatives;
    with diagrams, the alternatives can take too long to draw and rub out. With CRC cards, you model the interaction by picking up the cards and moving them around. This allows you to quickly consider alternatives.



    As you do this, you form ideas about responsibilities and write them on the cards. Thinking about responsibilities is important,
    because it gets you away from the notion of classes as dumb data holders and eases the team members toward understanding the
    higher-level behavior of each class. A responsibility may correspond to an operation, to an attribute, or, more likely, to
    an undetermined clump of attributes and operations.



    A common mistake I see people make is generating long lists of low-level responsibilities. But doing so misses the point.
    The responsibilities should easily fit on one card. Ask yourself whether the class should be split or whether the responsibilities
    would be better stated by rolling them up into higher-level statements.



    Many people stress the importance of role playing, whereby each person on the team plays the role of one or more classes.
    I’ve never seen Ward Cunningham do that, and I find that role playing gets in the way.



    Books have been written on CRC, but I’ve found that they never really get to the heart of the technique. The original paper on CRC, written with Kent Beck, is [Beck and Cunningham]. To learn more about both CRC cards and responsibilities in design, take a look at [Wirfs-Brock].





    Posted by 아름프로


    Date: Sep 24, 2004 By Robert Martin.
    Sample Chapter is provided courtesy of Prentice Hall PTR.
    UML class diagrams allow us to denote the static contents of ? and the relationships between ? classes. In this chapter, Robert Martin explains the basics of UML class diagrams in a practical way.

    UML class diagrams allow us to denote the static contents of ? and the relationships between ? classes. In a class diagram
    we can show the member variables, and member functions of a class. We can also show whether one class inherits from another,
    or whether it holds a reference to another. In short, we can depict all the source code dependencies between classes.



    This can be valuable. It can be much easier to evaluate the dependency structure of a system from a diagram than from source
    code. Diagrams make certain dependency structures visible. We can see dependency cycles, and determine how best to break them. We can see when abstract classes depend upon concrete classes, and
    determine a strategy for rerouting such dependencies.



    The Basics



    Classes



    Figure 3-1 shows the simplest form of class diagram. The class named Dialer is represented as a simple rectangle. This diagram represents nothing more than the code shown to its right.



    03fig01.gifFigure
    3.1
    Class icon.




    This is the most common way you will represent a class. The classes on most diagrams don't need any more than their name to
    make clear what is going on.



    A class icon can be subdivided into compartments. The top compartment is for the name of the class, the second is for the
    variables of the class, and the third is for the methods of the class. Figure 3-2 shows these compartments and how they translate into code.



    03fig02.gifFigure
    3.2
    Class icon compartments with corresponding code.




    Notice the character in front of the variables and functions in the class icon. A dash (?) denotes private, a hash (#) denotes protected, and a plus (+) denotes public.



    The type of a variable, or a function argument is shown after the colon following the variable or argument name. Similarly,
    the return value of a function is shown after the colon following the function.



    This kind of detail is sometimes useful, but should not be used very often. UML diagrams are not the place to declare variables
    and functions. Such declarations are better done in source code. Use these adornments only when they are essential to the
    purpose of the diagram.



    Association



    Associations between classes most often represent instance variables that hold references to other objects. For example, in
    Figure 3-3 we see an association between Phone and Button. The direction of the arrow tells us that Phone holds a reference to Button. The name near the arrowhead is the name of the instance variable. The number near the arrowhead tells us how many references
    are held.



    03fig03.gif
    Figure 3.3
    Association.




    In Figure 3-3 we saw that 15 Button objects were connected to the Phone object. In Figure 3-4, we see what happens when there is no limit. A Phonebook is connected to many PhoneNumber objects. The star means many. In Java this is most commonly implemented with a Vector, a List, or some other container type.



    03fig04.gifFigure 3.4




    You may have noticed that I avoided using the word "has". I could have said: "A Phonebook has many PhoneNumbers." This was intentional. The common OO verbs HASA and ISA have lead to a number of unfortunate misunderstandings. We'll explore
    some of them later in Chapter 6. For now, don't expect me to use the common terms. Rather, I'll use terms that are descriptive of what actually happens in
    software, such as: "is connected to."



    Inheritance



    You have to be very careful with your arrowheads in UML. Figure 3-5 shows why. The little arrowhead pointing at Employee denotes inheritance1. If you draw your arrowheads carelessly, it may be hard to tell whether you mean inheritance or association. To make it clearer,
    I often make inheritance relationships vertical and associations horizontal.



    03fig05.gif
    Figure 3.5
    Inheritance.




    In UML all arrowheads point in the direction of source code dependency. Since it is the SalariedEmployee class that mentions the name of Employee, the arrowhead points at Employee. So, in UML, inheritance arrows point at the base class.



    UML has a special notation for the kind of inheritance used between a Java class and a Java interface. It is shown, in Figure 3-6, as a dashed inheritance arrow2. In the diagrams to come, you'll probably catch me forgetting to dash the arrows that point to interfaces. I suggest you
    forget to dash the arrows that you draw on white boards too. Life's too short to be dashing arrows.



    03fig06.gifFigure
    3.6
    Realizes relationship.




    Figure 3-7 shows another way to convey the same information. Interfaces can be drawn as little lollipops on the classes that implement
    them. We often see this kind of notation in COM designs.



    03fig07.gifFigure
    3.7
    Lollipop interface Indicator.


    An Example Class Diagram



    Figure 3-8 shows a simple class diagram of part of an ATM system. This diagram is interesting both for what it shows, and for what it
    does not show. Note that I have taken pains to mark all the interfaces. I consider it crucial to make sure my readers know
    what classes I intend to be interfaces and which I intend to be implemented. For example, the diagram immediately tells you
    that WithdrawalTransaction talks to a CashDispenser interface. Clearly some class in the system will have to implement the CashDispenser, but in this diagram we don't care which class it is.



    03fig08.gifFigure
    3.8
    ATM class diagram.




    Note that I have not been particularly thorough in documenting the methods of the various UI interfaces. Certainly WithdrawalUI will need more than just the two methods shown there. What about promptForAccount or informCashDispenserEmpty? Putting those methods in the diagram would just clutter it. By providing a representative batch of methods, I've given the
    reader the idea. That's all that's really necessary.



    Again note the convention of horizontal association and vertical inheritance. This really helps to differentiate these vastly
    different kinds of relationships. Without a convention like this it can be hard to tease the meaning out of the tangle.



    Notice how I've separated the diagram into three distinct zones. The transactions and their actions are on the left, the various
    UI interfaces are all on the right, and the UI implementation is on the bottom. Note also that the connections between the
    grouping are minimal and regular. In one case it is three associations, all pointing the same way. In the other case it is
    three inheritance relationships all merged into a single line. The grouping, and the way they are connected help the reader
    to see the diagram in coherent pieces.



    You should be able to see the code as you look at the diagram. Is Listing 3-1 close to what you expected for the implementation of UI?



    Example 3-1. UI.java




    public class UI implements
    WithdrawalUI, DepositUI, TransferUI
    {
    private Screen itsScreen;
    private MessageLog itsMessageLog;

    public void displayMessage(String message)
    {
    itsMessageLog.logMessage(message);
    itsScreen.displayMessage(message);
    }
    }

    The Details



    There are a vast number of details and adornments that can be added to UML class diagrams. Most of the time these details
    and adornments should not be added. But there are times when they can be helpful.



    Class stereotypes



    Class stereotypes appear between guillemet3 characters, usually above the name of the class. We have seen them before. The ≪interface≫ denotation in Figure 3-8 is a class stereotype. ≪interface≫ is one of two standard stereotypes that can be used by Java programmers. The other is
    ≪utility≫.



    ≪interface≫



    All the methods of classes marked with this stereotype are abstract. None of the methods can be implemented. Moreover, ≪interface≫
    classes can have no instance variables. The only variables they can have are static variables. This corresponds exactly to
    Java interfaces. See Figure 3-9.



    03fig09.gifFigure
    3.9
    ≪interface≫ class stereotype.




    I draw interfaces so often that spelling the whole stereotype out at the white board can be pretty inconvenient. So I often
    use the shorthand in the lower part of Figure 3-9 to make the drawing easier. It's not standard UML, but it's much more convenient.



    ≪utility≫



    All the methods and variables of a ≪utility≫ class are static. Booch4 used to call these class utilities. See Figure 3-10.



    03fig10.gifFigure
    3.10
    ≪utility≫ class stereotype.




    You can make your own stereotypes if you like. I often use stereotypes like ≪persistent≫, ≪C-API≫, ≪struct≫, or ≪function≫.
    You just have to make sure that the people who are reading your diagrams know what your stereotype means.



    Abstract classes



    In UML there are two ways to denote that a class or a method is abstract. You can write the name in italics, or you can use
    the {abstract} property. Both options are shown in Figure 3-11.



    03fig11.gifFigure
    3.11
    Abstract classes.




    It's a little difficult to write italics at a white board, and the {abstract} property is wordy. So at the white board, if
    I need to denote a class or method as abstract, I use the convention shown in Figure 3-12. Again, this isn't standard UML, but at the white board it is a lot more convenient.5



    03fig12.gifFigure
    3.12
    Unofficial denotation of abstract classes.




    Properties



    Properties, like {abstract} can be added to any class. They represent extra information that's not usually part of a class.
    You can create your own properties at any time.



    Properties are written in a comma separated list of name?value pairs, like this:



    {author=Martin, date=20020429, file=shape.java, private}

    The properties in the preceding example are not part of UML. The {abstract} property is the only defined property of UML that
    Java programmers would find useful.



    If a property does not have a value, it is assumed to take the boolean value true. Thus, {abstract} and {abstract = true} are synonyms.



    Properties are written below and to the right of the name of the class, as shown in Figure 3-13.



    03fig13.gif Figure 3.13 Properties.



    Other than the {abstract} property, I don't know when you'd this useful. Personally, in the many years that I've been writing
    UML diagrams, I've never had occasion to use class properties for anything.



    Aggregation



    Aggregation is a special form of association that connotes a "whole/part" relationship. Figure 3-14 shows how it is drawn and implemented. Notice that the implementation shown in Figure 3-14 is indistinguishable from association. That's a hint.



    03fig14.gif
    Figure 3.14
    Aggregation.




    Unfortunately, UML does not provide a strong definition for this relationship. This leads to confusion because various programmers
    and analysts adopt their own pet definitions for the relationship. For that reason I don't use the relationship at all, and
    I recommend that you avoid it as well. In fact, this relationship has been dropped from UML 2.0.



    The one hard rule that UML gives us regarding aggregations is simply this: A whole cannot be its own part. Therefore instances cannot form cycles of aggregations. A single object cannot be an aggregate of itself, two objects cannot be aggregates of
    each other, three objects cannot form a ring of aggregation, and so on. See Figure 3-15



    03fig15.gifFigure
    3.15
    Illegal cycles of aggregation between instances.




    I don't find this to be a particularly useful definition. How often am I concerned about making sure that instances form a
    directed acyclic graph? Not very often. Therefore I find this relationship useless in the kinds of diagrams I draw.



    Composition



    Composition is a special form of aggregation, as shown in Figure 3-16. Again, notice that the implementation is indistinguishable from association. However, this time the reason is not due to
    a lack of definition; this time it's because the relationship does not have a lot of use in a Java program. C++ programmers,
    on the other hand, find a lot of use for it.



    03fig16.gif Figure 3.16 Composition.



    The same rule applies to composition that applied to aggregation. There can be no cycles of instances. An owner cannot be
    its own ward. However, UML provides quite a bit more definition.





    • An instance of a ward cannot be owned simultaneously by two owners. The
      object diagram in Figure
      3-17
      is illegal. Note, however, that the corresponding class diagram
      is not illegal. An owner can transfer ownership of a ward to another owner.


      03fig17.gifFigure
      3.17
      Illegal composition.





    • The owner is responsible for the lifetime of the ward. If the owner is
      destroyed, the ward must be destroyed with it. If the owner is copied, the
      ward must be copied with it.





    In Java destruction happens behind the scenes by the garbage collector, so there is seldom a need to manage the lifetime of
    an object. Deep copies are not unheard of, but the need to show deep copy semantics on a diagram is rare. So, though I have
    used composition relationships to describe some Java programs, such use is infrequent.



    Figure 3-18 shows how composition is used to denote deep copy. We have a class named Address that holds many Strings. Each string holds one line of the address. Clearly, when you make a copy of the Address, you want the copy to change independently of the original. Thus, we need to make a deep copy. The composition relationship
    between the Address and the Strings indicates that copies need to be deep.6



    03fig18.gifFigure
    3.18
    Deep copy is implied by composition.




    Multiplicity



    Objects can hold arrays or vectors of other objects, or they can hold many of the same kind of objects in separate instance
    variables. In UML this can be shown by placing a multiplicity expression on the far end of the association. Multiplicity expressions can be simple numbers, ranges, or a combination of
    both. For example, Figure 3-19 shows a BinaryTreeNode, using a multiplicity of 2.



    03fig19.gifFigure
    3.19
    Simple multiplicity.




    Here are the allowable forms:
































    ? Digit.



    The exact number of elements.



    ? * or 0..*



    Zero to many.



    ? 0..1



    Zero or one. In Java this is often implemented with a reference that can be null.



    ? 1..*



    One to many.



    ? 3..5



    Three to five.



    ? 0, 2..5, 9..*



    Silly, but legal.




    Association stereotypes



    Associations can be labeled with stereotypes that change their meaning. Figure 3-20 shows the ones that I use most often.



    03fig20.gifFigure
    3.20
    Association stereotypes.




    The ≪create≫ stereotype indicates that the target of the association is created by the source. The implication is that the source creates
    the target and then passes it around to other parts of the system. In the example I've shown a typical factory.



    The ≪local≫ stereotype is used when the source class creates an instance of the target and holds it in a local variable. The implication
    is that the created instance does not survive the member function that creates it. Thus, it is not held by any instance variable
    nor passed around the system in any way.



    The ≪parameter≫ stereotype shows that the source class gains access to the target instance though the parameter of one of its member functions.
    Again, the implication is that the source forgets all about this object once the member function returns. The target is not
    saved in an instance variable.



    Using dashed dependency arrows, as the diagram shows, is a common and convenient idiom for denoting parameters. I usually
    prefer it to using the ≪parameter≫ stereotype.



    The ≪delegate≫ stereotype is used when the source class forwards a member function invocation to the target. There are a number of design
    patterns where this technique is applied, such as PROXY, DECORATOR, and COMPOSITE7 . Since I use these patterns a lot, I find the notation helpful.



    Inner classes



    Inner (nested) classes are represented in UML with an association adorned with a crossed circle, as shown in Figure 3-21.



    03fig21.gifFigure
    3.21
    Inner class.




    Anonymous inner classes



    One of Java's more interesting features is anonymous inner classes. While UML does not have an official stance on these, I
    find the notation in Figure 3-22 works well for me. It is concise and descriptive. The anonymous inner class is shown as a nested class that is given the
    ≪anonymous≫ stereotype, and is also given the name of the interface it implements.



    03fig22.gifFigure
    3.22
    Anonymous inner class.




    Association classes



    Associations with multiplicity tell us that the source is connected to many instances of the target, but the diagram doesn't
    tell us what kind of container class is used. This can be depicted by using an association class, as shown in Figure 3-23.



    03fig23.gifFigure
    3.23
    Association class.




    Association classes show how a particular association is implemented. On the diagram they appear as a normal class connected
    to the association with a dashed line. As Java programmers we interpret this to mean that the source class really contains
    a reference to the association class, which in turn contains references to the target.



    Association classes can also be used to indicate special forms of references, such as weak, soft, or phantom references. See
    Figure 3-24. On the other hand, this notation is a bit cumbersome and is probably better done with stereotypes as in Figure 3-25.



    03fig24.gifFigure
    3.24
    Association class denoting a weak reference.




    03fig25.gifFigure
    3.25
    Stereotype denoting a weak reference.




    Association qualifiers



    Association qualifiers are used when the association is implemented through some kind of key or token, instead of with a normal
    Java reference. The example in Figure 3-26 shows a LoginServlet associated with an Employee. The association is mediated by a member variable named empid, which contains the database key for the Employee.



    03fig26.gifFigure
    3.26
    Association qualifier.




    I find this notation useful in rare situations. Sometimes it's convenient to show that an object is associated to another
    through a database or dictionary key. It is important, however, that all the parties reading the diagram know how the qualifier
    is used to access the actual object. This is not something that's immediately evident from the notation.

    Conclusion



    There are lots of widgets, adornments, and whatchamajiggers in UML. There are so many that you can spend a long time becoming
    an UML language lawyer, enabling you to do what all lawyers can ? write documents nobody else can understand.



    In this chapter I have avoided most of the arcana and byzantine features of UML. Rather I have showed you the parts of UML
    that I use. I hope that along with that knowledge I have instilled within you the values of minimalism. Using too little of UML
    is almost always better than using too much.

    Notes



    [Booch1994]: Grady Booch, Object Oriented Analysis and Design with Applications. Redwood City, CA.: Benjamin Cummings, 1994.



    [Gamma1995]: Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design Patterns. Reading, Mass.: Addison-Wesley, 1995.



    Posted by 아름프로





    margin-left:22.0pt'>N-ary associations are associations that
    connect more than two classes.?Each instance
    lang=EN-US>쟯f the association lang=EN-US>쟧s an n-tuple of values from the respective classes.?There are
    several characteristics for n-ary association lang=EN-US>s, which are: (i) Multiplicity for ternary associations can be
    specified; (ii) The name lang=EN-US>쟯f the association (if any) is shown near the diamond; (iii) Role
    adornments can appear on each path lang=EN-US>쟞s with a binary association lang=EN-US>; (iv) The multiplicity lang=EN-US>쟯n a role lang=EN-US>쟲epresents the potential number of instance tuples in the
    association when the other N-1 values are fixed.?Indeed, binary association is
    a special case that it has its own notation.



    0cm;text-indent:0cm'> lang=EN-US>N-ary Association Resource Centric Interface



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image147.png">



    style='margin-left:62.35pt;border-collapse:collapse;border:none'>


























    Resource


    padding:0cm 5.4pt 0cm 5.4pt'>

    Name


    padding:0cm 5.4pt 0cm 5.4pt'>

    Description


    padding:0cm 5.4pt 0cm 5.4pt'>

    src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image077.png">


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt'>

    Association -> Class


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt'>

    To create a new Class and connect it
    with a bi-directional Association.


    padding:0cm 5.4pt 0cm 5.4pt;border:solid windowtext 1.0pt !msorm;border-top:
    none !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image082.png">


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    Aggregation -> Class


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    To create a new Class and connect it
    with an Aggregation.


    padding:0cm 5.4pt 0cm 5.4pt;border:solid windowtext 1.0pt !msorm;border-top:
    none !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image083.png">


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    Composition -> Class


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    To create a new Class and connect it
    with an Composition.


    padding:0cm 5.4pt 0cm 5.4pt'>

    src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image045.png">


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt'>

    Anchor -> Note


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt'>

    To create a Note and connect it with
    an Anchor.




    margin-left:55.0pt'>Table 5‑8 The
    resources of an N-ary Association



    0cm;text-indent:0cm'> name="_Toc24191472">Collaboration



     



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image148.png">



     



    margin-left:22.0pt'>A collaboration lang=EN-US>쟡escribes how an operation lang=EN-US>쟯r a classifier lang=EN-US>?like a use case lang=EN-US>) is realized by a set of classifiers and associations used in a
    specific way. The collaboration defines a set of roles to be played by
    instances and links, as well as a set of interactions that define the
    communication between the instances when they play those roles.



    0cm;text-indent:0cm'> lang=EN-US>Collaboration Resource Centric Interface



     



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image149.jpg">



     



    style='margin-left:62.35pt;border-collapse:collapse;border:none'>



















































    Resource


    padding:0cm 5.4pt 0cm 5.4pt'>

    Name


    padding:0cm 5.4pt 0cm 5.4pt'>

    Description


    padding:0cm 5.4pt 0cm 5.4pt;border:solid windowtext 1.0pt !msorm;border-top:
    none !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image042.png">


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    Realization -> Package


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    To create a new Package that is a
    realization
    쟯f the source Collaboration.


    padding:0cm 5.4pt 0cm 5.4pt;border:solid windowtext 1.0pt !msorm;border-top:
    none !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image058.png">


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    Realization -> Subsystem


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    To create a new Subsystem that is a
    realization
    쟯f the source Collaboration.


    padding:0cm 5.4pt 0cm 5.4pt;border:solid windowtext 1.0pt !msorm;border-top:
    none !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image068.png">


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    Realization -> Model


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    To create a new Model that is a
    realization
    쟯f the source Collaboration.


    padding:0cm 5.4pt 0cm 5.4pt'>

    src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image150.png">


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt'>

    Generalization-> Collaboration


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt'>

    To create a Collaboration that is a
    generalization
    쟯f the source Collaboration.


    padding:0cm 5.4pt 0cm 5.4pt'>

    src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image151.png">


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt'>

    Dependency -> Collaboration


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt'>

    To create a Collaboration and
    connect it with a Dependency (the source Collaboration depends on the new
    Collaboration).


    padding:0cm 5.4pt 0cm 5.4pt;border:solid windowtext 1.0pt !msorm;border-top:
    none !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image151.png">


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    Usage -> Collaboration


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    To create a Collaboration and
    connect it with a Usage Dependency (the source Collaboration depends on the
    new Collaboration).


    padding:0cm 5.4pt 0cm 5.4pt;border:solid windowtext 1.0pt !msorm;border-top:
    none !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image152.png">


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    Binding Dependency ->
    Collaboration


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    To create a Collaboration and
    connect it with a Binding Dependency (the source Collaboration depends on the
    new Collaboration).


    padding:0cm 5.4pt 0cm 5.4pt;border:solid windowtext 1.0pt !msorm;border-top:
    none !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image153.png">


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    Permission -> Collaboration


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;border-top:
    none !msorm;border-left:none !msorm;border-bottom:solid windowtext 1.0pt !msorm;
    border-right:solid windowtext 1.0pt !msorm;padding:0cm 5.4pt 0cm 5.4pt !msorm'>

    To create a Collaboration and
    connect it with a Permission Dependency (the source Collaboration depends on
    the new Collaboration).


    padding:0cm 5.4pt 0cm 5.4pt'>

    src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image045.png">


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt'>

    Anchor -> Note


    border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt'>

    To create a Note and connect it with
    an Anchor.




    margin-left:55.0pt'>Table 5‑9 The
    resources of a Collaboration



    0cm;text-indent:0cm'> name="_Toc24191475">Constraint



     



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image154.png">



     



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image155.png">



    margin-left:22.0pt'>A constraint lang=EN-US>?/span>is a semantic relationship lang=EN-US>쟞mong model lang=EN-US>쟢lements that specifies conditions and propositions that must be
    maintained as true; otherwise, the system lang=EN-US>쟡escribed by the model is invalid (with consequences that are
    outside the scope lang=EN-US>쟯f UML). Certain kinds of constraints (such as an association lang=EN-US>젗xor?constraint) are predefined in UML, others may be
    user-defined. A user-defined constraint is described in words in a given
    language, whose syntax lang=EN-US>쟞nd interpretation is a tool responsibility lang=EN-US>. A constraint represents semantic information attached to a model
    element lang=EN-US>, not just to a view lang=EN-US>쟯f it.



    0cm;text-indent:0cm'> name="_Toc24191476">Generalization



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image156.png">



    margin-left:22.0pt'>Generalization is a relationship lang=EN-US>쟟etween a general element lang=EN-US>쟞nd a more specific kind of that element. It means that the more
    specific element can be used whenever the general element appears. This relation
    is also known as specialization lang=EN-US>쟯r inheritance lang=EN-US>쟫ink lang=EN-US>.



    0cm;text-indent:0cm'> name="_Toc24191477">Usage



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image157.png">



    margin-left:22.0pt'>Usage is a dependency lang=EN-US>쟳ituation in which one element lang=EN-US>?the client) requires the presence of another element (the supplier lang=EN-US>) for its correct functioning or implementation lang=EN-US>.



    0cm;text-indent:0cm'> name="_Toc24191478">Realization



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image158.png">



    margin-left:22.0pt'>Realization is the relationship lang=EN-US>쟟etween a specialization lang=EN-US>쟞nd its implementation lang=EN-US>.?It is an indication of the inheritance lang=EN-US>쟯f behavior lang=EN-US>쟷ithout the inheritance of structure lang=EN-US>.?One classifier lang=EN-US>쟳pecifies a contract lang=EN-US>쟳uch that another classifier guarantees to carry out. Realization
    is used in two places: one is between interfaces and the classes that realize
    them, and the other is between use case lang=EN-US>s and the collaboration lang=EN-US>쟴hat realize them.



    0cm;text-indent:0cm'> name="_Toc24191479">Association



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image159.png">



    margin-left:22.0pt'>Association is represented with a line
    between classes.?Associations represent structural relationships between
    classes and can be named to facilitate model
    lang=EN-US>쟵nderstanding.?If two classes are associated you can navigate from
    an object lang=EN-US>쟯f one class to an object of the other class.



    0cm;text-indent:0cm'> name="_Toc24191481">Aggregation



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image160.png">



    margin-left:22.0pt'>Aggregation is a special kind of
    association
    lang=EN-US>쟧n which one class represents as the larger class that consists of
    a smaller class.?It has the meaning of 밾as-a?relationship lang=EN-US>.



    0cm;text-indent:0cm'> name="_Toc24191483">Composition



    margin-left:22.0pt'>Composition is a strong form of
    aggregation association
    lang=EN-US>. It has strong ownership lang=EN-US>쟞nd coincident lifetime lang=EN-US>쟯f parts by the whole lang=EN-US>. A part lang=EN-US>쟭ay belong to only one composite. Parts with non-fixed multiplicity lang=EN-US>쟭ay be created after the composite itself. But once created, they
    live and die with it (that is, they share lifetimes). Such parts can also be
    explicitly removed before the death of the composite.



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image161.png">



    0cm;text-indent:0cm'> name="_Toc24191485">Association Class



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image162.png">



    margin-left:22.0pt'>Association class is an association lang=EN-US>쟴hat is also a class, and has both association and class
    properties.?It can have attributes, operations and even other associations.
    It usually helps to further define a many-to-many relationship lang=EN-US>.



    0cm;text-indent:0cm'> name="_Toc24191486">Dependency



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image163.png">



    margin-left:22.0pt'>The dependency lang=EN-US>쟫ink lang=EN-US>쟧s a semantic relationship lang=EN-US>쟟etween the two elements. It indicates that when a change occurs in
    one element lang=EN-US>, there may be a change necessary to the other element.?A
    dependency link can include lang=EN-US>쟫abel and stereotype lang=EN-US>쟠an be set.



     



     



    0cm;text-indent:0cm'> name="_Toc24191487">Abstraction



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image164.png">



    margin-left:22.0pt'>An Abstraction Dependency is a type lang=EN-US>쟯f Dependency with stereotype lang=EN-US>잸bstraction.



    0cm;text-indent:0cm'> name="_Toc24191488">Binding



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image165.png">



    margin-left:22.0pt'>A Binding Dependency is a type lang=EN-US>쟯f Dependency with stereotype lang=EN-US>잹inding.



    0cm;text-indent:0cm'> name="_Toc24191489">Permission



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image166.png">



    margin-left:22.0pt'>A Permission Dependency is a type lang=EN-US>쟯f Dependency with stereotype lang=EN-US>쟑ermission.



    0cm;text-indent:0cm'> name="_Toc24191490">Containment



    margin-left:55.0pt'> src="http://www.visual-paradigm.com/working_with_unified_modeling_language/Working_with_Class_Diagrams_files/image167.png">



    margin-left:22.0pt'>Shows a class, package lang=EN-US>쟯r other model lang=EN-US>쟢lement lang=EN-US>쟡eclared within another model element. Such a declared class is not
    a structural part lang=EN-US>쟯f the enclosing class but merely has scope lang=EN-US>쟷ithin the namespace lang=EN-US>쟯f the enclosing class, which acts like a package lang=EN-US>쟴oward the inner class.





    Posted by 아름프로



    Guidelines, Patterns, and code for end-to-end Java applications.











    Designing Web Services with the J2EE(TM) 1.4 Platform : JAX-RPC, SOAP, and XML Technologies


    The final version of this book is now available href="http://java.sun.com/blueprints/guidelines/designing_webservices/html/">online, and for href="http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?isbn=0321205219">purchase.












    • Chapter 1 - Introduction

    • Chapter 2 - Standards and Technologies

    • Chapter 3 - Service Endpoint Design

    • Chapter 4 - Client Design

    • Chapter 5 - XML Processing

    • Chapter 6 - Enterprise Application Integration

    • Chapter 7 - Security

    • Chapter 8 - Application Architecture






    From the Back Cover

    Written by Sun Microsystems' Java™ BluePrints team, Designing Web Services with the J2EE™ 1.4 Platform is the authoritative guide to the best practices for designing and integrating enterprise-level Web services using the Java 2 Platform, Enterprise Edition (J2EE) 1.4. This book provides the guidelines, patterns, and real-world examples architects and developers need in order to shorten the learning curve and start building robust, scalable, and portable solutions.


    The authors use the Java Adventure Builder application to bring the design process to life and help illustrate the use of Java APIs for XML Processing (JAXP), Java APIs for XML-Based RPC (JAX-RPC), and other Web service and Java-XML technologies.


    Key topic coverage includes:



    • Web service requirements and design issues

    • Support for Web services provided by the J2EE 1.4 platform

    • Designing and implementing Web service end points

    • Writing efficient Web service client applications

    • Designing and developing XML-based applications

    • Integrating applications and data using Web services

    • The J2EE platform security model as it applies to Web services

    • A coherent programming model for designing and developing Web service endpoints and clients


    Designing Web Services with the J2EE™ 1.4 Platform provides the insight, advice, and detail that make it easier to create effective Web service applications using the J2EE 1.4 platform.








    Posted by 아름프로


    Developing an Enterprise Bean with EJB 3.0 Technology







    Let's look at what a developer does to create enterprise beans using EJB 3.0 technology. Note that the material in this section reflects the technology as documented in the early draft of the EJB 3.0 Specification. The specification might change over time, and so some aspects of what a developer codes to create enterprise beans might also change.



    A Stateless Session Bean











    To create a session bean using EJB 3.0 technology, a developer only needs to code a bean class, annotated with appropriate metadata annotations, and a business interface. The business interface can be generated by default. The bean class is coded as a plain old Java object (POJO).






    Let's examine what a developer needs to do to develop a stateless session bean using EJB 3.0 technology. Once again, let's develop a bean named Converter that converts currency -- from dollars to yen, and from yen to euros-- and that can be accessed remotely. This is the same stateless session bean presented in Developing an Enterprise Bean with EJB 2.1 Technology. You'll see how much easier it is to develop the bean using EJB 3.0 technology.


    To create the session bean, a developer only needs to code a bean class and annotate it with appropriate metadata annotations:



    @Stateless @Remote public class ConverterBean {

    BigDecimal yenRate = new BigDecimal("121.6000");
    BigDecimal euroRate = new BigDecimal("0.0077");

    public BigDecimal dollarToYen(BigDecimal dollars) {
    BigDecimal result = dollars.multiply(yenRate);
    return result.setScale(2,BigDecimal.ROUND_UP);
    }

    public BigDecimal yenToEuro(BigDecimal yen) {
    BigDecimal result = yen.multiply(euroRate);
    return result.setScale(2,BigDecimal.ROUND_UP);
    }
    }


    In this example, the metadata annotations are @Stateless and @Remote.
    Significantly, there's no home interface, remote interface, or deployment descriptor to code. All that's required in addition
    to the bean class is a business interface, and that can be generated by default (as is the case here).



    The bean class is coded as a plain old Java object ("POJO") rather than a class that implements an interface such as javax.ejb.SessionBean. Because the bean class doesn't implement an interface such as javax.ejb.SessionBean, a developer no longer has to implement methods such as ejbRemove, ejbActivate, or ejbPassivate in the bean class. However a developer can implement any or all of these callbacks if they are needed. If the bean class implements one of these callbacks, the EJB container calls it just as it does for EJB 2.1 technology.


    Metadata Annotation



    Metadata annotation is a new Java Language feature in Java 2 Platform Standard Edition (J2SE) 5.0. It's designed to give developers a way to annotate code at appropriate points in a program. A developer can define an annotation type, for example:



    public @interface Copyright {
    String value ();
    }


    An annotation type is defined with an @ sign preceding the interface keyword. The annotation type includes one or more elements -- in this case, value. (In annotations with a single element, the element should be named value to avoid having to specify the name when the annotation is used.) After an annotation type is defined, a developer can use it to annotate declarations in code:


    @Copyright("2004 My Corporation")
    public class Converter {
    ...


    An annotation consists of the @ sign preceding the annotation type, followed by a parenthesized list of element-value pairs. When an annotation processing tool (there's one in J2SE 5.0) encounters the annotation, it generates the code for the annotation -- here, a copyright notice that includes the string "2004 My Corporation".



    The EJB 3.0 Specification defines a variety of annotation types such as those that specify a bean's type (@Stateless, @Stateful, @MessageDriven, @Entity), whether a bean is remotely or locally accessible (@Remote, @Local), transaction attributes (@TransactionAttribute), and security and method permissions (@MethodPermissions, @Unchecked, @SecurityRoles). (There are many more annotations defined in the specification than these.) Annotations for the EJB 3.0 annotation types generate interfaces required by the class as well as references to objects in the environment.



    In many cases, defaults can be used instead of explicit metadata annotation elements. In these cases, a developer doesn't have to completely specify a metadata annotation to obtain the same result as if the annotation was fully specified. For example, by default, an entity bean (annotated by @Entity) has a default entity type of CMP, indicating that it has container-managed persistence. These defaults can make annotating enterprise beans very simple. In fact, in many cases, defaults are assumed when an annotation is not specified. In those cases, the defaults represent the most common specifications. For example, container-managed transaction demarcation (where the container, as opposed to the bean, manages the commitment or rollback of a unit of work to a database) is assumed for an enterprise bean if no annotation is specified. These defaults illustrate the "coding by exception" approach that guides EJB 3.0 technology. The intent is to simplify things for developers by forcing them to code things only where defaults are not adequate.



    Business Interface











    A business interface is a plain old Java interface (POJI).






    No component interface or home interface is required for a session bean. The one interface a session bean needs is a business interface. A business interface is a plain old Java interface ("POJI"). It does not have to extend or implement anything, and it does not throw java.rmi.Remote Exception or java.rmi.CreateException. A developer has the option of implementing the business interface or letting the interface be generated. In the previous example, a business interface named Converter is generated for ConverterBean by default. The generated interface is defined with the methods dollarToYen and yenToEuro. Generating business interfaces demonstrates that metadata annotation isn't the only place where defaults are assumed.


    If a developer wanted to implement the business interface, the code would look like this:



    @Stateless @Remote public class ConverterBean
    implements Converter {

    BigDecimal yenRate = new BigDecimal("121.6000");
    BigDecimal euroRate = new BigDecimal("0.0077");

    public BigDecimal dollarToYen(BigDecimal dollars) {
    BigDecimal result = dollars.multiply(yenRate);
    return result.setScale(2,BigDecimal.ROUND_UP);
    }

    public BigDecimal yenToEuro(BigDecimal yen) {
    BigDecimal result = yen.multiply(euroRate);
    return result.setScale(2,BigDecimal.ROUND_UP);
    }
    }

    public interface Converter {
    BigDecimal dollarToYen(BigDecimal dollars);
    BigDecimal yenToEuro(BigDecimal yen);
    }

    The Session Bean Client



    Here's part of what a remote client (in this case, a session bean) for the EJB 3.0 technology version ConverterBean might look like:


    import converter.Converter;
    import java.math.BigDecimal;

    @Session public class ConverterClient {
    @Inject Converter

    Converter currencyConverter;

    BigDecimal param = new BigDecimal("100.00");
    BigDecimal amount = currencyConverter.dollarToYen(param);

    ...
    }










    JNDI is no longer required to get references to resources and other objects in an enterprise bean's context. Instead, a developer can use resource and environment reference annotations in the bean class.






    Notice that there's no JNDI lookup code in the client. JNDI is no longer required to get references to resources and other objects in an enterprise bean's context. Instead, a developer can use resource and environment reference annotations in the bean class. These annotations are known as dependency annotations, because a developer uses them to declare the dependency of the enterprise bean on a resource or other object in the environment. The container then takes care of obtaining the references and providing them to the enterprise bean. Notice the @Inject annotation. It identifies a dependency injection, that is, it "injects" a dependency that the enterprise bean has on a resource or other object in the environment. Dependency injection can dramatically simplify what a developer has to code to obtain resource and environmental references.



    Although JNDI lookup is not required, it can still be used if desired.



    An Entity Bean With the EJB 3.0 Persistence Model











    EJB persistence technology is currently being updated for the entire Java platform as part of the EJB 3.0 specification. The new Java Persistence API will define a new single model for implementing persistence in the Java platform. The new model will take effect when J2EE 5.0 ships, which is currently planned for the first quarter of 2006. In the meantime, developers should continue to use container-managed persistance with enterprise beans. Existing container-manged persistence applications will continue to work unchanged because the current container-managed persistence functionality in EJB technology will continue to be supported (and will be improved as well). There is no need to migrate existing applications to this new API. The EJB expert group is also working hard to ensure that developers can make use of EJB technology and this new API in the same application.






    Now let's see what a developer does to develop an entity bean using EJB 3.0 technology. Once again, let's develop an entity bean named PlayerBean that represents a player on a sports team. PlayerBean the new lightweight persistence model, and has a many-to-many relationship to TeamBean, which represents a sports team. This is the same entity bean presented in Developing an Enterprise Bean with EJB 2.1 Technology. Here too you'll see how much easier it is to develop the bean using EJB 3.0 technology.











    To create an entity bean, a developer only needs to code a bean class and annotate it with appropriate metadata annotations. The bean class is coded as a POJO.






    To create the entity bean, a developer only needs to code a bean class and annotate it with appropriate metadata annotations. Here's what part of the bean class looks like:



    @Entity public class PlayerBean {

    private Long playerId;
    private String name;
    private String position;
    private double salary;
    private Collection teams;

    public PlayerBean() {}

    @id(generate=AUTO) public Long getPlayerId() {
    return id;
    }

    public String setPlayerId(Long id) {
    this id=id;
    }

    public String getName() {
    return name;
    }

    public String setName() {
    this name= name;
    }

    ...

    public Collection getTeams() {
    return teams;
    }

    public Collection setTeams(Collection teams) {
    this teams=teams;
    }

    ...


    The @Entity metadata annotation marks this as an entity bean. As is the case for a session bean in EJB 3.0 technology, there's no home interface, remote interface, or deployment descriptor to code. In fact, you don't even need a business interface for an entity bean. The bean class is coded as a POJO rather than a class that implements an interface such as javax.ejb.EntityBean. This means, among other things, that instances of an entity bean can be created simply through a new() operation. In addition, a developer no longer has to implement methods such as ejbRemove, ejbActivate, ejbPassivate, or ejbLoad in the bean class.



    In EJB 3.0 technology, an entity bean class is a concrete class. It's no longer an abstract class. Notice that an entity bean, as illustrated by PlayerBean, has non-abstract, private instance variables, such as PlayerID. These variables represent the bean's persistent fields. The persistent fields are accessible through access methods such as getPlayerID and setPlayerID. Access methods were also used in this way in EJB 2.1 technology. However in EJB 3.0 technology, access methods are concrete, not abstract. In addition, these get and set methods can include logic, something that wasn't possible previously. This is useful for actions such as validating fields. Another improvement is that access to the persistence fields is not limited to the get and set methods. The persistence fields are also accessible through a bean class's business methods. One restriction however is that in EJB 3.0 technology, only methods within the class can access persistence fields -- in other words, you can't expose the instance variables outside of the class. That's why the instance variables are private (they can also be protected). Also notice the constructor in the code. Entity beans in EJB 3.0 technology must define a constructor with no parameters.



    The @Id metadata annotation is used for the primary key. The element-value pair generate=AUTO tells the EJB container to pick a strategy for generating a primary key that's most appropriate for the database used by this application. @Id is one of the annotation types for object-relational mapping that's defined in the EJB 3.0 specification.


    The Entity Bean Client



    Here's what part of RosterBean, the session bean that locally accesses PlayerBean, might look like using EJB 3.0 technology:



    @Stateless public class RosterBean {

    @Inject EntityManager em;

    public Long createPlayer(PlayerBean player) {
    em.create(player);
    return player.getPlayerID();

    public PlayerBean findByPlayerId(Long playerId) {
    return (PlayerBean) em.find("Player", playerID);
    }
    ...

    }


    This version of the entity bean client is much smaller and easier to code than the version that uses EJB 2.1 technology. What makes the EJB 3.0 technology version smaller and simpler to code are two new features introduced in EJB 3.0 technology: dependency injection and the EntityManager.



    Dependency Injection



    As mentioned earlier, the @Inject metadata type identifies a dependency injection -- it injects a dependency that the enterprise bean has on a resource or other object in the environment. The container then takes care of obtaining the reference to the resource or object and provides it to the enterprise bean. Dependency injection reflects a fundamental change in philosophy in the EJB architecture. Previous versions of the EJB architecture forced the developer into complying with the requirements of the EJB container in terms of providing classes and implementing interfaces. By comparison, dependency injection reflects the fact that the bean tells the EJB container what it needs, and then container satisfies those needs.











    Dependency injection, a new feature introduced in EJB 3.0 technology,
    reflects a fundamental change in philosophy
    in the EJB architecture. Previous versions of the EJB architecture
    forced the developer into complying with the requirements of the EJB
    container in terms of providing classes and implementing interfaces. By
    comparison, dependency injection reflects the fact that the bean tells
    the EJB container what it needs, and then container satisfies those
    needs.







    In the RosterBean class the @Inject annotation tells the EJB container that the session bean needs the EntityManager object. In general, a dependency annotation identifies a needed resource or other object in the class's environment, and the name that is used to access that resource or object. The @Inject annotation is used when all the needed elements of the annotation can be inferred. Two other annotations that can be used for dependency injection are @Resource, which identifies a dependency on a resource, and @EJB, which identifies a dependency on a session bean. A developer can specify a dependency injection on a setter method of a bean class or on an instance variable in a bean class.



    It's the responsibility of the EJB container to inject the reference to the needed resource or object before the session bean is made available to handle a business method. This is typically at the time that the EJB container invokes the setSessionContext method.


    Dynamic Lookup



    Dependency injection is not the only way to locate resources. The EJB 3.0 specification also includes a dynamic lookup capability. This capability is offered through a lookup method in the javax.ejb.EJBContext interface. This provides the ability to dynamically look up a needed resource. In the following example, the setSessionContext subinterface of EJBContext is injected into the client code and then used to dynamically look up a session bean named myShoppingCart:



    ...
    @Inject
    private void setSessionContext(SessionContext ctx) {
    this.ctx = ctx;
    }
    ...
    myShoppingCart = (ShoppingCart)ctx.lookup
    ("shoppingCart");


    EntityManager











    The persistence model in EJB 3.0 technology has been simplified for entity beans with container-managed persistence.






    The persistence model in EJB 3.0 technology has been simplified for
    entity beans with container-managed persistence. A significant aspect
    of this simplified persistence model is the EntityManager, a new API in the EJB 3.0 architecture. The EntityManager is much like a home interface (but without a type). It is used to manage an entity bean's state. Various lifecycle methods are defined in the API, such as create, which puts an entity bean in a managed state (that is, what's termed a "persistence context") and remove, which removes an entity bean from the persistence context. When a bean instance is in a managed state, the data it represents is inserted into a database at the end of a transaction. The EntityManager also provides a flush method which synchronizes the persistence context with the underlying database. The data represented by a managed entity bean instance is inserted into a database when flush is issued, that is, before the end of the transaction. What gets inserted at the end of a transaction or through flush, and where in the database it gets inserted, depends on Object/Relational mapping specifications -- another new feature in EJB 3.0. When a bean instance is removed through remove, it's no longer in a managed state -- the data it represents is removed from the database at the end of a transaction, or sooner if flush is specified.



    Some other important methods provided by the EntityManager include find, which finds an entity bean instance by primary key, and merge, which merges the state of a detached entity bean instance into the current persistent context. The entity bean model in the EJB 3.0 architecture allows for detaching entity beans instances. An entity bean instance becomes detached at the end of a transaction. Detached instances can exist outside of the transaction context in which they were created. This allows a developer to do things such as serialize the bean instance to another application tier. This is a significant improvement over older versions of the entity bean model. Previously, entity beans were not serializable. Developers had to resort to a Data Transfer Object (DTO) to export an entity bean's state. In general, DTOs are not viewed positively. They're seen as "antipatterns," that is, bad solutions to a problem. The merge method brings the state of a detached instance into the persistence context.


    Looking back at the client code, RosterBean first requests the EJB container to inject a reference to the EntityManager:



    @Inject EntityManager em;


    Then RosterBean invokes the EntityManager's create method to put PlayerBean in a managed state:



    public Long createPlayer(PlayerBean player) {
    em.create(player);
    return player.getPlayerID();


    It then invokes the EntityManager's find method to find an instance of PlayerBean by its primary key.



    public PlayerBean findByPlayerId(Long playerId) {


    Other Improvements







    In addition to the simplifications highlighted in Developing an Enterprise Bean with EJB 3.0 Technology, the technology includes other ease-of-development improvements. Chief among these improvements are:



    • Support for testing enterprise beans outside of the EJB container

    • Support for Object-Relational mapping

    • Enhanced EJB QL



    Let's briefly examine each of these improvements.



    Support for Testing Outside of the EJB Container



    It's now much easier to test entity beans outside of an EJB container. Previously, the entity bean component model, with its requirements for home and component interfaces, abstract entity bean classes, and virtual persistent fields, made it difficult to test entity beans outside of the container. The entity bean model in the EJB 3.0 architecture removes the requirement for these interfaces. The only thing required for an entity bean is a concrete bean class that has non-abstract persistent fields. In addition, an entity bean's lifecycle is controlled through the EntityManager API, not through a home interface whose lifecycle methods are implemented by the EJB container. All of this makes entity beans less dependent on intervention by the EJB container, and so, can be more easily tested outside of the container.











    Entity beans are now less dependent on intervention by the EJB container, and so, can be more easily tested outside of the container.






    The difficulty of testing outside a container was compounded in the past by container-managed relationships. Because a container automatically manages these relationships, there's no assurance that a bean tested outside of the EJB container will behave the same and produce the same results as inside the EJB container. In supporting the testing of enterprise beans outside of an EJB container, the EJB 3.0 architecture removes support for container-managed relationships -- but still maintains support for bean-managed relationships. Dropping support for container-managed relationships was a difficult decision to make by the Expert Group responsible for the architecture. But the need to support entity bean testing outside of the EJB container is a very important requirement -- one that needed to be met.



    Support for Object/Relational Mapping



    The EJB 3.0 specification defines metadata annotations for Object/Relational (O/R) mapping, that is, the mapping of an entity bean to the relational database structure that underlies it. Or put another way, O/R mapping is the mapping of an object schema to a database schema. An O/R mapping specification was not part of the EJB architecture in the past. By providing it, the EJB architecture gives developers a lot more control over the data model than in the past.











    An Object/Relational (O/R) mapping specification has been added in the EJB 3.0 architecture. The O/R mapping supports inheritance and polymorphism.






    Significantly, O/R mapping support in the EJB 3.0 architecture supports inheritance and polymorphism. This means that a hierarchy of entity beans, where one entity bean subclasses another, can be mapped to a relational database structure, and the same queries or methods can be used against the different classes and subclasses in the hierarchy to produce results that are specific to that class or subclass.



    Metadata annotations include those for table mappings, column mappings, and associations (such as many-to-one and one-to-many). For example, here is a metadata annotation that maps an entity bean named Customer to a database table named CUST:



    @Entity
    @Table(name="CUST")

    public class Customer {...}


    Here's an example that specifies a one-to-many relationship between the Customer entity bean and an Order entity bean:



    @Entity
    @Table(name="CUST")

    public class Customer {
    private Setorders = new Hashset();
    ...

    @OneToMany(cascade=ALL)
    public Set getOrders() {
    return orders;
    }

    public void setOrders(Set orders) {
    this.orders = orders;
    }
    ...


    The cascade=ALL specification means that actions are cascaded through the relationship. So when a Customer instance is created and its data is stored in the database, all the orders for that instance are also stored in the database.



    Here's an example of mapping with inheritance. In the following example, ValuedCustomer is an entity bean that extends the Customer entity bean. The hierarchy is mapped to the CUST table:



    @Entity
    @Table(name="CUST")
    @Inheritance (strategy=SINGLE_TABLE,
    discriminatorType=STRING,
    discriminatorValue="CUST")
    public class Customer {...}

    @Entity
    @Inheritance (discriminatorValue="VCUST")
    public class ValuedCustomer extends Customer {...}


    The @Inheritance metadata annotation identifies an inheritance strategy for a class hierarchy. In this example, the strategy specified by the value of the strategy element is SINGLE_TABLE. This means that all the bean instances are mapped to a single table. This type of strategy requires a discriminator column in the table to identify one type of bean instance from another. The value in the column indicates the class for a specific bean instance. In the example, discriminatorType specifies that the discriminator column contains strings. The discriminatorValue element specifies that instances of Customer are identified by the value CUST, and instances of ValuedCustomer are identified by the value VCUST.



    As mentioned earlier, defaults can be used in many places throughout the EJB architecture. Relying on defaults, the inheritance example can be as simple as this:



    @Entity
    public class Customer {...}

    @Entity
    public class ValuedCustomer extends Customer {...}


    Enhanced EJB QL



    EJB QL has been a very popular facet of EJB technology. However, despite its popularity, EJB QL has lacked some of the features of a full SQL query language, such as bulk update and delete operations, outer join operations, projection, and subqueries. EJB 3.0 technology adds those features to EJB QL.











    EJB QL adds support for operations such as bulk update and delete, outer join, projection, and subqueries. It also adds support for outer join-based prefetching.






    For example, here's an EJB QL query that requests a bulk delete operation. It requests deletion of all customers whose status is inactive.



    DELETE
    FROM Customer c
    WHERE c.status= 'inactive'


    Here's an example of an EJB QL subquery. It's a correlated subquery that requests employees whose spouse is also an employee:



    SELECT DISTINCT emp
    FROM EMPLOYEE emp
    WHERE EXISTS (
    SELECT spouseEmp
    FROM EMPLOYEE spouseEmp
    WHERE spouseEmp = emp.spouse)


    Another important addition to EJB QL is support for outer join-based prefetching
    (termed a "FETCH JOIN"). A FETCH JOIN for a query returns a result and the prefetched data. For this to work, there must be an association between the entity that the query returns as a result and the prefeteched data. This gives developers a way of bringing in data that an application immediately needs, and related data that it will later need. Prefetching can improve application performance by reducing the number of EJB QL queries that need to be invoked (and the subsequent database transmissions that need to be made). For example, here is an outer join with a fetch that requests all customers in California and all the orders for those customers:



    SELECT DISTINCT c
    FROM CUSTOMER c LEFT JOIN FETCH c.orders
    WHERE c.address.state = 'CA'


    Beyond EJB QL enhancements, the EJB 3.0 architecture also adds a Query API to create dynamic queries and named queries (named queries are similar to static queries in EJB-SQL). Here's an example that creates a dynamic query. The query produces a result set of customers whose name is like a name that's dynamically supplied to the query.



    @Inject public EntityManager em;

    public List findWithName (string Name) {
    return em.CreateQuery {
    "SELECT c FROM Customer c" +
    "WHERE c.name LIKE :custName")
    .setParameter("custName", name)
    .setMaxResults(10)
    .listResults();
    }
    ...


    The CreateQuery method is a factory method of the EntityManager for creating queries. This example uses the Query API on the entity manager to generate the dynamic query. Like dynamic queries in SQL, the query is specified as a string. Notice the named parameter :custName. Named parameters have a colon (:) prefix. This is another enhancement to EJB QL. Named parameters can be used in addition to positional parameters in EJB QL queries. There are three method calls in the example. The setParameter method dynamically binds a specific name to the query at run time. The setMaxResults and listResults methods limit the result set to 10, and list the results, respectively.



    Here's an example that creates a named query. The named query in the example does essentially the same thing as the dynamic query in the previous example, that is, find customers who have a specific name. To create a named query, a developer first uses a metadata annotation (@NamedQuery) to define the named query:



    @NamedQuery {
    name="findAllCustomersWithName",
    queryString=
    "SELECT c" +
    "FROM Customer c" +
    "WHERE c.name LIKE :custName"
    }


    Next, the developer creates the named query that was previously defined:



    @Inject public EntityManager em;

    customers = em.createNamedQuery("findAllCustomersWithName")
    .setParameter("custName", "Smith")
    .setMaxResults(10)
    .listResults();
    }
    ...


    There's Even More







    This article only highlights some of the simplifications made to EJB technology in the EJB 3.0 Specification. You'll find even more improvements to the technology, and more detailed information, by reviewing the specification. Your feedback on the EJB 3.0 Specification is also very important in ensuring that EJB technology meets its objectives of simplifying the developer's experience while maintaining its power and sophistication.



    For More Information







    About the Author







    Ed Ort is a staff member of java.sun.com and developers.sun.com. He has written extensively about relational database technology, programming languages, and web services.






    Posted by 아름프로


    Developing an Enterprise Bean with EJB 2.1 Technology







    Let's examine what a developer does to create enterprise beans using EJB 2.1 technology. The examples presented here are taken from the J2EE 1.4 Tutorial. The source code for the examples is contained in the J2EE 1.4 tutorial bundle. If you download the tutorial bundle, you'll find the example source code below the /j2eetutorial14/examples/ejb directory, where <install_dir> is the directory where you installed the tutorial bundle.



    Note that the remainder of this article focuses on session beans and enterprise beans. Message-driven beans will not be specifically covered. Some of the same development techniques described in this section for stateless session beans also apply to message-driven beans. Also, many of the development simplifications and new features provided in EJB 3.0 technology are also applicable to message-driven beans. For information on how to develop message-driven beans in EJB 2.1 technology see Chapter 28: A Message-Driven Bean Example in the J2EE 1.4 Tutorial.



    A Stateless Session Bean



    Let's start with an example of a stateless session bean called ConverterBean. This is an enterprise bean that can be accessed remotely. The bean converts currency -- from dollars to yen, and from yen to euros. The source code for ConverterBean is in the /j2eetutorial14/examples/ejb/converter/src directory.



    To create the session bean, a developer needs to code:



    • A home interface that defines the life-cycle methods for the session bean that can be accessed
      by a remote client.

    • A remote interface that defines the business methods for the session bean that can be accessed by a remote client.

    • A bean class that contains the implementations of the home and remote interfaces.

    • A deployment descriptor that specifies information about the bean such as it's name and type.


    Home Interface



    Here's the home interface for ConverterBean:



    import java.rmi.RemoteException;
    import javax.ejb.CreateException;
    import javax.ejb.EJBHome;

    public interface ConverterHome extends EJBHome {
    Converter create() throws RemoteException, CreateException;
    }


    The home interface:



    • Extends the javax.ejb.EJBHome interface. All home interfaces must extend javax.ejb.EJBHome.

    • Defines a life-cycle method, create. A home interface must define one or more life cycle methods, such as create and remove, and these methods can have multiple signatures. In the case of a stateless session bean, the create method cannot have arguments. A remote client can invoke the create method to request creation of a session bean instance. In response, the EJB container creates the instance within the container (that is, on the server). The create method returns an object that is the remote interface type of the bean, in this example, Converter. This object runs locally on the client and acts as a proxy for the remote instance of the bean. A client can subsequently invoke business methods on the Converter object locally. In response, this invokes the same business methods on the remote session bean instance in the EJB container. The create method throws a RemoteException and a CreateException.


    Remote Interface



    Here's the remote interface for ConverterBean:



    import javax.ejb.EJBObject;
    import java.rmi.RemoteException;
    import java.math.*;

    public interface Converter extends EJBObject {
    public BigDecimal dollarToYen(BigDecimal dollars)
    throws RemoteException;
    public BigDecimal yenToEuro(BigDecimal yen)
    throws RemoteException;
    }


    The remote interface:



    • Extends the javax.ejb.EJBObject interface. All remote interfaces must extend the javax.ejb.EJBObject interface.

    • Defines the business methods for the bean, in this case, dollarToYen and yenToEuro. These are the methods that the remote client can call on the session bean. However, as mentioned in the description of the home interface, these method calls actually go through a local proxy object that subsequently invokes analogous methods on the remote session bean instance in the EJB container. Each business method throws a RemoteException.


    Bean Class



    Here's the class for ConverterBean:



    import java.rmi.RemoteException;
    import javax.ejb.SessionBean;
    import javax.ejb.SessionContext;
    import java.math.*;

    public class ConverterBean implements SessionBean {

    BigDecimal yenRate = new BigDecimal("121.6000");
    BigDecimal euroRate = new BigDecimal("0.0077");

    public BigDecimal dollarToYen(BigDecimal dollars) {
    BigDecimal result = dollars.multiply(yenRate);
    return result.setScale(2,BigDecimal.ROUND_UP);
    }

    public BigDecimal yenToEuro(BigDecimal yen) {
    BigDecimal result = yen.multiply(euroRate);
    return result.setScale(2,BigDecimal.ROUND_UP);
    }

    public ConverterBean() {}
    public void ejbCreate() {}
    public void ejbRemove() {}
    public void ejbActivate() {}
    public void ejbPassivate() {}
    public void setSessionContext(SessionContext sc) {}
    }

    The bean class:



    • Implements the javax.ejb.SessionBean interface. Because the session bean implements this interface, it must also implement all of the methods in the interface: ejbRemove, ejbActivate, ejbPassivate, and setSessionContext. The class must implement these methods even if it doesn't use them, as is the case here because the methods are empty.

    • Defines a constructor with no parameters.

    • Implements an ejbCreate method. A session bean must implement at least one ejbCreate method. It could implement more, but each must have a different signature. For every ejbCreate method implemented in the class, there must be a corresponding create method defined in the home interface. Recall that a client can't directly call a session or entity bean's methods, and instead calls methods defined in the bean's interfaces. To create an instance of the session bean, a remote client calls the create method on the home interface. In response, the EJB container instantiates the session bean and then invokes the corresponding ejbCreate method in the bean class to initialize the instance's state. In this example, ejbCreate is empty so there is no initial setting of data in the bean instance.

    • Implements the business methods defined in the remote interface: dollarToYen and yenToEuro. A remote client invokes business methods on the remote interface (through the local proxy). In response, this invokes the same business methods on the remote session bean component in the EJB container. The container then runs the business method implementations in the bean class.


    Deployment Descriptor



    Here's the deployment descriptor for ConverterBean:





    ConverterJAR


    ConverterBean
    converter.ConverterHome
    converter.Converter
    converter.ConverterBean
    Stateless
    Bean








    The deployment descriptor is an XML file that specifies basic information about
    the bean, such as it's name and the name of its interfaces. In fact, the descriptor's
    purpose is mainly to associate the bean class with the interfaces. The descriptor in this
    example also identifies this as a stateless session bean.


    The Session Bean Client



    To demonstrate how the bean is accessed, here's the remote client provided in the ConverterBean example inside the J2EE 1.4 tutorial bundle:



    import converter.Converter;
    import converter.ConverterHome;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.rmi.PortableRemoteObject;
    import java.math.BigDecimal;


    public class ConverterClient {
    public static void main(String[] args) {
    try {
    Context initial = new InitialContext();
    Context myEnv = (Context) initial.lookup("java:comp/env");
    Object objref = myEnv.lookup("ejb/SimpleConverter");

    ConverterHome home =
    (ConverterHome) PortableRemoteObject.narrow(objref,
    ConverterHome.class);

    Converter currencyConverter = home.create();

    BigDecimal param = new BigDecimal("100.00");
    BigDecimal amount = currencyConverter.dollarToYen(param);

    System.out.println(amount);
    amount = currencyConverter.yenToEuro(param);
    System.out.println(amount);

    System.exit(0);
    } catch (Exception ex) {
    System.err.println("Caught an unexpected exception!");
    ex.printStackTrace();
    }
    }
    }


    The initial part of the code creates an instance of the session bean. Recall that a client can't directly call a session bean's methods, and instead calls methods defined in the bean's interfaces. To create an instance of the session bean, the client needs to call the create method on the bean's home interface. To do that, the client first uses the Java Naming and Directory Interface (JNDI) to acquire an object that represents the ConverterHome interface. The client then invokes the create method on the ConverterHome object. In response, the EJB container creates the session bean instance and then invokes the corresponding ejbCreate method in the bean class to initialize the instance's state. In this example, ejbCreate is empty so there is no initial setting of data in the bean instance. The container returns a Converter object. To invoke a business method, the client calls the business method on the Converter object.



    An Entity Bean with Container-Managed Persistence



    For the second example, let's examine an entity bean called PlayerBean that represents a player on a sports team. PlayerBean uses container-managed persistence. In addition, it has relationships with other entity beans, such as TeamBean. The TeamBean entity bean represents a sports team. The relationship to TeamBean is many-to-many: a player can be on multiple teams (in different sports), and a team has multiple players. These relationships are maintained by the container. The source code for PlayerBean is in the /j2eetutorial14/examples/ejb/cmproster/src directory.


    An entity bean like PlayerBean that is the target of a container-managed relationship must have a local interface. So PlayerBean is accessible by local clients only. To create the entity bean, a developer needs to code:



    • A local home interface that defines the life-cycle methods for the entity bean that can be invoked by local clients.

    • A local interface that defines the business and access methods for the entity bean that can be invoked by local clients.

    • A bean class that contains the implementation of the business logic for the local home and local interfaces.

    • A deployment descriptor that specifies information about the bean such as its name, its persistence type, and its abstract schema.


    Local Home Interface



    Here's an excerpt from the local home interface for PlayerBean:



    package team;

    import java.util.*;
    import javax.ejb.*;

    public interface LocalPlayerHome extends EJBLocalHome {

    public LocalPlayer create (String id, String name,
    String position, double salary)
    throws CreateException;

    public LocalPlayer findByPrimaryKey (String id)
    throws FinderException;

    public Collection findByPosition(String position)
    throws FinderException;
    ...
    public Collection findBySport(String sport)
    throws FinderException;
    ...
    }


    The local home interface:



    • Extends the javax.ejb.EJBLocalHome interface. All local home interfaces must
      extend javax.ejb.EJBLocalHome.

    • Defines a life-cycle method, create. As is the case for home interfaces, a local home interface must define one or more life cycle methods, such as create and remove. However unlike methods for stateless sessions beans, a create method for an entity bean can have arguments. A client can invoke the create method to request creation of an entity bean instance. In response, the EJB container creates the instance within the container (that is, on the server). The create method returns an object that is the local interface type of the entity bean, in this example, LocalPlayer. It also throws a CreateException. (Because this is a local interface, the create method doesn't throw a RemoteException.)

    • Defines finder methods. These are methods whose name begins with find. A local home interface for an entity bean must define at least the findByPrimaryKey method. All finder methods except findByPrimaryKey use EJB QL queries (defined in the deployment descriptor for the bean) to find instances of an entity bean based on specific criteria. For example, findBySport uses an EJB QL query to find instances of PlayerBean that represent players in a specified sport. Finder methods return the local interface type of the entity bean or a collection of those types. They also throw a FinderException.



    Although not shown in this example, a local home interface can also define home methods. A home method is similar to a business method in that it contains business logic, but unlike a business method, a home method applies to all entity beans of a particular class. (A business method applies to a single entity bean.)


    Local Interface



    Here's the local interface for PlayerBean:



    package team;

    import java.util.*;
    import javax.ejb.*;

    public interface LocalPlayer extends EJBLocalObject {

    public String getPlayerId();
    public String getName();
    public String getPosition();
    public double getSalary();
    public Collection getTeams();

    public Collection getLeagues() throws FinderException;
    public Collection getSports() throws FinderException;
    }

    The local interface:



    • Extends the javax.ejb.EJBLocalObject interface. All local interfaces must extend the javax.ejb.EJBLocalObject interface.

    • Defines the access methods that a local client can invoke, in this case, getPlayerID, getName, getPosition, getSalary, and getTeams. These methods access the bean's persistent fields (playerID, name, position, and salary) and relationship field (teams) that are specified in the bean's deployment descriptor.

    • Defines business methods that a local client can invoke on the entity bean, in this case, getLeagues and getSports.


    Bean Class


    Here's an excerpt from the PlayerBean class:



    public abstract class PlayerBean implements EntityBean {
    private EntityContext context;


    public abstract String getPlayerId();
    public abstract void setPlayerId(String id);
    ...

    public abstract Collection getTeams();
    public abstract void setTeams(Collection teams);
    ...

    public abstract Collection ejbSelectLeagues(LocalPlayer player)
    throws FinderException;
    ...

    public Collection getLeagues() throws FinderException {
    LocalPlayer player =
    (team.LocalPlayer)context.getEJBLocalObject();
    return ejbSelectLeagues(player);
    }
    ...

    public String ejbCreate (String id, String name,
    String position, double salary) throws CreateException {

    setPlayerId(id);
    setName(name);
    setPosition(position);
    setSalary(salary);
    return null;
    }

    public void ejbPostCreate(String id, String name, String position,
    double salary) throws CreateException {
    }
    ...

    The bean class:



    • Implements the javax.ejb.EntityBean interface. Because the entity bean implements this interface, it must also implement all of the methods in the interface: ejbRemove, ejbActivate, ejbPassivate, ejbLoad, ejbStore, setEntityContext and unsetEntityContext. The class must implement these methods even if it doesn't use them.

    • Defines access methods such as getPlayerID and setPlayerID that access the bean's persistent fields, and methods such as getTeams and setTeams that access the bean's relationship field. Entity bean fields are identified as persistent fields or relationship fields in the bean's deployment descriptor. Notice that the access methods are defined as abstract. That's because the EJB container actually implements the methods. In other words, the container actually gets and sets the data for these fields.

    • Defines select methods, such as ejbSelectLeagues. These are methods that begin with ejbSelect. Select methods are similar to finder methods. For example, each select method requires a corresponding EJB QL query in the deployment descriptor. However unlike finder methods, select methods cannot be invoked by a client. They can be invoked only by the methods implemented in the entity bean class. In the PlayerBean class, the select methods appear within business methods (which the local client can invoke). Unlike select methods, finder methods are not defined in the bean class.

    • Implements business methods, such as getLeagues. In the PlayerBean class, these methods are essentially wrappers for select methods.

    • Implements an ejbCreate method and an ejbPostCreate method. To create an instance of the entity bean, a local client calls the create method on the local home interface. In response, the EJB container instantiates the entity bean and then invokes the corresponding ejbCreate method in the bean class. The container initializes the instance's state by calling the set access methods in ejbCreate to assign the input arguments to the persistent fields. At the end of the transaction that contains the create call, the container saves the persistent fields by inserting a row into the database. The container also calls method ejbPostCreate after the component is created. This method can be used to do things such as set a relationship field to initialize the bean instance. However, in this example, the method is empty.


    Deployment Descriptor


    Here's an excerpt from the deployment descriptor for PlayerBean:





    TeamJAR


    PlayerBean
    team.LocalPlayerHome
    team.LocalPlayer
    team.PlayerBean
    Container
    ...
    Player

    no description
    position

    ...
    playerId
    ...


    findAll


    select object(p) from Player p

    ...


    ejbSelectLeagues

    team.LocalPlayer


    Local
    select distinct t.league
    from Player p, in (p.teams) as t
    where p = ?1


    ...





    Many

    TeamBean


    players
    java.util.Collection



    Many

    PlayerBean


    teams
    java.util.Collection




    ...






    Clearly there's a lot more here than in the deployment descriptor for the stateless session bean in the previous example. In addition to the basic information it specifies about the entity bean, such as it's name and the name of its interfaces, the deployment descriptor specifies the bean's abstract schema. The abstract schema for the bean identifies the bean's container-managed persistence fields, such as position, and the bean's container-managed relationships, such as the many-to-many relationship between players and teams. The deployment descriptor also specifies EJB QL queries, such as select object(p) from Player p, and the finder method each query is associated with (in this case, findAll). Additionally, the deployment descriptor associates EJB QL queries with select methods.


    The Entity Bean Client and Remote Session Bean



    To demonstrate how the entity bean is accessed, here are some excerpts from the local client and from a remote session bean named RosterBean. The client and the session bean are provided in the ConverterBean example inside the J2EE 1.4 tutorial bundle. The client invokes methods on RosterBean, which works in conjunction with entity beans local to it, such as PlayerBean and TeamBean, to access needed data.


    Here is the client:



    import java.util.*;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.rmi.PortableRemoteObject;
    import util.*;
    import roster.*;


    public class RosterClient {
    public static void main(String[] args) {
    try {
    Context initial = new InitialContext();
    Object objref = initial.lookup("java:comp/env/ejb/SimpleRoster");

    RosterHome home =
    (RosterHome) PortableRemoteObject.narrow(objref,
    RosterHome.class);

    Roster myRoster = home.create();



    The client uses JNDI to acquire an object that represents the session bean's remote interface, RosterHome. The client then invokes the create method on the RosterHome object. In response, the EJB container creates the session bean instance, and invokes a corresponding ejbCreate method in the RosterBean class to initialize the instance's state.


    The client invokes the createPlayer method of RosterBean to create a new player:



    myRoster.createPlayer(new PlayerDetails("P1", "Phil Jones",
    "goalkeeper", 100.00));

    Here is the createPlayer method in RosterBean:



    public void createPlayer(PlayerDetails details) {

    try {
    LocalPlayer player = playerHome.create(details.getId(),
    details.getName(), details.getPosition(),
    details.getSalary());
    } catch (Exception ex) {
    throw new EJBException(ex.getMessage());
    }
    }

    The client then calls the addPlayer method of RosterBean to add player P1 to team T1:



    myRoster.addPlayer("P1", "T1");

    The P1 and T1 parameters are the primary keys of the PlayerBean and TeamBean instances.



    The client invokes the getPlayersByPosition method of PlayerBean to create a new player.



    playerList = myRoster.getPlayersByPosition("defender");


    The local home interface for PlayerBean defines the finder method, findByPosition, as follows:



    public Collection findByPosition(String position)
    throws FinderException;


    The EJB container then executes the EJB QL query associated with findByPosition in the bean's deployment descriptor. The EJB QL query is:



    SELECT DISTINCT OBJECT(p) FROM Player p
    WHERE p.position = ?1


    So What's the Problem?



    Looking at the EJB 2.1 examples, it's not too hard to understand why some developers see EJB technology as overly complex. Some of the things that feed this perception are:



    • The need to code a variety of classes, interfaces, and files for an enterprise bean. For even a "simple" enterprise bean, a developer needs to code two interfaces (a home and component interface), a bean class, and a deployment descriptor.

    • The size and complexity of the deployment descriptor. Notice especially the size and content of the deployment descriptor for the entity bean with container-managed persistence in the previous example. Beyond that, the deployment descriptor contains a lot of information that appears in the interfaces and class of the bean -- in other words, the deployment descriptor contains a lot of redundant information.

    • The many rules that need to be followed. EJB technology is quite prescriptive. Rules such as "all home interfaces must extend javax.ejb.EJBHome" pervade the technology.

    • The need to implement all interface methods. Because an enterprise bean class implements an interface, it must also implement all of the methods in the interface, such as ejbActivate and ejbPassivate. This is required even if the bean doesn't use the interface methods. This adds to what many developers see as "code clutter."

    • The use of JNDI to locate and acquire enterprise bean objects. Some developers view JNDI as clumsy and non-intuitive.



    EJB 3.0 technology aims to address these and other problems that contribute to perceived complexity.

    Posted by 아름프로


    Article

    Ease of Development in Enterprise JavaBeans Technology

























    By Ed Ort, October 2004







    Articles Index










    Enterprise Beans




    Enterprise JavaBeans (EJB) technology is a J2EE technology for developing business components in a component-based, enterprise Java application. Business components developed with EJB technology are often called Enterprise JavaBeans components or simply "enterprise beans." Enterprise beans typically provide the logic and represent the data needed to perform operations specific to a business area such as banking or retail. For example, an enterprise bean (perhaps together with other enterprise beans) might offer the data and logic needed to perform banking account operations, such as crediting and debiting an account. Other enterprise beans might offer the data and logic needed to perform "shopping cart" operations that allow customers to purchase goods online from a retail store.



    EJB technology is generally viewed as powerful and sophisticated. The technology helps developers build business applications that meet the heavy-duty needs of an enterprise. In particular, applications built using EJB and other J2EE technologies are secure, scale to support very large numbers of simultaneous users, and are transaction-enabled so that data maintains its integrity even though it's processed concurrently by multiple users.



    These needs are met through services that are provided by the EJB runtime environment -- the EJB container. What this means is that support for things like concurrent data access and security is automatically provided by the EJB container to all enterprise beans.



    Despite its power and sophistication, some developers are hesitant to use EJB technology. The major obstacle for these developers is complexity. But there's good news in store. The next release of the Enterprise JavaBeans architecture, EJB 3.0, focuses primarily on making the technology easier for developers to use -- but not at the expense of the technology's power and sophistication. (In addition, the EJB 2.0 and 2.1 APIs are still available for use.) The idea is not only to make EJB technology easier to use for developers who already use it, but to attract a wider range of developers.











    The next release of the Enterprise JavaBeans architecture, EJB 3.0, focuses primarily on making the technology easier for developers to use -- but not at the expense of the technology's power and sophistication.






    This article covers some of the ease-of-development features that are being planned for EJB 3.0 and that are documented in the EJB 3.0 Specification (now available as an early draft). It's important to note that the EJB 3.0 Specification is a work in progress, and so might change over time.


    But first, let's take a step back and look at some of the basics of EJB technology. Then let's look at how the technology works today. In other words, let's examine what a developer does to create and use enterprise beans with the current level of the technology, EJB 2.1. After that let's examine how EJB 3.0 simplifies things for developers.




    Table of Contents






    An Overview of Enterprise JavaBeans Technology







    This section gives a brief overview of some of the key concepts related to EJB technology. A lot of the material in this section is extracted from the J2EE 1.4 Tutorial, which is an excellent resource for learning more about EJB terminology and concepts. See especially Chapter 23: Enterprise Beans for a more detailed introduction to Enterprise JavaBeans technology.











    Enterprise beans are portable, reusable, and they're managed. The EJB container provides system-level services, so a developer is free to concentrate on developing the logic and data aspects of the application.






    As mentioned earlier, enterprise beans provide the logic and represent the data for business-oriented operations. Enterprise beans are portable -- you can deploy them in any compliant J2EE application server. This gives developers a lot of flexibility in terms of distributing the components of an application. Enterprise beans are also reusable -- you can use them in multiple business applications. But perhaps what's most appealing about enterprise beans is that they're managed. The EJB container provides system-level services such as transaction management (to preserve the integrity of data in a multi-user environment) and security management (to protect against unauthorized access to resources). Because the EJB container provides these and other system-level services, a developer does not have to provide them in an application, and so is free to concentrate on developing the logic and data aspects of the application.



    There are three types of enterprise beans: session beans, entity beans, and message-driven beans. Often a combination of these beans is used in an enterprise application.



    Session Beans









    Session Bean




    A session bean represents a single unique session between a client and an instance of the bean. A session bean can't be shared. One instance of the bean is tied to a specific client in a specific session. The session bean exposes methods that a client can call to execute business tasks on the server. When the client's session ends, the session bean is no longer associated with that client.



    There are two types of session beans: stateful and stateless. A stateful session bean maintains data about the unique client-bean session in its instance variables. The data represents the state (often called the "conversational state") of that specific session. The conversational state is maintained for the life of the client-bean association. Significantly, this means that the data is maintained across operations. If one of the bean's methods finishes executing and another is called during the session, the conversational state is maintained from one operation to the next. This makes stateful session beans useful for things like shopping cart and banking services that involve multiple, related operations. To maintain conversational state when space is constrained, the EJB container might write a stateful session bean to secondary storage and then later retrieve it.



    By comparison, a stateless session bean does not maintain conversational state for its client. Because a stateless session bean cannot maintain conversational state across methods, it's typically used for one-step tasks, such as sending an email that confirms an online order.


    An EJB container never writes a stateless session bean to secondary storage. One other distinguishing thing about a stateless session bean is that it can implement a web service.



    Entity Beans









    Entity Bean



    An entity bean represents data in a storage medium, such as a relational database. Each entity bean may correspond to a table in a relational database, and each instance of the bean corresponds to a row in that table. Entity beans are not limited to representing relational databases. They can represent data in other types of data stores. But the majority of enterprise applications that use EJB technology access data in relational databases, so this article focuses on that type of data store.



    The emphasis here is on the word "represents." An entity bean in not part of a relational
    database, but rather contains data that is loaded from the database at appropriate points in time.
    The data is then written back to the database at other appropriate points in time.



    An entity bean differs from a session bean in several ways. An entity bean can be shared (a session bean cannot), that is, multiple clients can use the same entity bean. The gives multiple clients the ability to access the same data that the bean represents. Of course, this is where the transaction management (and its data integrity control) provided by the EJB container is important. In addition, entity beans are persistent. This means that the entity bean's state exists even after the application that uses it ends. The bean is persistent because the database that underlies it is persistent. For that matter, the entity bean's state can be reconstructed even after a server crash (because the database can be reconstructed). Remember that the state of a stateful session bean exists only for the life of the client-bean session, and for a stateless session bean, only during the life of a method. Also, an entity bean can have relationships with other entity beans, much like a table in a relational database can be related to another table. For example, in a college enrollment application, an entity bean that represents data about students might be related to an entity bean that represents data about classes. By comparison, a session bean cannot be related to other session beans.



    An entity bean can manage its own persistence (this is called bean-managed persistence) or let the EJB container manage it (container-managed persistence). With bean-managed persistence, the entity bean code includes SQL statements that access the database. With container-managed persistence, the EJB container automatically generates the necessary database access calls.



    Message-Driven Beans









    Message-Driven Bean




    A message-driven bean processes asynchronous messages typically sent through the Java Message Service (JMS) API. Asynchronous messaging frees the message sender from waiting for a response from the message receiver.



    A message-driven bean can process messages sent by any J2EE component (such as an application client, another enterprise bean, or a web component) or by a JMS application or system that does not use J2EE technology. Often message-driven beans are used to route messages. This makes them useful in many business-to-business communication scenarios.



    Enterprise Bean Interfaces and Classes



    Although it's easy to imagine a client directly calling a bean's methods, the reality is that it can't. Instead, for session or entity beans, a client calls methods defined in the bean's interfaces. These interfaces comprise the client's "view" of the bean. A session or entity bean must have two interfaces -- a component interface and a home interface -- as well as a bean class. Neither can a client access a message-driven bean directly -- it needs to send messages to the message endpoint serviced by the bean.



    The component interface defines the business methods for the bean. For example, the component interface for a session bean that handles bank accounts might define a method that credits an account and one that debits an account. The home interface defines "life-cycle" methods for the bean. These are methods that do things like create an instance of a bean or remove it (or at least make it unavailable). For entity beans, the home interface can also define finder methods and home methods. Finder methods locate instances of a bean. Home methods are business methods that are invoked on all instances of an entity bean class.



    The bean class implements the methods defined in the bean's interfaces.



    Local and Remote Enterprise Beans



    Clients can access beans locally, that is, where the client and bean are in the same Java virtual machine1, or remotely, where the client and bean can be in different Java virtual machines (or even different physical machines). A local or remote client can be a web component or another enterprise bean. A remote client can also be a web application. For local access, a session or entity bean must provide a component interface called a local interface, and a home interface called a local home interface. For remote access, a session or entity bean must provide a component interface called a remote interface, and a home interface.



    The EJB Container and Persistence



    Clearly, the EJB container plays an important role in Enterprise JavaBeans technology. It provides the runtime environment inside of an application server for enterprise beans. In doing that, it offers a wide variety of services to the beans, such as transaction management and security control. In addition, it manages persistence for entity beans with container-managed persistence, and relationships for entity beans with container-managed relationships. To manage persistence and relationships, the EJB container needs information beyond the information provided in the bean's interfaces and classes. This additional information is provided in an abstract schema that defines the bean's persistent fields (the fields that represent persistent data) and the bean's relationships. An abstract schema differs from the physical schema of the underlying database (which defines the table structures in the database and the table relationships). In EJB 2.0 and EJB 2.1 technology, you need to provide deployment descriptor information for each entity bean. The deployment descriptor specifies, among other things, the abstract schema for the bean (see Developing an Enterprise Bean with EJB 2.1 Technology, for an example).



    EJB Query Language



    Recall that an entity bean with container-managed persistence does not include SQL statements. So you might wonder, how does the EJB container know what persistent data to access and what to return? The answer is through finder methods and Enterprise JavaBeans Query Language (EJB QL) queries. Finder methods find instances of an entity bean or collections of entity beans. EJB QL queries query the abstract schema. You specify finder methods in the home interface of the bean, and associate them with queries written in EJB QL. An EJB QL query looks like an SQL query -- it contains a SELECT clause, a FROM clause, and a WHERE clause. However, unlike an SQL-based query, an EJB QL query queries the abstract schema, not the database. When a finder method is invoked, the EJB container executes the EJB QL query associated with that method and returns references to one or more entity beans that represent data satisfying the query criteria. An example of a finder method might be one that identifies bank accounts that have an account balance that is less than a certain threshold. The EJB QL query for that finder method queries the abstract schema and returns references to one or more entity beans that represent accounts meeting the query criteria. In addition to the abstract schema it defines, the deployment descriptor for an entity bean in EJB 2.1 technology defines the EJB QL queries for the bean and associates the queries with finder methods.

    Posted by 아름프로
    잘알고 있다고 생각들 하는 JDBC ...
    JDBC 전문가가 이야기하는거 한번 들어보세요.. ^^
    Posted by 아름프로

    Roadmap to

    Agile methods and tools



    What Is Agile Software Development?


    In the late 1990's several methodologies began to get increasing
    public attention. Each had a different combination of old ideas, new
    ideas, and transmuted old ideas.
    But they all emphasized close collaboration
    between the programmer team and business experts; face-to-face
    communication (as more efficient than written documentation);
    frequent delivery of new deployable business value; tight,
    self-organizing teams; and ways to craft the code and the
    team such that the inevitable requirements churn was not a crisis.



    Early 2001 saw a workshop in Snowbird, Utah, USA, where various
    originators and practitioners of these methodologies met to figure
    out just what it was they had in common. They picked the word "agile"
    for an umbrella term and crafted the
    Manifesto for Agile Software
    Development
    , whose most important part was a statement of
    shared development values:




    We are uncovering better ways of developing
    software by doing it and helping others do it.
    Through this work we have come to value:




    Individuals and interactions over processes and tools

    Working software over comprehensive documentation

    Customer collaboration over contract negotiation

    Responding to change over following a plan




    That is, while there is value in the items on
    the right, we value the items on the left more.



    (See also the attached principles.)



    The Manifesto struck a chord, and it led to many new Agile projects
    being started. As with any human endeavor, some succeeded and
    some failed. But what was striking about the successes was how much
    both the business people and the technical people loved their
    project. This was the way they wanted software development
    done. Successful projects spawned enthusiasts.



    The Agile Alliance exists to help more Agile projects succeed and to
    help the enthusiasts start more Agile projects. This particular page
    is to help people learn more about Agile software development. In
    keeping with the Agile emphasis on face-to-face communication, we urge
    you to visit a
    users group
    and talk to your peers about their
    experience. But we also provide this Roadmap, which intends to give you a quick
    introduction to various agile methods and tools. Click on the links
    below to get more info on a certain method or tool. On the following
    pages you will find links to pages that contain the specific
    information you need.



    If you're looking for more information regarding the history of the Agile
    Alliance then look at
    the articles section
    .




    Each page contains links to books published on the method. Please use
    the supplied link if you intend to order any books. By doing so you
    sponsor the Agile Alliance. No hassle for you but a great help for us: href="http://www.amazon.com/exec/obidos/external-search?tag=agilealliance-20&keyword=agile%20methods&mode=books">
    General Books on Agile Methods.





    Version 2.3 revised on December 16th, 2004





    Posted by 아름프로

    RCP (Rich Client Platform)

    2005. 3. 3. 11:57
    Eclipse Rich Client Platform
    While the Eclipse platform is designed to serve as an open tools platform, it is architected so that its components could be used to build just about any client application. The minimal set of plug-ins needed to build a rich client application is collectively known as the Rich Client Platform.

    Applications that don't require a common resource model can be built using a subset of the platform. These rich applications are still based on a dynamic plug-in model, and the UI is built using the same toolkits and extension points. The layout and function of the workbench is under fine-grained control of the plug-in developer in this case.

    When we say that the Rich Client Platform is the minimal set of plug-ins needed to build a platform application with a UI, we mean that your application need only require two plug-ins, org.eclipse.ui and org.eclipse.core.runtime, and their prerequisites. However, rich client applications are free to use any API deemed necessary for their feature set, and can require any plug-ins above the bare minimum. Examples include the Help UI, and the Update Manager.

    Posted by 아름프로
    Web Services Metadata(WSM)에 대한 BEA 자료
    Posted by 아름프로
    Securing XML is an essential element in keeping Web services secure. Created in partnership with our sister site, SearchSecurity.com, this SearchWebServices.com Learning Guide is a compilation of resources that review different types of XML security standards and approaches for keeping your XML Web services secure. Send us an e-mail to let us know what other learning guides you'd like to see on SearchWebServices.com.
    Posted by 아름프로
    BPEL4WS – Business Process Execution Language for Web Services
    Java developers need to publish synchronous and asynchronous Web services and compose them into reliable and transactional business flows. Web service orchestration standards (SOAP Conversation, BPEL4WS and WS-Transaction) are emerging and need to be packaged into a reliable and easy-to-manage software solution. So we've gathered a wealth of information to get you up-to-speed quickly.

    Posted by 아름프로
    Posted by 아름프로

    PMD for Eclipse install instructions





    1. Start Eclipse.


    2. Start the installation procedure : select the Help>Software Updates>Find and
      Install... menu item.


    3. Select "Search for new features to install" option and click Next.


    4. Click New Remote Site...


    5. Give a name (ie PMD Eclipse Site), enter the URL http://pmd.sourceforge.net/eclipse


    6. Select this new site in the Sites to include in search list and click Next.


    7. Select PMD for Eclipse 3 and Apache Xerces in the "Select the features to install" list and click Next.


    8. Accept the terms of the license agreements and click Next.


    9. Verify that the install location is your Eclipse installation directory, otherwise
      select the correct one, click Finish.


    10. A warning appear telling the feature is not signed. Ignore and click Install to
      continue.


    11. Accept to restart the workbench to load PMD into the workbench.



    Eclipse is restarted and a PMD welcome page is displayed : the plugin is correctly
    installed.

    Posted by 아름프로




















    서비스 지향 모델링과 아키텍쳐
























    SOA 서비스의 정의, 특성화, 구현 방법






    Level: Intermediate







    Average rating:
    (29 ratings)

    Ali Arsanjani, 박사

    아키텍트, SOA and Web services Center of Excellence, IBM

    2004년 11월 9일


    서비스 지향 모델링과 아키텍쳐의 핵심을 논의한다. 서비스
    지향 아키텍쳐(SOA)를 구현하는데 필요한 분석과 디자인을 위한 핵심 액티비티를 논의한다. 필자는 서비스의
    정의, 특성화, 실현에 필요한 기술을 언급하는 것의 중요성을 강조하고 있다. 또한 서비스의 흐름과 구성,
    SOA에 요구되는 서비스의 품질을 실현 및 보증하기 위해 필요한 엔터프라이즈급 컴포넌트의 중요성에 대해서도
    이야기 하고 있다.

    Introduction

    그동안 서비스 지향 아키텍쳐(SOA)와 웹 서비스로서 이를 구현하는 것을 둘러싸고 많은 소문과 가설들 -
    이중 몇몇은 사실이고 어떤 것은 전혀 근거 없는 것이었다 - 이 무성했다. 분석가들은 예언했고, 학자들은
    가설을 내놓았으며, 교수들은 강의했고, SOA는 제품이 아니라는 중요한 사실을 망각한 기업들은 그들이 가진
    것을 SOA로 포장해서 팔기에 급급했다. 디자인 원리, 패턴, 기술을 사용하는 비지니스와 제휴된 IT 서비스를
    통해 비지니스와 IT 사이의 차이를 이으려고 한다.


    ZDNet
    최근 "Gartner는 2008년 까지, 60 퍼센트 이상의 기업들이 중요한 미션을 수행하는 애플리케이션과
    프로세스를 만들 때 "가이드 원리" 로서 SOA를 사용할 것"이라고 발표했다."


    SOA의 개발과 구현에 대한 수요는 대단하다. 만일 SOA가 이들을 구현하는 것을 돕는 단순한 제품과
    표준에 관한 것이 아니라면, 예를 들어, 웹 서비스 같이, 어떤 추가적인 요소들이 SOA를 구현하는데 필요한가?
    서비스 지향 모델링은 전통적인 객체 지향의 분석과 디자인(OOAD)에는 없는 추가적인 액티비티와 가공물들이
    필요하다. “Elements
    of Service-oriented Analysis and Design
    " 에서는 OOAD 그 이상의
    것이 필요한 이유를 설명하고 있다. 또한 이 글에서는, 비지니스 프로세스 관리 또는 엔터프라이즈 아키텍쳐(EA)와
    OOAD가 분석과 디자인을 수행하기에 부적절한지도 설명한다. IBM Redbook, “Patterns:
    Service-Oriented Architecture and Web Services
    "에서는 서비스
    지향 모델링 접근방식의 주요 액티비티를 설명하고 있다.


    하지만 몇 가지 더 고려해야 할 중요한 사항들이 있다.우선, 현재 OOAD 방식은 SOA의 세 가지 핵심
    요소들인 서비스, 플로우, 서비스를 구현하는 컴포넌트를 다루지 않는다. 또한, 서비스의 구분, 특성화,
    구현에 필요한 기술과 프로세스, 흐름과 구성, 엔터프라이즈 급의 컴포넌트를 분명히 다룰 필요도 있다.


    두 번째, SOA에서 두 가지 핵심 역할들인 서비스 공급자와 서비스 소비자에 대한 분명한 요구사항을 파악하기
    위해 패러다임 변화가 필요하다. 셋째로, 하나의 엔터프라이즈 또는 비지니스 라인을 위해 구현될 애플리케이션들은
    공급 체인 안에서 사용되어야 하고, 이 애플리케이션들을 새로운 애플리케이션으로 구성, 결합 및 캡슐화 할
    비지니스 파트너들에게 노출되어야 한다. 이러한 개념을 서비스 생태계 또는 서비스 밸류 네트(value-net)
    라고 한다.


    이는 "분산 객체" 보다 약간 올라선 개념이다. 네트워크 효과를 통해 만들어진 가치에
    대한 것이다; 예를 들어 Google의 검색 서비스와 Amazon.com을 결합하고, 이들을 eBay 서비스와
    결합하여 혼합 솔루션을 구현했다고 해보자. 이런 예도 생각할 수 있다. 여행사가 항공 예약 시스템과 연계하고,
    렌트카 에이전시와 호텔 체인과 협업할 때, 기록들이 업데이트 되고 여행 일정이 전자 계획표상에 전송된다.
    애플리케이션이 무엇이든 간에, SOA를 성공적으로 구현하기 위해서는 좋은 툴과 표준 그 이상이 필요하다.
    SOA의 수명 주기를 지원할 통시적 시각이 필요하다; 분석, 디자인, 서비스 구현, 플로우, 컴포넌트 등에
    대한 기술이 필요하다. 따라서 엔터프라이즈 애플리케이션 개발에 관심이 있는 사람이라면 서비스 지향 모델링과
    아키텍쳐에 개입된 상세한 단계들을 이해해야 한다.


    이들 과정을 자세히 설명하기 전에 여러분이 만들어내고자 하는 것을 이해하도록 하자; SOA가 무엇이고
    어떤 모습인가? SOA의 개념을 정의한 후에 SOA의 레이어를 설명하고, 프로젝트, 비지니스 성격, 엔터프라이즈
    목적, 밸류 체인에 합당한 SOA의 청사진을 구현할 수 있도록 그러한 레이어들 마다 핵심적인 아키텍쳐 결정을
    수립하는 방법을 설명하겠다.


    서비스 지향 아키텍쳐:
    개념 모델


    이 개념은 세 가지 주요 참여자들인 서비스 공급자(서비스 디스크립션의 퍼블리시 및 서비스 구현 공급),
    서비스 사용자(서비스 디스크립션의 URI를 직접 사용하거나 서비스 레지스트리에서 서비스 디스크립션을 찾아
    호출), 서비스 브로커(서비스 레지스트리의 공급 및 관리) 사이의 인터랙션을 정의하는 아키텍쳐 스타일에
    기반하고 있다.


    아래 그림 1은 이러한 관계를 보여주는 메타-모델이다.


    그림 1: SOA 아키텍쳐 스타일의 개념 모델

    The Java Beans view


    아키텍쳐 스타일과 원리

    SOA를 정의하는 아키텍쳐 스타일은 약결합된, 비지니스와 연계된 서비스를 만드는 일련의 패턴과 가이드라인을
    설명한다. 디스크립션, 구현, 분리의 문제를 해결하지는 못한다. 새로운 비지니스 위협과 기회에 대한 응답에
    있어 전례가 없는 유연성을 제공한다.


    SOA는 리소스를 "온 디맨드" 방식으로 연결하기 위한 엔터프라이즈급의 IT 아키텍쳐이다.
    SOA에서 리소스들은 밸류 네트, 엔터프라이즈, 비지니스 라인에 참여할 수 있다. 한 조직의 비지니스 프로세스
    및 목표를 집합적으로 수행하는 비지니스와 제휴된 IT 서비스들로 구성되어 있다. 이러한 서비스들을 합성
    애플리케이션으로 구성할 수 있고 표준 프로토콜을 통해 호출할 수 있다.(그림
    2
    )


    서비스는 외부화된 서비스 디스크립션을 갖춘 소프트웨어 리소스이다. 서비스 디스크립션은 서비스 소비자들에
    의해 검색, 바인딩, 호출될 수 있다. 서비스 공급자는 서비스 디스크립션 구현을 실현하고 서비스 소비자들에게
    양질의 서비스 요구 사항들을 제공한다. 서비스들은 선언적 정책에 의해 관리되어 동적으로
    설정 가능한 아키텍쳐 스타일
    을 지원하는 것이 이상적이다.


    그림 2: SOA의 애트리뷰트

    IT services


    비지니스민첩성은 SOA에 의해 제공되는 인터페이스, 구현, 바인딩(프로토콜)의 분리로 인해 유연해진
    IT 시스템을 통해 이룩될 수 있다. 어떤 서비스 공급자가 새로운 비지니스 요구 사항들에 기반하여 주어진
    지점과 시간에 적절한지를 선택할 여유도 주어진다. (함수적 요구사항과 비 함수적 요구사항(예를 들어, 퍼포먼스,
    보안, 확장성 등)).


    fractal realization pattern으로 내부 비지니스단위 또는 비지니스파트너들 사이의
    밸류 체인을 통해 서비스들을 재사용할 수 있다. fractal realization은 인터랙션 모델에 참여한
    참여자들의 패턴과 역할을 적용하기 위해 아키텍쳐 스타일의 기능을 참조한다. 아키텍쳐 내의 한 티어에 이를
    적용할 수 있고 엔터프라이즈 아키텍쳐를 통해 멀티 티어에도 적용할 수 있다. 프로젝트 사이에서는 하나의
    밸류 체인 안에서 일관성 및 확장 가능한 방식으로 비지니스 단위들과 비지니스 파트너들 간 존재할 수 있다.


    콘텍스트

    이 섹션에서는 서비스 지향 모델링의 구분, 특성화, 구현, 가공물의 고급 작동에 대해 소개하겠다. 서비스
    지향 모델링은 비지니스분석, 프로세스, 목표와 연계된 SOA의 모델링, 분석, 디자인, 제작을 위한 서비스
    지향 분석과 디자인(SOAD) 프로세스 이다.


    우선, 구현하려고 하는 것, 주로 SOA와 이것의 레이어를 살펴보자. 그런 다음, SOA를 구현할 때
    필요한 주요 액티비티와 기술을 설명하면서 SOA 구현 방법을 설명하겠다.


    예를 들어, 여러분이 프로젝트를 진행 중이고 목표는 셀프 서비스 어카운팅 시스템을 갖고 있는 비지니스의
    뱅킹 라인의 한 부분을 SOA로 마이그레이션 한다고 생각해보자.


    SOA로 마이그레이션 하기 위해서는 서비스 모델링 외에도 몇 가지 추가 요소들이 필요하다:


    • 채택과 성숙 모델. SOA와 웹 서비스의 채택에 있어 엔터프라이즈의 상대적 성숙도는 어느 정도인가?
      다양한 채택 레벨들은 그 레벨 마다 고유한 필요가 있다.

    • 평가. 파일럿을 갖고 있는가? 웹 서비스에 관여해 본 적이 있는가? 결과 아키텍쳐의 상태는 어떠한가?
      같은 방향으로 지속적으로 가야하는가? 이것이 엔터프라이즈 SOA로 이끌 것인가? 고려해야 할 사항들을
      생각해 보았는가?

    • 전략과 플래닝 액티비티. SOA로 마이그레이션하기 위해 어떤 계획을 세웠는가? 절차, 툴, 메소드,
      기술, 표준, 교육 등 고려해야 할 사항들은 무엇인가? 로드맵과 전망은 무엇이며, 어떻게 도달 할 것인가?
      계획은 무엇인가?

    • 관리. 기존 API 또는 기능들이 서비스가 되어야 하는가? 그렇지 않다면 어떤 것이 가능한가?
      모든 서비스들은 어떤 방식으로든 비지니스에 가치를 창출하도록 구현되어야 한다. 여기에 개입하지 않고
      프로세스를 어떻게 관리하는가?

    • 최상의 사용법 구현. 보안을 구현하고, 퍼포먼스를 보장하고, 상호운용성을 위한 표준에 순응하고 변화를
      계획하기 위해 시도된 방식은 무엇인가?


    이 글에서 설명한 구분, 특성화, 구현 외에도 서비스 지향 모델링 방식에는 SOA의 전체 수명 주기를 지원하는데
    필요한 전개, 모니터링, 관리 기술들이 포함된다.


    SOA로의 마이그레이션과 구현 후 추가 액티비티에 대한 논의는 다음 글에서 서서히 다루도록 하겠다. 지금은
    기존 시스템 또는 서비스를 새로운 시스템과 서비스로 변형하는 것에 초점을 맞추겠다. 서비스 지향 아키텍쳐를
    구현하기 위해 서비스 지향 모델링을 시작할 수 있다.


    SOA를 위한 아키텍쳐
    템플릿


    SOA의 추상적인 모습은 비지니스프로세스와 제휴된 합성 서비스들이 부분적으로 레이어 된 아키텍쳐이다.
    그림 3은 이러한 유형의 아키텍쳐를 묘사하고 있다.


    서비스와 컴포넌트 사이의 관계는 엔터프라이즈급 컴포넌트들(크게 구분된 엔터프라이즈 또는 비지니스 라인
    컴포넌트)이 서비스를 실현하고, 기능을 제공하고 서비스의 품질을 관리하는 것이다. 비지니스프로세스 플로우는
    이렇게 노출된 서비스들을 합성 애플리케이션에 구성함으로서 지원될 수 있다. 통합 아키텍쳐는 Enterprise
    Service Bus (ESB)를 사용하여 서비스, 컴포넌트, 플로우의 라우팅, 중개, 트랜슬레이션을 지원한다.


    그림 3: SOA의 레이어

    SOA layers


    이들 각 레이어의 경우 디자인과 아키텍쳐 결정을 내려야 한다. 따라서 SOA를 문서화하려면 각 레이어에
    상응하는 섹션들로 구성된 문서를 만들어야 한다.


    다음은 SOA 아키텍쳐 문서를 위한 템플릿이다:


    1. 범위 <이 아키텍쳐가 필요한 엔터프라이즈 영역은?>

    2. 연산 시스템 레이어


      1. 패키지 애플리케이션

      2. 커스텀 애플리케이션

      3. 아키텍쳐 결정


    3. 엔터프라이즈 컴포넌트 레이어


      1. 엔터프라이즈 컴포넌트로 지원되는 기능 영역

      2. <이 엔터프라이즈 컴포넌트로 지원되는 비지니스도메인, 목표 프로세스는 무엇인가?>

      3. 관리와 관련된 결정


        1. <클라이언트 조직 내에서 엔터프라이즈 컴포넌트로서 선택된 것들의 기준은 무엇인가?>


      4. 아키텍쳐 결정


    4. 서비스 레이어


      1. 서비스 포트폴리오 범주

      2. 아키텍쳐 결정


    5. 비지니스프로세스 및 합성 레이어


      1. 구성법으로 표현되는 비지니스프로세스

      2. 아키텍쳐 결정


        1. <어떤 프로세스가 구성법으로 연결되어야 하고 어떤 것이 애플리케이션 안으로 구현되어야
          하는가?>



    6. 액세스 또는 표현 레이어


      1. <이 레이어 상의 웹 서비스와 SOA의 문서 포함; 예를 들어 사용자 인터페이스 레벨에서
        웹 서비스를 호출하는 포틀릿의 사용과 그러한 레이어의 기능에 대한 내용>


    7. 통합 레이어


      1. <ESB 고려사항 포함>



      1. <서비스의 클라이언트가 필요로 하는 서비스 레벨 계약(SLA)와 서비스 품질(QoS)을
        어떻게 보장하는가?>

      2. 보안 문제 및 결정

      3. 퍼포먼스 문제 및 결정

      4. 기술과 표준 한계 및 결정

      5. 서비스의 모니터링과 관리


        1. 디스크립션과 결정




    이제 각 레이어를 상세히 살펴보겠다.


    Layer 1: 연산 시스템 레이어. 기존의 커스텀 구현 애플리케이션, 다시 말해서 레거시
    시스템들(기존 CRM, ERP 패키지 애플리케이션, 오래된 객체 지향 시스템 구현, 비지니스정보 애플리케이션)로
    구성된다. 이 레이어에서는 기존 시스템을 사용하고 이들을 서비스 지향 통합 기술을 사용하여 통합할 수 있다.


    Layer 2: 엔터프라이즈 컴포넌트 레이어. 노출된 서비스의 기능을 구현하고 QoS를
    관리하는 책임을 맡고 있다. 이 특별한 컴포넌트는 엔터프라이즈 또는 비지니스단위 레벨의 자금 지원을 받는
    엔터프라이즈 자산으로 관리된다. 엔터프라이즈급의 자산으로서 애플리케이션을 사용할 때 SLA 순응해야 한다.
    이 레이어에서는 애플리케이션 서버 같은 컨테이너 기반의 기술을 사용하여 컴포넌트, 워크로드 관리, 고 가용성,
    로드 밸런싱을 구현한다.


    Layer 3: 서비스 레이어. 비지니스가 자금을 지원하고 노출하기로 선택한 서비스들이
    이 레이어에 있다. 이 서비스들은 발견될 수도 있고 또는 정적으로 바인딩 되어 호출될 수도 있고 또는 합성
    서비스로 구성될 수도 있다. 이 서비스 노출 레이어는 엔터프라이즈급 컴포넌트, 비지니스단위 스팩의 컴포넌트,
    프로젝트 스팩의 컴포넌트를 가져다가 서비스 디스크립션의 형태로 그들의 인터페이스들의 하위 세트를 외부화하는
    메커니즘을 제공한다. 따라서, 엔터프라이즈 컴포넌트는 인터페이스가 제공하는 기능을 사용하여 런타임 시 서비스
    구현을 제공한다. 이 레이어에서 인터페이스는 서비스 디스크립션으로서 반출된다. 이곳이 노출되어 사용되는
    곳이다. 고립되어 존재할 수도 있고 합성 서비스로서 존재할 수 있다.


    Level 4: 비지니스프로세스 합성 및 구성 레이어. Layer 3에서 노출된 서비스들의
    합성과 구성이 이 레이어에서 정의된다. 서비스들은 오케스트레이션 또는 구성법을 통해 플로우로 번들되고 따라서
    하나의 애플리케이션으로서 함께 작동한다. 이러한 애플리케이션들은 특정 사용 케이스와 비지니스프로세스를
    지원한다. IBM® WebSphere® Business Integration Modeler 또는 Websphere
    Application Developer Integration Edition 같은 시각적인 플로우 합성 툴은
    애플리케이션 플로우의 디자인에 사용될 수 있다.


    Layer 5: 액세스 또는 표현 레이어. 이 레이어는 이 글의 범위에서 벗어나지만 점점
    관련성이 커지고 있다. Web Services for Remote Portlets Version 2.0
    및 기타 기술 같이 애플리케이션 인터페이스 또는 표현 레벨에 웹 서비스를 활용하는 표준으로 집중되기 때문에
    다루기로 결정했다. 미래의 솔루션에 고려해야 할 미래형 레이어로 생각해도 좋다. SOA는 사용자 인터페이스와
    컴포넌트의 결합을 해제하고 액세스 채널에서 서비스 또는 서비스 합성 까지 엔드투엔드 솔루션을 제공한다.


    Level 6: 통합 (ESB). 이 레이어에서는 지능형 라우팅, 프로토콜 중개, 기타
    변형 메커니즘 (주로 ESB- 참고자료) 같은 신뢰성 있는
    기능들을 도입하여 서비스 통합을 실현한다. Web Services Description Language
    (WSDL)는 바인딩을 지정하는데 이는 서비스가 제공되는 위치를 포함하고 있다. 반면 ESB는 위치와 독립적인
    통합 메커니즘을 제공한다.


    Level 7: QoS. 이 레이어는 보안, 퍼포먼스, 가용성 같은 QoS를 모니터, 관리,
    유지에 필요한 기능을 제공한다. 이것은 SOA 애플리케이션의 상태를 감시하는 감지와 반응 메커니즘과 툴을
    통한 백그라운드 프로세스이다. SOA의 QoS를 구현하는 WS-Management, 기타 관련 프로토콜,
    표준의 구현들이 포함되어 있다.


    서비스 지향 모델링과
    아키텍쳐에 대한 접근 방법


    이 섹션에서는 탑-다운 방식의 비지니스주도형 방식과 기존 투자를 활용하는 바톰-업 방식을 결합하는 방법을
    설명하겠다.


    서비스 지향 모델링 방식은 SOA의 근본을 정의하는 모델링, 분석, 디자인 기술, 액티비티들을 제공한다.
    각 SOA 레이어의 요소들을 정의하고 각 레벨 마다 중요한 아키텍쳐 결정을 내리는 데 도움이 된다. 기존
    자산과 시스템을 활용하여 서비스 구분을 수행하는 작업 스트림과 결합된 탑-다운 방식의 비지니스주도적인
    방식의 서비스를 사용한다.


    이러한 방식으로, 고급 비지니스 프로세스 기능은 서비스를 위해 외부화된다. 고급 서비스를 구현하는 것을
    돕는 세분화된 서비스는 기존 레거시 기능을 검토하고 어댑터와 래퍼를 만드는 방법을 결정하거나 시스템 내에서
    잠겨진 기능을 외부화하기 위해 레거시를 컴포넌트화하여 구분된다.


    마지막으로, goal-service
    modeling
    을 사용하여 크로스 섹션 접근 방식을 통해 이미 확인된 후보 서비스들을 잘라 낼 수
    있다. 보다 중립적인 방법은 우선 탑-다운 방식을 수행하는 것이고 그런 다음 goal-service modeling
    이고 마지막은 기존 자산의 바톰-업 레거시 분석이다. 프로젝트를 관리 가능하고 현실적인 범주로 빠르게 잡아갈수록
    핵심 서비스에 집중된 가치를 더 빨리 실현할 수 있다.


    기능적 비지니스목표와 레거시 시스템에 대한 기존 투자의 활용을 결합하면 현대적인 SOA로 엔터프라이즈를
    마이그레이션하려는 조직에 놀라운 솔루션을 제공할 수 있다. 서비스 지향 통합을 통한 소프트웨어 애플리케이션의
    결합은 가능하다.


    서비스 지향 통합은 Enterprise Application Integration (EAI)의 진화이다.
    소유권이 있는 커넥션이 ESB 개념을 통해 표준 기반의 연결로 대체된다. ESB는 위치가 투명하고 라우팅,
    중개, 변형 기능이 유연하다.


    서비스 지향 모델링:
    서비스의 분석과 디자인


    지금까지 SOA를 설명했다. SOA를 구현하기 위해서는 SOA의 각 레이어에 대한 핵심 아키텍쳐 결정이
    이뤄져야 하고, 디자인은 비지니스와 제휴된 서비스들과 구성법을 반영해야 한다는 것을 설명했다.


    객체(objects) 라는 편안한 세계와는 달리, SOA의 경우 두 가지 관점을 고려해야 한다; 서비스
    소비자와 서비스 공급자에 대한 전망. 서비스 브로커는 현재 주류에 속하지 않아 나중에 다루겠다.


    SOA를 위한 디자인 전략은 웹 서비스 기반 방법에서 쓰이는 "바톰-업"으로 시작하지
    않는다. SOA는 보다 전략적이고 비지니스와 제휴되어 있다는 것을 기억해야 한다. 웹 서비스는 SOA의
    임시적인 구현이다. 중요한 많은 액티비티와 결정들이 통합 아키텍쳐 뿐만 아니라 엔터프라이즈와 애플리케이션
    아키텍쳐에 영향을 주고 있다. 여기에는 소비자와 공급자 라는 두 가지 핵심의 액티비티들이 포함된다.(그림
    4
    )


    그림 4: 서비스 지향 모델링의 액티비티

    SOA activities


    그림 4는 공급자와 소비자의 각 역할에 의해 전형적으로 수행되는
    액티비티들이다. 공급자의 액티비티는 소비자의 액티비티의 상위세트라는 것에 주목하라. (예를 들어, 공급자는
    서비스 구분, 범주 등과 관련되어 있다). 많은 경우 역할의 차이는 소비자가 원하는 서비스를 지정한다는
    사실에서 기인한다. 그리고 일단 찾고있는 서비스 스팩과 맞으면 필요한 서비스를 바인드하여 호출한다. 공급자는
    지원하고자 하는 서비스를 퍼블리시 해야 한다. 소비자가 요구하는 QoS의 관점에서 가장 중요한 것과 기능을
    고려해야 한다. 여기에는 소비자와 공급자가 SLA로 계약을 맺고 있어야 함을 함축하고 있다.


    위에 설명된 액티비티는 서비스 지향 모델링과 아키텍쳐 메소드 내에서의 흐름을 설명하고 있다.(그림
    5
    )


    그림 5: 서비스 지향 모델링과 아키텍쳐 메소드

    SOMA Method


    서비스 지향 모델링과 아키텍쳐의 프로세스는 세 가지 일반적인 단계로 구성된다: 구분, 서비스의 특성화와
    구현, 컴포넌트와 플로우(서비스 구성법).


    서비스 구분

    이 프로세스는 탑-다운, 바톰-업, 미들-아웃(middle-out) 기술로 도메인 디컴포지션, 기존 자산
    분석, goal-service modeling의 결합으로 구성되어 있다. 탑-다운 관점에서, 비지니스사용
    케이스의 청사진은 비지니스서비스를 위한 스팩을 제공한다. 이 탑-다운 프로세스는 도메인 디컴포지션(decomposition)이라고
    하는데, 이는 비지니스 도메인을 기능 영역과 하위 시스템으로 나눈다. 플로우 또는 프로세스 디컴포지션은
    프로세스, 하위 프로세스, 고급 비지니스 사용 케이스로 나누는 것이다. 이 사용 케이스들은 엔터프라이즈의
    끝에 노출된 비지니스 서비스에 적합하다. 비지니스 라인을 통해 엔터프라이즈 영역 안에 사용되어도 좋다.


    바톰-업 부분의 프로세스 또는 기존 시스템 분석에서, 기존 시스템들은 비지니스프로세스를
    지원하는 기저의 서비스 기능의 구현에 저렴한 비용의 솔루션을 제공할 수 있는 후보로서 선택된다. 이 프로세스에서
    레거시 애플리케이션과 패키지 애플리케이션에서 API, 트랜잭션, 모듈을 분석 및 활용할 수 있다. 어떤
    경우 레거시 시스템의 컴포넌트화는 서비스 기능을 지원하기위해 기존 자산들의 재모듈화에 필요하다.


    미들-아웃(middle-out) 뷰는 탑-다운 또는 바톰-업 서비스 구분 방식으로 잡히지
    않은 다른 서비스들을 확인하기 위한 goal-service modeling으로 구성된다. 서비스를 목표(goal)와
    하위 목표, 핵심 퍼포먼스 인디케이터, 메트릭스로 묶는다.


    서비스 구분 또는 범주화

    서비스가 구분될 때 이 액티비티가 시작된다. 서비스 구분을 서비스 계층으로 시작하는 것이 중요하다. 서비스의
    합성 또는 서비스의 프랙탈 속성을 반영해야 한다: 서비스는 세세하게 가려진 컴포넌트와 서비스들로 구성되어야
    한다. 구분은 합성과 레이어링을 결정할 때 도움이 될 뿐만 아니라 계층에 근거한 상호 의존적인 서비스들의
    구현을 조정한다. 또한 서비스의 '증식 증후군'을 막는데 도움이 된다. 세분화된 서비스들은 관리를 많이
    하지 않고도 정의, 디자인 전개될 수 있어 주요 퍼포먼스, 확장성, 관리가 수월하다. 무엇보다도 중요한
    것은 서비스 증식은 비지니스에 유용한 서비스를 제공하지 못한다.


    하위시스템 분석

    이 액티비티는 도메인 디컴포지션 동안 찾아낸 하위 시스템들을, 하위 시스템들 간 상호 의존성과 플로우를
    지정한다. 하위 시스템 인터페이스에 노출된 서비스로서 도메인 디컴포지션 동안 사용 케이스를 구분한다. 하위
    시스템 분석은 내부 작동을 나타내는 객체 모델 만들기와 서비스를 노출하고 이를 구현할 하위 시스템을 포함하는
    디자인으로 구성된다. "하위시스템"의 디자인 구조는 다음 액티비티에서 서비스를 구현하는
    크게 구분된 컴포넌트의 구현 구조로서 실현된다.


    컴포넌트 특성화

    서비스를 구현하는 상세한 컴포넌트들이 지정된다:


    • 데이터

    • 규칙

    • 서비스

    • 설정 가능한 프로파일

    • 변수


    메시징 및 이벤트 스팩과 관리 정의는 이 단계에서 발생한다.


    서비스 할당

    서비스 할당은 서비스들을 하위 시스템들로 할당하는 것으로 구성된다. 이 하위 시스템들은 퍼블리시된 기능을
    구현하는 엔터프라이즈 컴포넌트를 갖고 있다. 하위 시스템들은 엔터프라이즈 컴포넌트와 일대일 상관관계가 있다고
    보면 된다. 컴포넌트를 구현은 패턴을 사용하여 엔터프라이즈
    컴포넌트
    를 다음과 같은 요소들로 만들 때 발생한다:


    • 중개

    • Facade

    • 규칙 객체

    • 설정 가능한 프로파일

    • 팩토리


    서비스 할당은 SOA의 레이어로 실현하는 서비스와 컴포넌트를 할당하는 것으로 구성된다. SOA의 레이어로 컴포넌트와
    서비스를 할당하는 것은 핵심 아키텍쳐 디자인의 문서화와 결정을 필요로 하는 핵심 태스크이다. 애플리케이션 아키텍쳐
    뿐만 아니라 런타임 시 SOA 실현을 지원하는데 사용되는 작동 아키텍쳐와도 관련되어 있다.


    서비스 실현

    이 단계는 주어진 서비스를 구현하는 소프트웨어가 선택 또는 커스텀 구현된다는 것을 인식한다. 사용할 수
    있는 다른 옵션들에는 통합, 변형, 등록, 아웃소싱 등이 있다. 이 단계에서 주어진 서비스를 실현하는데
    어떤 레거시 시스템 모듈이 사용되는 지와 처음부터 구현되어야 할 서비스가 무엇인지 결정해야 한다. 기타
    구현 결정 사항으로는 보안, 관리, 서비스 모니터링 등이 있다.


    실제로는 모든 것을 부합하기 위해 노력이 들기 대문에 세 가지 흐름을 병렬로 수행하는 것을 권한다.


    탑-다운 도메인 디컴포지션 (프로세스 모델링과 디컴포지션, 변수 지향 분석, 정책 및 비지니스규칙 분석,
    도메인 스팩의 작동 모델링(문법과 다이어그램 사용))은 기존 자산의 바톰-업 분석과 병행하여 수행된다.
    프로젝트 뒤의 비지니스의도를 파악하고 비지니스의도 대로 서비스를 제휴하기 위해 goal-service
    modeling이 수행된다.


    결론

    이 글에서 서비스 지향 아키텍쳐의 기초, 레이어, 관련 유형의 아키텍쳐 결정을 설명했다. 서비스 지향 모델링의
    액티비티를 설명하고 서비스 소비자와 공급자 관점에서의 중요한 액티비티를 설명했다. 이 방식은 서비스 지향
    아키텍쳐의 세 가지 근본적인 측면(서비스, 플로우, 서비스를 구현하는 컴포넌트)을 결정하기 위한 분석 및
    디자인 액티비티에 대한 특정 가이드라인이다. 아키텍쳐 결정에 사용할 수 있는 템플릿도 설명했다.


    서비스 구분과 관련해서 탑-다운, 바톰-업, 크로스-섹션, goal-model analysis을 결합하는
    것의 중요성을 강조했다. 서비스 스팩과 실현의 주요 활동도 살펴보았다.


    다음 칼럼에서는 이 방식을 은행의 어카운트 관리에 적용하여 각 단계를 예시를 들어 설명할 것이다. 구분,
    특성화, 구현 외에도 서비스 지향 모델링 방식의 나머지 액티비티를 설명할 것이다. 전개, 모니터링, 관리
    등 전체 SOA의 수명 주기를 지원하는데 필요한 것들이다.


    감사의 말

    조언과 피드백을 아끼지 않은 많은 분들께 감사드립니다. (순서 없음): Luba Cherbakov, Kerrie
    Holley, George Galambos, Sugandh Mehta, David Janson, Shankar
    Kalyana, Ed Calunzinski, Abdul Allam, Peter Holm, Krishnan
    Ramachandran, Jenny Ang, Jonathan Adams, Sunil Dube, Ralph
    Wiest, Olaf Zimmerman, Emily Plachy, Kathy Yglesias-Reece,
    David Mott.


    참고자료































    차:





































































    Introduction
    서비스 지향 아키텍쳐: 개념 모델
    아키텍쳐 스타일과 원리
    SOA를 위한 아키텍쳐 템플릿
    서비스 지향 모델링과 아키텍쳐에 대한
    접근 방법
    서비스 지향 모델링: 서비스의 분석과
    디자인
    결론
    감사의 말
    참고자료
    필자소개
    기사에 대한 평가

















    관련
    dW 링크:




















    Elements
    of Service-oriented Analysis and Design
    Patterns:
    Service-oriented Architecture and Web Services
    dW
    newsletters











    US
    원문 읽기




















    필자소개

    Ali Arsanjani 박사는 IBM Global Services의 SOA and Web Services
    Center of Excellence의 아키텍트이다.



    Posted by 아름프로





    October 2004

    Discussion


     


    Enterprise JavaBeans(EJB)는 분산 컴포넌트를 작성하기 위해 소개되었다. 등장 시점에는 모든 이슈들과 CORBA의 복잡성을 해결하겠다는 의지를 가지고 있었다. EJB는 몇몇 메이저 버전업을 통하면서 J2EE의 핵심이 되었고, 많은 특징들을 갖춰 나갔다. 초창기부터 많은 개발자들은 EJB에 대한 호감을 가졌고, 큰 고민없이 EJB를 적용한 어플케이션을 개발해 나갔다. 결국 많은 개발자들은 EJB를 사용한 프로젝트가 원만하지 않을 경우, EJB에 책임을 돌리게 되었다.


     


    EJB 개발은 결코 쉽지 않으며, 릴리즈 될 때 마다 그 복잡함을 더해 갔다. EJB는 그 복잡성과 무거운 속성 때문에 코끼리에 비유되고 있다. 많은 개발자들은 EJB를 도넛에 입혀진 두터운 설탕 시럽처럼 느끼고 있다. 저탄수화물과 Atkins 다이어트에 열광하고 있는 시대에, EJB expert committee 또한 EJB 개발을 쉽고 간편하게 만들어야 함은 당연하다. EJB 3.0 expert committee는 JavaOne 2004에서 EJB 3.0 Specification의 첫번째 public draft를 발표했을 때 샘플 이미지를 배포 하였다.


     


    언뜻 보기에 EJB의 새로운 모델은 꽤 괜찮아 보였따. 이 글에서는 개발자들에게 어필하기 위해 EJB 3.0이 작은 사이즈의 멋진 외양으로 변신하려는 지 알아보련다. 다음 글에서는 EJB 3.0이 퍼시스턴스 모델을 어떻게 간소화 하려는 지 알아 보겠다.


     


    Cleaning up the Dirty Laundry


    EJB 3.0이 새로이 내놓을 것들을 다루기 전에, 현재의 EJB 모델에서 볼 수 있는 복잡성을 먼저 보도록 하자.





    • 현재 사용되는 EJB 모델은 컴포넌트 인터페이스와 불필요한 몇몇 callback 메소드 구현이 필요하다.


    • 컴포넌트 인터페이스는 EJBObject나 EJBLocalObject를 구현해야 하며, 적잖은 수의 불필요한 Exception 핸들링을 필요로 한다.


    • EJB 모델에 기반한 CMP는 개발과 관리에 더더욱 복잡하다. CMP는 몇가지 기본 원칙들을 준수하지 못하고 있다. 예를 들면 데이터베이스 시퀀스를 사용하는 프라이머리키를 정의하는 것에서 그렇다. 그리고 EJBQL은 아주 제한적이다.


    • EJB 컴포넌트는 그 자체가 OO 처럼 보이지 않는다. 상속이나 다형성을 사용하는데 있어 제약이 있기 때문이다.


    • EJB의 가장 큰 단점은 EJB 컨테이너 밖에서는 EJB 모듈을 테스트 할 수 없다는 점이다. 컨테이너에서의 디버깅 또한 개발자들에겐 공포이다.


    • EJB를 사용한다면 EJB를 룩업하고, 호출해야 하는 복잡한 구조를 알아야 한다. 즉 어플리케이션에서 EJB를 사용만 하기 위해서 최소한 JNDI 정도는 알아야 한다. 

     


    Simplifying Developers view


    최신 명세로 EJB를 개발한다면 HelloWorldEJB와 같은 간단한 EJB를 개발하는 것이 얼마나 어려운 것인가를 깨닫게 될 것이다. 최소한 두개의 인터페이스와 빈 클래스, 그리고 DD가 필요하다. 대부분의 개발자들은 자신이 왜 이 모든 것을 해야 하는 지 의아해 한다. Oracle JDeveloper, Eclipse 같은 IDE 들이나, Xdoclet은 개발자들을 좀 더 편하게 만들어준다. 그렇더라도 개발자들은 컨테이너에 EJB가 디플로이 될 수 있도록 클래스들을 컴파일 하고, DD를 패키징 하여야 한다. 


     


    EJB 3.0은 복잡성에 대응하기 위해 다음과 같이 하고 있다.




    • 인터페이스와 DD의 필요성을 제거하고, metadata annotation을 사용하여 컨테이너에 의해 생성될 수 있도록 한다.


    • EJB로 보통의 자바 클래스를 사용하고, EJB를 위한 보통의 비즈니스 인터페이스를 사용한다.

     


    Metadata Annotations


    EJB 3.0은 metadata annotaion에 큰 의존을 하고 있다. metadata annotaion은 JSR 175에서 표준화되었고, J2SE 5.0에서 채텍될 것이다. Annotaion은 XDoclet과 유사한 attribute 기반 프로그래밍의 한 종류이다. 사전 컴파일이 필요한 XDoclet과 달리, annotaion은 클래스 안에서 컴파일 시점에 자바 컴파일러에 의해 컴파일 된다. (@Retention이 설정되었을 때이다.) 개발자 관점에서 보자면, annotation은 public과 같은 제한자이며, 클래스, 필드, 메소드, 변수, 로컬변수, 생성자, enumeration, 패키지에서 사용될 수 있다. Annotation은 attribute를 자바 소스에 기술해서 사용한다. Attribute는 코드 생성, 문서화, 비즈니스 레베 보안 향상과 같은 특정 서비스나 런타임 시의 특정 비즈니스 로직 등이 있다. J2EE 1.5 (5.0)의 목표는 annotaion을 사용하여 개발 과정을 보다 간소화 하는 것이고, 결국에는 annotation이 필수 요소가 되도록 하는 것이다. Annotation은 다음처럼 @ 로 표시되어 진다.    

     @Author("Debu Panda") @Bean public class MySessionBean  

    EJB 3.0의 목표는 개발 과정을 간소화 하는 것이다. 이를 위해서 인터페이스와 같은 몇몇 산출물을 생성하기 위해 metadata annotation을 사용하고, DD 대신에 annotaion을 사용한다.


     


     


    Using POJOs and POJIs


    전통적으로, 자바빈즈와 인터페이스는 종종 POJO와 POJI로 간주된다. EJB 클래스는 이제 POJO와 POJI와 유사해 질 것이다. 홈 인터페이스와 같은 불필요한 객체는 곧 제거될 것이다.


     


    개발자는 javax.ejb 패키지에 있는 EJB 인터페이스(SessionBean, EntityBean, MessageDrivenBean)를 구현하거나, 빈 구현 클래스에 있는 annotaion을 사용해야 한다. 빈 클래스에 annotate를 달기 위해 Stateless, Stateful, MessageDriven, Entity 들 중 하나를 사용할 수 있다. 예를 들면 HelloWorld란 stateless EJB를 만든다면, 다음과 같이 EJB를 정의한다.

    @Remote @Stateless public class HelloWorldBean { 
    public String sayHello(String s) {
    System.out.println("Hello: "+s;
    }
    }

    리모트, 또는 로컬과 같은 EJB를 위한 인터페이스는 EJBOBject, 또는 EJBLOcalObject를 구현할 필요가 없다. EJB를 위한 비즈니스 인터페이스를 제공하거나, 빈 클래스에서 인터페이스를 구현하거나, 디플로이 하는 동안 생성되면 된다. 인터페이스는 Entity Bean에서는 옵션이지만, SessionBean과 MessageDrivenBean에서는 반드시 필요하다. 세션 빈에서 인터페이스를 구현하지 않는다면, 빈 인터페이스는 자동으로 생성할 것이다. 생성된 인터페이스는 빈 클래스에 사용된 annotation에 따라 로컬이거나, 리모트가 된다. 위의 코드를 보면, HelloWorld 빈을 위해 리모트 인터페이스를 생성하도록 @Remote 가 사용되었음을 알 수 있다. 필요할 경우, 리모트와 로컬 인터페이스를 모두 생성할 수 있다.  


     


    위의 예제를 보면, 인터페이스 정의와 콜백 메소드를 구현 등의 EJB 컴포넌트를 만들기 위한 일련의 작업들이 더 이상 개발자의 몫이 아님을 알 수 있다.


     


    생성된 인터페이스의 이름은 빈 구현 클래스의 이름으로과 연관되어 만들어진다. 생성된 인터페이스들은 개발자들에겐 더할 나위없이 적합한 것들이다. 하지만 Oracle JDeveloper와 같은 IDE에서 이러한 것들을 생성해 주는 것만큼의 효용을 볼 수는 없었다.   


     


    이번 Draft에선 클라이언트에서 EJB를 룩업하기 위해 필요한 것이 무엇인지가 명확하지 않다. 그리고 EJB를 호출하기 위해 필요한 인터페이스들을 어떻게 해야 할 지에 관해서도 막연하기만 하다. 아래 열거한 이유들 때문에 난 생성된 인터페이스를 사용하는 것을 지지하지 않는다. 






    • 생성된 인터페이스의 이름은 빈 이름으로부터 생성된다.


    • EJB에서 인터페이스로 내보내고 싶지 않은 어떤 메소드가 있을 수 있지만, 기본적으로 모든 메소드들이 생성된 인터페이스에 내보내 질 것이다.


    • 클라이언트 측에서는 EJB를 호출하기 위한 EJB가 필요하다.

    Removing need for Callback methods


     


    EJB 2.1과 그 이전 릴리스에서는 몇몇 라이프 사이클과 관련한 메소드의 구현이 반드시 필요했다. 라이프 사이클 메소드로는 ejbPassivate, ejbActivate, ejbLoad, ejbStore 등이 있다. 이런 것들이 필요없는 EJB들도 모두 구현해야 했다. 예를 들면 무상태 세션 빈에서 ejbPassivate는 필요가 없다. 빈 클래스에서 이 메소드를 구현하기 전까지는 전혀 사용되지 않는 것이다. 그래서 EJB 3.0에서 이러한 라이프 사이클 메소드들은 옵션으로 되어 있다. EJB에서 어떤 콜백 메소드를 구현했을 때에만 컨테이너가 그 메소드를 호출할 것이다.


     


    단 하나의 예외는 Stateful 세션 빈의 ejbRemove 메소드이다. Stateful 세션빈의 비즈니스 메소드에서 Remove annotation을 사용하여 표시한다. Remove annotation은 표시된 메소드를 정상, 또는 비정상 종료한 후에 Stateful 세션빈이 제거될 수 있도록 컨테이너에게 알려주는 역할을 한다. 예를 들면 Stateful 세션빈 인스턴스의 checkOut 메소드가 실행된 후 제거될 수 있도록 다음과 같이 기술하면 된다.

    @Stateful public class Cart { 
    ... ...
    @Remove public void checkOut() {
    ...
    }
    }

    Annotations vs. deployment descriptors


    상기한 바와 같이, EJB에서 DD 대신에 annotation이 쓰이게 될 것이다. DD에서 각 attribute의 기본 값은 설정되어 있으며, 개발자들은 기본 값 이외의 다른 값을 필요로 하지 않는 한 특별히 기술하지 않았다. 이것들은 빈 클래스 자체에서 annotation을 사용하여 기술될 것이다. EJB 3.0 스펙에는 개발자가 사용할 수 있는 metadata annotaion set을 정의되어 있다. metadata annotation에는 bean type, type of interfaces, resource references, transaction attributes, security 등이 있다. 간단한 예로 특정 EJB를 위한 resource reference를 쓰고 싶다면, 다음과 같이 한다.



    @Resource(name="jdbc/OracleDS", resourceType="javax.sql.DataSource")


    Oracle, BEA, IBM 과 같은 J2EE 벤더들은 벤터 자체의 DD에서 쓰이는 attribute를 위한 annotaion 들을 추가할 것이다. 그리고 개발자들은 DD를 사용하지 않기 위해서 추가된 annotation들을 사용할 것이다. 개발자들에겐 아주 흥미있는 소식이 될 것이다. 왜냐하면 그들이 꽤나 귀찮아 하던 xml 디스크립터들이 사라지기 때문이다. 하지만 몇가지 문제점은 있다. Annotation을 받아 들이기 전에 좀 더 주의할 필요가 있다.




    • 아무 곳에서나 구동할 수 있는 장점이 퇴색할 수 있다. EJB가 벤더에 종속된 DD를 사용한다면, 다른 벤더에 적용하기 위해 EJB를 컴파일하고 패키징하는 작업을 새로 해주어야만 한다. 


    • DD는 EJB 모듈에 대한 정보를 제공한다. 그래서 EJB 내부를 들여다 보지 않아도 assembler와 deployer에게 EJB 모듈에 관한 정보를 알 수 있도록 해준다. DD는 각 디플로이먼트 단위로 필요하다. 만약 descriptor가 사용될 수 없거나, 디플로이먼트가 끝날 때까지 생성되지 않는다면 개발자들에겐 또 하나의 난관이 될 것이다.


    • DD는 EJB 모듈에서 툴에 의해 EJB를 정의하도록 사용되어져 왔다. 그래서 DD는 다른 컨테이너로의 전환에 아주 유용하게 사용되어져 왔다. EJB 3.0도 DD에서 annotation을 오버라이드 할 수 있는 방법을 제공한다. 하지만 annotation을 오버라이딩하는 부분은 Draft에서 빠져있는 상태이다.  

    DD를 제거하게 된다면 새로운 개발자들에겐 보다 쉽게 느껴질 것이다. 그러나 주의하지 않는다면 관리적인 측면에서 새로운 암초로 등장할 수도 있을 것이다.


     


     


    Simplifying Container Managed Persistence


    CMP 엔티티 빈은 EJB 3.0에서 개발자들을 감탄시킬 수 있을 만큼의 대대적인 정비가 이루어 지고 있다. 복잡하고 무거운 엔티티 빈을 싫어하는 개발자들은 TopLink나 Hibernate 같은 Persistence 프레임웍은 J2EE 어플리케이션을 위한 퍼시스턴스 프레임웍을 애용하고 있다. EJB 3.0은 CMP를 간편하게 하기 위해 TopLink나 Hibernate 같은 경량 퍼시스턴스 모델을 적용하고 있어 개발자들을 기대하게 만들고 있다. 엔티티 빈을 위한 플랜을 훑어 보자. 그리고 다른 아티클에서 퍼시스턴스 향상에 관한 세부적인 내용을 다시 다루겠다.  


     


    엔티티 빈은 POJO로 다시 태어났다. 그리고 엔티티 빈에 필수였던 컴포넌트 인터페이스는 필요없다. 이제 엔티티 빈은 상속과 다형성을 지원하는 순수한 오브젝트의 모습이 될 것이다.


     


    Following is the source code for an entity bean:

    @Entity public class Employee { 
    private Long empNo;
    private String empName;
    private Address address;
    private Hashmap projects = new Hashmap();
    private Double salary;

    @Id(generate=SEQUENCE) public Long getEmpNo() {
    return empNo;
    }

    protected void setEmpNo(Long empNo) {
    this.empNo = empNo;
    }


    public String getEmpName() {
    return EmpName;
    }
     public void setEmpName(String EmpName) { 
    this.EmpName = EmpName;
    }
     @Dependent public Address getAddress() { 
    return address;
    }
     public void setAddress(Address address) { 
    this.address = address;
    }
     public Set getProjects() { 
    return projects;
    }
     public void setProjects(Set projects) { 
    this.projects = projects;
    }
     public Double getSalary() { 
    return salary;
    }
     public void setSalary(Double salary) { 
    this.salary = salary;
    }
    ....
    }

    코드를 보면, 빈 클래스가 보통의 엔티티 빈과 같은 추상 클래스가 아닌 보통 클래스란 것을 알 수 있을 것이다.  


     


    EJB QL에서 쿼리 능력 향상, 엔티티 빈에서의 SQL 질의 지원 등 몇가지 향상된 기능이 추가 되었다. 새로운 EntityManager API(Hibernate, TopLink의 Session API의 단순화된 버전과 유사)는 엔티티 빈을 조작하기 위해 제안되었다. (예: creattion, removal, finding of entity beans)


     


    다음에 나올 아티클에서 제안된 CMP 엔티티 빈에 관해 더 상세히 보겠다.


     


     


    Simplifying Client View for EJBs


    EJB를 사용하는 건 EJB가 어플리케이션에 들어 있다 하더라도 매우 복잡하다. J2EE 1.4와 EJB 3.0 스펙은 EJB를 바라보는 클라이언트 측을 보다 더 단순화시켜 놓았다.


     


    지금은 EJB를 사용하고 싶을 경우 DD에서 ejb-ref나 ejb-local-ref를 정의해 놓아야 한다. 예를 들어 HelloWorld EJB를 호출하고 싶다면, 보통 다음과 같은 방법으로 EJB를 호출하게 된다.


     


    먼저 EJB 레퍼런스를 DD에 등록한다.

     
    HelloWorldEJB
    Session
    hello.HelloWorldHome
    hello.HelloWorld

    다음 처럼 EJB를 lookup 한다. 빈 인스턴스의 EJB 룩업과 생성을 위한 예외를 명시적으로 처리해 주어야 한다.

    try { 
    Context context = new InitialContext();
    HelloWorldHome helloHome =
    (HelloWorld)PortableRemoteObject.narrow(
    context.lookup("java:comp/env/ejb/HelloWorldEJB"),
    HelloWorldHome.class);
    HelloWorld hello = helloHome.create();
    ....
    } catch(RemoteException e) {
    System.err.println("System/communication error: " + e.getMessage());
    } catch(NamingException e) {
    System.err.println("Communication error: " + e.getMessage());
    } catch(CreateException e) {
    System.err.println("Error creating EJB instance: " + e.getMessage());
    }

    다른 방법으로 EJB 3.0은 EJB를 룩업하고 호출할 수 있는 setter injection을 쓰는 방안을 제공한다.


     


    다음은 다른 EJB에서 setter injection을 사용하여 HelloWorldEJB를 호출하는 방법이다.

    @Inject private void setSessionContext(SessionContext ctx) { 
    this.ctx = ctx
    }
    ...
    myHello = (HelloWorld)ctx.lookup("java:comp/env/ejb/HelloWorldEJB");

    코드를 보면 setSessionContext 메소드에 @Inject가 붙어 있다. @Inject는 이 메소드가 dependency injection에 사용됨을 나타내는 것이다. @Inject 처리된 메소드는 EJB의 있는 메소드가 호출되기 전 EJBContext를 세팅할 때 호출된다.


     


    HelloWorld 세션빈을 inject 하기 위해서 @EJB public HelloWorld myHello 처럼 해도 된다. 이렇게 하면 HelloWorld 빈 인스턴스가 myHello에 inject 된다.


     


    dependency injection은 DataSource, JMS, Mail, Web Service 같은 타입의 environment나 resource reference 를 룩업하기 위해 사용할 수도 있다.


     


     


    Testability Usability Outside Container


    EJB 개발자들의 가장 주요한 관심사는 EJB 개발이 복잡하다는 것 뿐만 아니라, 테스트가 쉽지 않다는 점에도 있다. EJB 컨테이너는 EJB를 개발하고 테스트 하는데 반드시 필요하다. 그래서 개발자는 테스트를 수행할 배포 플랫폼에 익숙해야만 한다. 이 부분은 많은 엔터프라이즈 개발자들에게 주요한 이슈가 아닐 수도 있다. 그렇지만 다양한 벤더를 지원해야 하는 ISV들에는 이슈가 된다. 그들은 다양한 환경에서의 동작을 보증하기 위해 그들의 EJB 테스팅을 수행해야 하기 때문이다. EJB 3.0 스펙은 컨테이너 외부에서의 테스팅 기능 제공을 약속하고 있다. 그러나 아직 Draft 스펙에는 누락되어 있다.


     


     


    Conclusion


    packing, assembly, API 등 많은 정보가 누락되긴 했지만, EJB 3.0에 담긴 제안들은 엔터프라이즈 자바 개발자들에겐 매우 환영할 만한 것들이다. 제안들로 인해 개발자들에게 부여되었던 복잡성을 컨테이너 벤더들에게 넘겨버리게 되므로 확실히 단순화 될 것이다. 컨테이너 벤더들이 이것들을 어떻게 구현할지, 엔터프라이즈 어플리케이션을 개발할 때 EJB 3.0을 보다 수월하게 할 수 있는 방법들을 볼 수 있게 될 것이다.  


     


    References and further reading



     


    Author Bio


    Debu Panda is a principal product manager of Oracle Application Server development team, where he focuses his efforts on the EJB container and Transaction Manager. He has more than 13 years of experience in the IT industry and has published articles in several magazines and has presented at many technology conferences. His J2EE-focused weblog can be found at http://radio.weblogs.com/0135826/.



    PRINTER FRIENDLY VERSION 
     

    Posted by 아름프로
    Article

    NetBeans IDE 4.1

























    By Qusay H. Mahmoud, February 2005







    An Integrated Development Environment (IDE) is a necessity for enterprise developers who want to have all their productivity tools under one umbrella. An IDE enables the developer to move from one phase of application development to the next without having to worry about manual management of source code or tool interfaces. With so many IDEs available on the market today, it has become a time-consuming task to decide on and choose one. Ideally, you should be looking for an IDE that maximizes your productivity: easy to use, fun to work with, enables you to get the work done, and has out-of-the-box support for open standards and technologies.



    The NetBeans IDE 4.1 Early Access 2 (EA2), which was released in January 2005, includes Java 2 Platform, Enterprise Edition (J2EE) and web services development capabilities. This new release allows developers to not only develop applications in the web tier but also includes Enterprise JavaBeans (EJBs) and web service development capabilities. NetBeans IDE 4.1 is a single platform with out-of-the-box development capabilities and support for enterprise (J2EE 1.4) applications and web services, mobile/wireless Java 2 Platform, Micro Edition (J2ME) applications and services and desktop Java 2 Platform, Standard Edition (J2SE) applications.













    NetBeans IDE








    The NetBeans IDE, which is sponsored by Sun Microsystems, is a free and open source IDE that enables you to develop J2EE 1.4 applications and web services, mobile/wireless applications and services, and J2SE desktop applications. Using the NetBeans IDE, developers get their work done in a fun development environment that enables them to concentrate on the business logic of their applications. It provides productivity tools, and supports refactoring and integrated debugging, that simplify the work of Java technology developers.



    NetBeans IDE 4.1 (EA2) supports the development of J2EE 1.4 applications and web services, and their deployment on the freely available Sun Java System Application Server 8.1 Platform Edition (Application Server PE 8) and Tomcat. Application Server PE 8 is the first compatible "production grade" application server implementation of the J2EE 1.4 specification, and it is free for development and deployment. This release of NetBeans IDE 4.1 with support for J2EE 1.4 will make a big difference for enterprise applications developers as it provides them with out-of-the-box support for J2EE 1.4, which helps them increase their productivity.



    In this release (4.1), J2EE EJBs and web services are first class citizens. The IDE features ease of use, and the overall design of the IDE keeps the tools you need the most immediately at your fingertips. Developers get everything they need to develop J2EE 1.4 enterprise applications and web services with a single download.



    The NetBeans IDE 4.1 (EA2) allows developers to:



    • Create J2EE applications, automatically add EJB modules and web modules, and deploy the applications

    • Create EJBs from existing source, from scratch, or from an existing database

    • Automatically generate EJB business methods, database calls, and calls to EJBs

    • Create a web module for deployment to the freely available Application Server PE 8 or Tomcat

    • Add multiple source folders to an EJB module or web module, and create unit tests as part of the project

    • Edit deployment descriptors in a graphical editor that is automatically synchronized with the underlying XML

    • Create, register, and test web services

    • Import your existing J2EE projects

    • Validate your applications with the J2EE Verifier

    • Visually configure your EJBs, web Services and web components



    Note that the NetBeans IDE is not only meant to be used by advanced developers, but also by beginners who wish to learn about J2EE and web services technologies. The NetBeans IDE 4.1 allows you to try out the sample applications to learn and understand the J2EE technology and web services.



    The IDE increases the productivity of developers by guiding them through the development process, and automatically building the underlying J2EE infrastructure. The distribution provides several great quick starts and tutorials that enable beginners to get up to speed quickly. In addition, it comes with numerous samples of J2EE applications that can be easily accessed from within the IDE, as well as contributions from the J2EE Java BluePrints catalog.




    NetBeans IDE 4.1 (EA2) Key Features








    The NetBeans IDE 4.1 (EA2) features significant new development capabilities for J2EE 1.4, including EJB components and web services. It has over 15 new modules for developing J2EE 1.4 applications and services. The three key features are:



    Creating EJB Modules, Session Beans, Entity Beans, and Message Driven Beans


    • The NetBeans IDE 4.1 guides the user through the process to easily learn how to write an EJB as well as deploy, package, and test applications.

    • A GUI is available to select an EJB and perform tasks such as adding business methods and editing deployment descriptors.

    • All EJB infrastructure methods are generated automatically and are hidden in a power code fold.

    • The resulting EJB module can be easily added to a J2EE application.

    • Entity beans can be created using an existing database schema.

    • The NetBeans project structure matches J2EE Java BluePrints standards and relies on the Ant open standard for the build system.



    Calling EJBs


    • Using the "Call EJB" feature from within a Servlet, JSP, or web service saves the user the headache of writing the JNDI lookup code and required exception handling. It will even work with your existing ServiceLocator class.



    Develop and Test Web Services


    • Developers can create, modify, package, deploy, and test web services from the IDE.

    • Web services can be created from scratch, existing code, and/or WSDL.

    • Once created, the web service can be registered with the IDE, which creates an internal client for testing the web services.

    • NetBeans also supports creating web service client code from existing WSDL.




    Getting Started








    The NetBeans IDE 4.1 is available for the Solaris Operating System, Microsoft Windows, and Linux. It runs on J2SE SDK 1.4.2 as well as J2SE SDK 5.0. I recommend that you download the NetBeans IDE 4.1 EA2 + AS 8.1 Bundle Installer.




    Sample Projects








    If you wish to experiment with some J2EE projects, chose File -> New Project then expand the Samples folder. In addition, the IDE includes samples from the Java BluePrints Solution Catalog as shown in Figure 2. You can select one of these samples and install it.












    Figure 2: Java BluePrints Solution Catalog


    Figure 2: Java BluePrints Solution Catalog




    Once you select a sample project, press F6 to run the project. Figure 3 shows a sample run.












    Figure 3: Sample Run


    Figure 3: Sample Run




    You can easily develop new J2EE applications and web services. To learn how to create J2EE applications, EJB modules, web modules, and to call, deploy, and test applications, please see the Quick Start Guide for J2EE Applications, and Exposing and Consuming Web Services, which provide you with a step-by-step tutorial on how to get started with J2EE and web services development.



    NetBeans.org Needs You








    The NetBeans IDE 4.1 (EA2) currently supports deployment on the Application Server PE 8 and Tomcat, but netbeans.org needs your support in order to ensure that the majority of J2EE 1.4 compliant application servers can be used as both development and deployment targets from the NetBeans IDE.



    If you are interested in supporting this effort, you can download the source code that implements the support for J2EE 1.4 in the NetBeans IDE 1.4 (EA2) from the NetBeans.org J2EE page.



    You can subscribe to a mailing list by sending a blank email to nbj2ee-subscribe@netbeans.org, and you can send questions and feedback to nbusers@netbeans.org.



    If you are a serious Java developer looking for an IDE with out-of-the-box support for J2EE and web services, that is easy to install, simple to learn and use, fun to work with, and enables you to get the job done, then try the NetBeans IDE 4.1 early access. Download it today and see for yourself. Learning about J2EE and building JEE applications and web services has never been easier.



    For More Information






    Posted by 아름프로





    Getting around JSF: The role of JSP


    Learn how to use JavaServer Pages with JavaServer Faces





    Summary


    In this excerpt from JavaServer Faces in Action (Manning, November 2004), author Kito Mann explains how JavaServer Pages fits with JavaServer Faces. (1,800 words; December 13, 2004)


    By Kito D. Mann








    JavaServer Faces (JSF) applications require some sort of display technology, such as JavaServer Pages. One of the cool things about JSP is the ability to extend it with custom tags. A custom tag is a special XML element backed by Java code, that can be used in addition to standard JSP elements or HTML elements. A custom tag can do almost anything: display the value of variables, parse XML, conditionally display parts of a page, access a database, and so on (whether or not anyone should be doing all of these things with JSP tags is a question for another day...). Their main purpose is to keep Java code out of the pages and allow frontend developers to use simple, familiar tags instead. A group of related custom tags forms a tag library.


    JSF is integrated with JSP using custom tags. All of the JSF tags we've shown so far in this book —<h:inputText>, <h:outputText>, <h:form>, <f:view>, and so on—are custom tags. JSF implementations must support JSP with custom tag libraries that provide access to all of the standard components, renderers, validators, and converters. These libraries (included in the JSF JARs) are listed in the table below.


    JSF custom tag libraries

    URINameCommon prefixDescription
    http://java.sun.com/jsf/coreCorefContains tags that are independent of a particular render kit (like <f:view>, <validator>, and so on)
    http://java.sun.com/jsf/htmlHTMLhContains tags for all of the standard components and the HTML render kit


    All of the tags in these libraries must be named and implemented in a specific manner. This way, your JSP-based applications are guaranteed to be portable across different JSF implementations. Most IDEs can be used with JSP.


    For the most part, using JSF with JSP is just a matter of using the JSF custom tag libraries. There are, however, some nuances you should be aware of, like using JSP includes.

    Using JSP includes

    One of JSP's key features is the ability to integrate content from multiple JSPs into a single page. This is often used for fun tasks like including a header or a footer. JSP supports two types of includes: dynamic and static. Dynamic includes (performed with the <jsp:include> tag or the JSTL <c:import> tag) access a resource at runtime. In this case, control is forwarded to the included JSP. The response from the included JSP is merged with the response sent back from the calling page. When changes are made to a dynamically included page, they automatically show up in all calling pages.


    Static includes integrate the resource at translation time—when the page is morphed into Java code and compiled. The contents of the source page are essentially copied into the calling page. Changes made to the included content generally aren't automatically noticed by calling pages because they already have their own copy of the content. They have to be "touched" so that they can be recompiled with the new content. (JSP 2.0's implicit includes, which can be configured in web.xml, are processed like static includes.)


    JSF works with both types of JSP includes. For dynamic includes, there are two requirements:


    1. Included pages must be enclosed in a JSF <f:subview> core tag. This tag can either be in the included page or around the include statement.


    2. All template text and non-JSF tags inside included pages should be enclosed with the JSF <f:verbatimgt; core tag.


    So, let's say we had the following snippet in a JSP page:



    <f:view>


    ...


    <jsp:include page="foo.jsp"/>


    ...


    </f:view>



    Foo.jsp might look like this:



    <f:subview>


       <h:outputText value="heyah!"/>


       ...


          <f:verbatim>


          <b>Template text.</b>


          <customtag:dothis/>


       </f:verbatim>


    </f:subview>





    As you can see, the entire included page is enclosed in an <f:subview> tag, and all non-JSF tags and template text are enclosed in an <f:verbatim> tag. Alternatively, we could move the <f:subview> tag into the first page, around the <jsp:include> tag.


    Using a static include is much simpler. There are no restrictions—you don't even have to use the <f:subview> tag.


    In the last example, we showed a fictitious custom tag, <customtag:dothis>, that performs some random task. This underscores an important point: you can use JSF with other JSP custom tags.


    Using JSF with JSTL and other JSP custom tags

    All of this talk about JSF's custom tag libraries is nice, but what if you have your own custom tags, or third-party ones? Or what if you're using the JSP Standard Tag Library (JSTL), which is a set of standard tags that do all of those neat things we just mentioned? For the most part, you can mix and match them with JSF tags. Faces tags can be nested within other tags and vice versa. Some products, like IBM's WebSphere Application Developer, encourage this approach, while others, like Sun's Java Creator Studio, opt for a pure JSF approach. Oracle's JDeveloper on the other hand, lets you mix and match, but also encourages the pure JSF approach.


    Note: Whenever you nest a JSF tag inside a non-JSF custom tag, you must assign the JSF tag a component identifier.


    Because JSTL is standard and familiar to many, we'll use it to demonstrate the use of JSF with custom tags. (If you're thirsty for general information on JSTL, check out Shawn Bayern's excellent book, JSTL in Action.) Let's start with the simple example (shown in Listing 1) that mixes and matches some JSTL tags with JSF tags. This code imports both JSF tag libraries and the core JSTL tag libraries.


    Listing 1. Mixing JSTL tags with JSF tags



    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>


    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>


    <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>





    <html>


    <head>


       <title>JSF in Action: JSTL Example 1 - Mixing JSF with other custom tags


       </title>


    </head>


    <body bgcolor="#FFFFFF">





       <f:view>


          <h1>


             <h:outputText value="Example of using JSF tags with other custom tags"/>


          </h1>


          <p>


             <b>


                <c:out value="Here's the value of your web.xml (don't do this at home):"/>


             </b>


             <blockquote>


                <f:verbatim>


                   <c:import url="WEB-INF/web.xml"/>


                </f:verbatim>


             </blockquote>


          </p>


       </f:view>





    </body>


    </html></code>



    In this example, both JSTL and JSF tags are nested within the JSF <f:view> tag, which defines the start of the JSF component tree. The example uses the JSF HtmlOutputText component (<h:outputText>) and the JSTL <c:out> tag to display text. A JSTL <c:import> tag includes the system's web.xml file in the page (this isn't exactly something you want to share with others, so don't do this on a real server). Because web.xml is an XML file, the <c:import> tag is nested in an <f:verbatim> tag, which is a JSF UIOutput component whose renderer escapes the XML so it can be displayed normally in an HTML page. This example doesn't do much, but it does demonstrate the ability to use different tags on the same page together.


    Note that we nested a JSTL tag inside the JSF <f:verbatim> tag. In general, it's easier to nest JSF tags inside other tags than vice versa. As a matter of fact, any component that displays its own children, like HtmlDataTable and HtmlPanelGrid, requires that any template text or nested tags be within an <f:verbatim> tag.


    What's great about using JSTL tags with JSF tags is that they both use similar expression languages to reference objects (this is true for JSP 2.0's expression language as well). This allows you to easily share data between JSTL and JSF tags in an intuitive manner. To illustrate this point, let's look at another example that allows the user to input a number into an HtmlInputText control and then uses that value to display a string repeatedly with a JSTL <c:forEach> tag. This code is shown in Listing 2.


    Listing 2. Using JSF and JSTL tags together with the same backing bean



    ...


    <f:view>


       <jsp:useBean class="org.jia.examples.TestForm" id="exampleBean" scope="session"/>





       <h1>


          <h:outputText value="Example of using JSF and JSTL expression languages"/>


       </h1>





       <h:form>


          <h:outputLabel for="inputInt">


             <h:outputText value="How many times do you want to repeat the Oracle's prophecy?"/>


          </h:outputLabel>





          <h:inputText id="inputInt" value="#{sessionScope.exampleBean.number}"/>


          <h:commandButton value="Go!"/>


          <p>


             <c:if test="${sessionScope.exampleBean.number > 0}">


                <c:forEach begin="0" end="${sessionScope.exampleBean.number - 1}" var="count">


                   Queen Tracey will achieve world domination.<br>


                </c:forEach>


             </c:if>


          </p>


       </h:form>


    ...


    </f:view>


    ...




    Warning: If you're using JSP or JSTL expressions with managed beans, you need to ensure that the beans have been created first, either by a JSF expression, Java code, or your own custom tag. This is because these older expression languages don't know about JSF's Managed Bean Creation facility.


    This listing references a JavaBean, called exampleBean that has a number property of type int. An HtmlInputText component is used to update the value of the bean's property based on user input. When the user clicks the Go! button (an HtmlCommandButton component), the number property is updated and the page is redisplayed. When this happens, the JSTL <c:forEach> tag repeats the text displayed by a JSTL <c:out> tag exampleBean.number times. The <c:forEach> tag only executes if exampleBean.number is greater than 0; this is controlled by a JSTL <c:if> tag.


    You cannot use JSF component tags inside tags that iterate over their body, like the JSTL <c:forEach> tag. The recommended workaround is to use the HtmlDataTable component or another component iterates over a dataset or collection.


    In this example, there are no JSF components nested inside the JSTL <c:if> tag. But what happens if a component is displayed once and then hidden by a conditional tag like <c:if> when the page is redisplayed? The first time the component is displayed, it will be added to the view. The second time, if the <c:if> tag doesn't display the component, JSF will delete it from the view. This means that any input controls will lose their local values, and that you won't be able to reference these components (via client identifiers or in code). As an example, take a look at Listing 3, which is from the same page as Listing 2.


    Listing 3. Conditionally displaying JSF components with JSTL tags


    ...


    <h:form>


       <h:outputText value="If you entered a number greater than 10,


          two input controls will display below."/>


       <p>


          <c:if test="${sessionScope.exampleBean.number > 10}">


             <h:outputLabel id="inputStringLabel"for="inputString">


                <h:outputText id="outputStringLabel" value="Enter in your string.


                   JSF will remember the value unless this control is hidden."/>


                </h:outputLabel>


                <h:inputText id="inputString"/>


                <h:commandButton value="Go!"/>


          </c:if>


       </p>


    </h:form>


    ...



    The JSTL <c:if> tag will execute its body if the value of exampleBean.number is greater than 10. If the body is executed, then all of the nested components will be added to the view and displayed. If not, the components will be removed (if they have been added previously). This is shown graphically in Figure 1. If you control visibility of components with JSTL conditional tags (or other custom tags), the components will be removed from the view if they're not displayed. This means that the components will forget their local values as well.








    Figure 1. The JSTL <c:if> tag will execute its body if the value of exampleBean.number is greater than 10. Click on thumbnail to view full-sized image.



    Figure 2 shows the output of the JSP page used for Listings 2 and 3. The value of the input field at the top (an HtmlInputText component) is wired to the exampleBean.number backing bean property, which is used by the JSTL <c:forEach> tag to display a string exampleBean.number times. In the bottom portion of the page, a JSTL <c:if> tag shows a form with JSF components if exampleBean.number is greater than 10. Otherwise, the components will not be displayed, and they are removed from the view (and the input control will lose its value).








    Figure 2. The output of the JSP page shown in Listings 2 and 3. Click on thumbnail to view full-sized image.



    You can achieve the same effect as the code in Listing 3 by placing these components in an HtmlPanelGroup and setting its rendered property to equal the same expression. An HtmlPanelGroup is used as a container for multiple components. Here's an example:



    <h:panelGroup rendered="#{sessionScope.exampleBean.number > 10}">


       <h:outputLabel id="inputStringLabel2"for="inputString">


          <h:outputText id="outputStringLabel2" value="Enter in your string. JSF


             will remember the value."/>


          </h:outputLabel>


       <h:inputText id="inputString2"/>


       <h:commandButton value="Go!"/>


    </h:panelGroup>



    If exampleBean.number is greater than 10, this panel becomes visible. In this case, the components won't be deleted if they're not displayed. This is a good example of the types of things you can do with pure JSF tags without JSTL.


    Tip: Even though custom tags like the ones provided by the JSTL provide a lot of functionality, if you're developing from scratch (or refactoring), you should first look to see if you can implement the desired behavior with standard JSF components. Using good components and well-designed backing beans, you can usually avoid the need for many JSTL tags in your pages. You can hide or display entire panels and do all sorts of powerful things with standard JSF.


    Here are a few other interoperability constraints for using JSF tags with JSTL internationalization and formatting tags:


    • Use of <fmt:parseDate> and <fmt:parseNumber> is not recommended. You should use the HtmlInputText component with a DateTime or Number converter.


    • The <fmt:requestEncoding> tag, which is used to determine or specify the character encoding for the page, should not be used. Usually, JSF handles this automatically, and if you need to force a particular encoding, you should use the JSP page directive: <%page contentType="[contenttype];[charset]"%>.


    • The <fmt:setLocale> tag shouldn't be used either. Because it doesn't know about JSF, it may cause your JSTL tags to use one locale and your JSF components may use another, which is a recipe for disaster. Instead, you should use JSF's internationalization features. To control the locale for a particular page, use the locale property of the UIViewRoot component. JSF's internationalization features work for both JSF and JSTL.


    Combining JSF with the JSTL can be quite powerful. Custom tags that you have developed or obtained from third parties should work with JSF as well as the JSTL tags we've shown here. In general, though, you should stick with JSF tags when possible.



    About the author

    Kito D. Mann is a consultant specializing in enterprise architecture, mentoring, and development. A programmer since the tender age of 12, he has written several articles on Java-related technologies, and also speaks at user groups and conferences. He has consulted with several Fortune 500 companies and has been the chief architect of an educational application service provider. Mann is also the founder of the JSF Central community Website, and a member of the JSF 1.2 and JSP 2.1 expert groups. He holds a B.A. in computer science from Johns Hopkins University and lives in Stamford, Connecticut, with his wife, four cats, and two parrots. In his spare time, he enjoys making incomplete compositions with electronic music equipment.





    Posted by 아름프로





    Service-context propagation over RMI


    A lightweight design approach for supporting transparent service-context propagation over RMI





    Summary


    CORBA supports the passing of service-context information implicitly with requests and replies over remote object interface invocation. Without instrumenting the underlying protocol, Java RMI (Remote Method Invocation) can't easily support transparent service-context propagation. This article describes a simple and efficient design approach for supporting such capability over RMI. In building RMI-based distributed applications, such an approach can serve as a basic building block for implementing infrastructure-level functions, such as transaction, security, and replication. (3,000 words; January 17, 2005)


    By Wenbo Zhu








    CORBA's service context provides an efficient and elegant design and implementation approach for building distributed systems. Java RMI (Remote Method Invocation) can't easily support transparent service-context propagation without instrumenting the underlying protocol. This article describes a generic lightweight solution for supporting transparent and protocol-independent service-context propagation over RMI. Reflection-based techniques are used to emulate what's normally seen in protocol-specific service-context implementations.



    This article introduces you to a real-world solution and the related distributed-computing design concept, as well as Java reflection techniques. We start with an overview of the CORBA object request broker (ORB) interceptor and the service-context design architecture. Then a concrete implementation example describes the actual solution and demonstrates how RMI invocation is actually massaged to propagate service-context data, such as transaction context, which is usually offered through the IIOP (Internet Inter-ORB Protocol) layer. Lastly, performance considerations are discussed.

    Interceptor and service context in CORBA

    In the CORBA architecture, the invocation interceptor plays an important role in the function provided by the ORB runtime. Generally speaking, four interception points are available through the ORB runtime. As shown in Figure 1, these interception points are for:



    • Out-bound request messages from the client process

    • In-bound request messages to the server process

    • Out-bound response messages from the server process

    • In-bound response messages to the client process



    The so-called portable interceptor can support both a request-level interceptor (pre-marshaling) and a message-level interceptor (post-marshaling). More specific details can be found in the CORBA specification documents.










    Figure 1. ORB invocation interceptors.




    Interceptors provide a powerful and flexible design support to both ORB vendors and application builders for constructing highly distributed applications. Value-adding functions can be transparently added and enabled at the protocol, ORB, or application layers without complicating standardized application-level APIs. Examples include invocation monitoring, logging, and message routing. In some sense, we are looking for a kind of RMI-level AOP (aspect-oriented programming) support.



    Among the many uses of interceptors, propagating service-context data is one of the most important. Effectively, service-context propagation provides a way to extend the ORB runtime and IIOP protocol without affecting applications built on top of the ORB, such as IDL (interface definition language) definitions. CORBA services, such as transaction and security services, standardize and publish the structure of their specific service-context data as IDL data types, together with the unique context identifiers (context_id).



    Simply put, service-context data is information that the ORB runtime (RMI runtime, for this article's purposes) manages to support infrastructure-level services that the runtime provides to hosted applications. The information usually must be piggybacked on each invocation message between the client process and the server process. ORB runtime and related infrastructure-level services are responsible for sending, retrieving, interpreting, and processing such context data and delivering it to the application layer whenever necessary. Service-context data is passed with each request and reply message with no application interface-level exposure, such as at the IDL layer.



    Nevertheless, it is not fair to ask RMI to directly support such capabilities as it is only a basic remote method invocation primitive, while CORBA ORB is at a layer close to what the J2EE EJB (Enterprise JavaBean) container offers. In the CORBA specification, service context is directly supported at the IIOP level (GIOP, or General Inter-Orb Protocol) and integrated with the ORB runtime. However, for RMI/IIOP, it is not easy for applications to utilize the underlying IIOP service-context support, even when the protocol layer does have such support. At the same time, such support is not available when RMI/JRMP (Java Remote Method Protocol) is used. As a result, for RMI-based distributed applications that do not use, or do not have to use, an ORB or EJB container environment, the lack of such capabilities limits the available design choices, especially when existing applications must be extended to support new infrastructure-level functions. Modifying existing RMI interfaces often proves undesirable due to the dependencies between components and the huge impact to client-side applications. The observation of this RMI limitation leads to the generic solution that I describe in this article.

    The high-level picture

    The solution is based on Java reflection techniques and some common methods for implementing interceptors. More importantly, it defines an architecture that can be easily integrated into any RMI-based distributed application design. I demonstrate the solution through an example implementation that supports the transparent passing of transaction-context data, such as a transaction ID (xid), with RMI. The example's source code is available for download from Resources. The solution contains the following three components:



    1. RMI remote interface naming-function encapsulation and interceptor plug-in (rmicontex.interceptor.*)


    2. Service-context propagation mechanism and server-side interface support (rmicontex.service.*)


    3. Service-context data structure and transaction-context propagation support (rmicontex.*)



    The components' corresponding Java class packages are shown in Figure 2.










    Figure 2. The component view of packages




    The example is not meant to be used as a whole package solution; rather, the implementation demonstrates the underlying design approach. The implementation assumes that RMI/IIOP is used. However, it by no means implies that this solution is only for RMI/IIOP. In fact, either RMI/JRMP or RMI/IIOP can be used as the underlying RMI environments, or even a hybrid of the two environments if the naming service supports both.



    Naming-function encapsulation

    To implement our solution, first we encapsulate the naming function that provides the RMI remote interface lookup, allowing interceptors to be transparently plugged in. Such an encapsulation is always desirable and can always be found in most RMI-based applications. The underlying naming resolution mechanism is not a concern here; it can be anything that supports JNDI (Java Naming and Directory Interface). In this example, to make the code more illustrative, we assume all server-side remote RMI interfaces inherit from a mark remote interface ServiceInterface, which itself inherits from the Java RMI Remote interface. Figure 3 shows the class diagram, which is followed by code snippets that I will describe further:










    Figure 3. Class diagram of ServiceInterface and ServiceManager





    package rmicontext.service;



    public interface ServiceInterface extends Remote {

    }



    package rmicontext.service;



    public class Service

       extends PortableRemoteObject

       implements ServiceInterface,

       ServiceInterceptorRemoteInterface {

       ....

    }



    package rmicontext.service;



    public interface ServiceManagerInterface {

       public ServiceInterface getServiceInterface(String serviceInterfaceClassName);

    }



    package rmicontext.service;



    public class ServiceManager

       implements ServiceManagerInterface {



       /**

        * Gets a reference to a service interface.

        *

        * @param serviceInterfaceClassName The full class name of the requested interface

        * @return selected service interface

        */

       public ServiceInterface getServiceInterface(String serviceInterfaceClassName) {

          // The actual naming lookup is skipped here ...



       }

    }



    The Service serves as the base class for any server-side RMI remote interface implementation. No real code is needed at the moment. For simplicity, we just use the RMI remote interface Class name as the key for the interface naming lookup. The naming lookup is encapsulated through the class ServiceManager, which implements the interface ServiceManagerInterface as the new encapsulated naming API.



    In the next section, you find out how the interceptor is plugged in. A simple interface-caching implementation is also included to complete the class ServiceManager.

    RMI invocation interceptor

    To enable the invocation interceptor, the original RMI stub reference acquired from the RMI naming service must be wrapped by a local proxy. To provide a generic implementation, such a proxy is realized using a Java dynamic proxy API. In the runtime, a proxy instance is created; it implements the same ServiceInterface RMI interface as the wrapped stub reference. Any invocation will be delegated to the stub eventually after first being processed by the interceptor. A simple implementation of an RMI interceptor factory follows the class diagram shown in Figure 4.










    Figure 4. RMI interceptor factory





    package rmicontext.interceptor;



    public interface ServiceInterfaceInterceptorFactoryInterface {

       ServiceInterface newInterceptor(ServiceInterface serviceStub, Class serviceInterfaceClass) throws Exception;

    }



    package rmicontext.interceptor;



    public class ServiceInterfaceInterceptorFactory

       implements ServiceInterfaceInterceptorFactoryInterface {



       public ServiceInterface newInterceptor(ServiceInterface serviceStub, Class serviceInterfaceClass)

          throws Exception {



          ServiceInterface interceptor = (ServiceInterface)

             Proxy.newProxyInstance(serviceInterfaceClass.getClassLoader(),

                new Class[]{serviceInterfaceClass},

                new ServiceContextPropagationInterceptor(serviceStub));   // ClassCastException



          return interceptor;

       }

    }



    package rmicontext.interceptor;



    public class ServiceContextPropagationInterceptor

       implements InvocationHandler {



       /**

        * The delegation stub reference of the original service interface.

        */

       private ServiceInterface serviceStub;



       /**

        * The delegation stub reference of the service interceptor remote interface.

        */

       private ServiceInterceptorRemoteInterface interceptorRemote;



       /**

        * Constructor.

        *

        * @param serviceStub The delegation target RMI reference

        * @throws ClassCastException as a specified uncaught exception

        */

       public ServiceContextPropagationInterceptor(ServiceInterface serviceStub)

          throws ClassCastException {



          this.serviceStub = serviceStub;



          interceptorRemote = (ServiceInterceptorRemoteInterface)

             PortableRemoteObject.narrow(serviceStub, ServiceInterceptorRemoteInterface.class);

       }



       public Object invoke(Object proxy, Method m, Object[] args)

          throws Throwable {

          // Skip it for now ...

       }

    }



    I have simplified the above code to focus more on the underlying design. Here, only one type of interceptor is created, and it is implemented as the ServiceContextPropagationInterceptor class. This interceptor is responsible for retrieving and passing all the service-context data available under the current invocation scope. More detail will be covered later. The interceptor factory is used by the naming-function encapsulation described in the previous section.



    To complete the ServiceManager class, a simple interface proxy cache is implemented:




    package rmicontext.service;



    public class ServiceManager

       implements ServiceManagerInterface {



       /**

        * The interceptor stub reference cache.

        * <br><br>

        * The key is the specific serviceInterface sub-class and the value is the interceptor stub reference.

        */

       private transient HashMap serviceInterfaceInterceptorMap = new HashMap();



       /**

        * Gets a reference to a service interface.

        *

        * @param serviceInterfaceClassName The full class name of the requested interface

        * @return selected service interface

        */

       public ServiceInterface getServiceInterface(String serviceInterfaceClassName) {



          // The actual naming lookup is skipped here.

          ServiceInterface serviceInterface = ...;



          synchronized (serviceInterfaceInterceptorMap) {



             if (serviceInterfaceInterceptorMap.containsKey(serviceInterfaceClassName)) {

                WeakReference ref = (WeakReference) serviceInterfaceInterceptorMap.get(serviceInterfaceClassName);

                if (ref.get() != null) {

                   return (ServiceInterface) ref.get();

                }

             }

             try {

                Class serviceInterfaceClass = Class.forName(serviceInterfaceClassName);



                ServiceInterface serviceStub =

                   (ServiceInterface) PortableRemoteObject.narrow(serviceInterface, serviceInterfaceClass);



                ServiceInterfaceInterceptorFactoryInterface factory = ServiceInterfaceInterceptorFactory.getInstance();

                ServiceInterface serviceInterceptor =

                   factory.newInterceptor(serviceStub, serviceInterfaceClass);



                WeakReference ref = new WeakReference(serviceInterceptor);

                serviceInterfaceInterceptorMap.put(serviceInterfaceClassName, ref);



                return serviceInterceptor;

             } catch (Exception ex) {

                return serviceInterface;   // no interceptor

             }

          }

       }

    }



    Optionally, the ability to distinguish between an interceptor-enabled service interface and a non-interceptor-enabled service interface can be added. For a non-interceptor-enabled service interface, the raw RMI stub reference will return. Further, a registration mechanism can be used when multiple interceptors need to be invoked according to some predefined invocation order for each different ServiceInterface type. To make the local proxy more robust, we also need to detect stale remote references in each interceptor. However, to keep the example more concise, such error handlings are not included for the above implementation.



    In the next section, I describe the actual context data we'd like to use as well as the related interceptor proxy implementation—the invoke() method from the java.lang.reflect.InvocationHandler interface.



    Transaction context

    Transaction context is the most commonly used service-context data. As described in the Java Transaction Service specification, transaction context, such as transaction ID (xid), must be associated with threads currently involved in a transaction. Thus, the transaction-context data must be propagated from the client JVM to the target server JVM with each RMI invocation.



    On the server-side, an RMI thread is assigned to service the invocation call and hence the enclosing transaction. Obviously, it is impossible to require each RMI ServiceInterface to include an additional argument for each of its operations to pass such context data. Even if we choose to do so, the client code is not supposed to be aware of such invocation semantics. Therefore, for each RMI invocation in the client code, the context fetching and propagating should occur in a way that is totally transparent to client code.



    According to the API convention described in the CORBA Transaction Service Specification, the following classes are defined to serve as the target service-context data structure and provide the required runtime support:




    package rmicontext;



    public class ServiceContext implements Serializable {



       public static final int TRANSACTION_CONTEXT_ID = 2;

       public int contextId = 0;   // Unknown

       public Object contextData = null;



       public ServiceContext() {



       }

       public ServiceContext(int contextId) {

          this.contextId = contextId;

       }

       public boolean isContextId(int id) {

          if (contextId == id) {

             return true;

          } else {

             return false;

          }

       }

       public int getContextId() {

          return contextId;

       }

       public Object getContextData() {

          return contextData;

       }

       public void setContextData(Object data) {

          contextData = data;

       }

    }



    package rmicontext;



    public class TransactionContextData implements Serializable {



       public static final int UNASSIGNED_XID = 0;



       private int xid = UNASSIGNED_XID;    // Not assigned



       public TransactionContextData() {}



       public TransactionContextData(int xid) {

          this.xid = xid;

       }



       public int xid() {

          return xid;

       }

    }



    package rmicontext;



    public class Current {



       private static ServiceContextList contextList = new ServiceContextList();



       public static void setServiceContextList(ServiceContext[] contexts) {



          contextList.set(contexts);

       }

       public static void clearServiceContextList() {

          contextList.set(null);

       }

       public static ServiceContext[] getServiceContextList() {

          return (ServiceContext[]) contextList.get();

       }



       /**



        * To set the transaction ID to the associated context data.

        */

       public static void setXid(int xid) {

          // ...

       }

       /**

        * To fetch the transaction id from the associated context data.

        */

       public static int getXid() {

          // ...

       }

    }



    /**

    * The list of service contexts associated with the current thread. Package access only.

    */

    class ServiceContextList extends InheritableThreadLocal {

    }



    Class ServiceContext contains a context ID and context data. The context ID is predefined and known to both the client and server code. Context data does not require type-safety and is only opaque data as far as the service-context propagation protocol is concerned. In this example, context data for the transaction service context contains only an xid as defined in the class TransactionContextData. For the current thread, all service contexts, defined as ServiceContext[], are maintained as thread local data through the Current class. For convenience, this class also provides direct API support for fetching and setting xid, which represents the transaction context in this example.



    Until now, I haven't revealed the real solution for the RMI service-context propagation. The next section describes what's required on the client and server sides to make that happen.

    The realization of service-context propagation

    So far, I have described the infrastructure support for enabling the RMI interceptor and service context. To realize the implicit service-context propagation over RMI, the ultimate approach is still to add an additional argument for each RMI invocation. However, such an argument is only passed behind the scenes, and the client code still invokes the original RMI service interface method. I begin to reveal the real mechanism by first going through the following server-side code:




    package rmicontext.interceptor;





    /**

    * This interface will be implemented by each Service class.

    */

    public interface ServiceInterceptorInterface {



       /**

        * The interceptor method that decodes the incoming request message on the Service side.

        *

        * @param methodName    The method name

        * @param arguments     The arguments

        * @param argumentTypes The argument class names to be used to identify an implementation Method

        * @param contextList   The ContextList to be set to Current

        * @return The return value of the method invocation

        * @throws RemoteException           if any RMI error

        * @throws InvocationTargetException that wrapps the cause exception of the invocation

        */

       Object exec(String methodName, Object[] arguments, String[] argumentTypes, ServiceContext[] contextList)

          throws RemoteException, InvocationTargetException;

    }



    package rmicontext.interceptor;



    /**

    * The remote version of ServiceInterceptorInterface.

    */

    public interface ServiceInterceptorRemoteInterface extends ServiceInterceptorInterface, Remote {

    }



    Instead of having a server-side skeleton interceptor, above I have defined the ServiceInterceptorInterface and ServiceInterceptorRemoteInterface, two interfaces that the Service base class must implement. The reason for two interfaces is to decouple the remoteness from the functional interface definition. (By doing so, we can support even local method propagation.) Now it is time to complete the Service class's implementation:




    package rmicontext.service;



    public class Service

       extends PortableRemoteObject

       implements ServiceInterface,

       ServiceInterceptorRemoteInterface {





       public Service() throws RemoteException {

          super();

       }



       // ==== Service Interceptor Server-side Implementation ====

       public Object exec(String methodName, Object[] arguments, String[] argumentTypes, ServiceContext[] contextList)

          throws RemoteException, InvocationTargetException {



          Class serviceClass = getClass();

          try {

             Class[] argTypes = ClassUtil.forNames(argumentTypes);

             Method serviceMethod = serviceClass.getMethod(methodName, argTypes);

             Current.setServiceContextList(contextList);

             return serviceMethod.invoke(this, arguments);



          } catch (ClassNotFoundException ex) {

             processExecReflectionException(ex);

          } catch (NoSuchMethodException ex) {

             processExecReflectionException(ex);

          } catch (IllegalAccessException ex) {

             processExecReflectionException(ex);

          }

          return null;   // javac



       }



       /**

        * Process a reflection exception.

        *

        * @throws InvocationTargetException a wrapped exception

        */

       private void processExecReflectionException(Exception ex) throws InvocationTargetException {

          // The cause exception has to be a runtime exception.

          throw new InvocationTargetException(new IllegalArgumentException("Interceptor Service.exec() failed: " + ex));

       }

    }



    As a base class for each server-side ServiceInterface implementation, the Service class provides a generic way for accepting service-context data as an implicit argument via a generic exec() method, which is available to every client-side proxy stub. The magic also lies in the logics of finding the target method that the actual RMI invocation is to be delegated to. Because methods can be overloaded in every class, an exact argument type-matching is needed. That explains why the exec() method must pass the class names of all the argument types. Regarding this point, you may have noticed the use of the ClassUtil class. This class enhances the java.lang.Class class by defining a more convenient forName() method that covers primitive types too. ClassUtil's contents follow:




    package rmicontext;



    public final class ClassUtil {



       /**

        * Get the class names than can be used in remote reflection invocation.



        * @param argTypes The method argument classes

        * @return class names

        */

       public static String[] getNames(Class[] argTypes) {



          String[] result = new String[argTypes.length];

          for (int i = 0; i < argTypes.length; i++) {

             result[i] = argTypes[i].getName();

          }

          return result;

       }



       /**

        * Get the classes from names.

        *

        * @param argTypes The method argument classes' names

        * @return ClassNotFoundException if any class can not be located

        */

       public static Class[] forNames(String[] argTypes) throws ClassNotFoundException {

          Class[] result = new Class[argTypes.length];



          for (int i = 0; i > argTypes.length; i++) {

             result[i] = forName(argTypes[i]);

          }



          return result;

       }



       /**

        * Enhanced java.lang.Class.forName().

        *

        * @param name The class name or a primitive type name



        * @return ClassNotFoundException if no class can be located

        */

       public static Class forName(String name) throws ClassNotFoundException {

          if (name.equals("int")) {

             return int.class;

          } else if (name.equals("boolean")) {

             return boolean.class;

          } else if (name.equals("char")) {

             return char.class;

          } else if (name.equals("byte")) {

             return byte.class;

          } else if (name.equals("short")) {

             return short.class;

          } else if (name.equals("long")) {

             return long.class;

          } else if (name.equals("float")) {

             return float.class;

          } else if (name.equals("double")) {

             return double.class;

          } else {

             return Class.forName(name);

          }

       }

    }



    On the client side, we now complete the only interceptor we are supporting here, particularly, the invoke() method from the java.lang.reflect.InvocationHandler interface. To support the service-context propagation, this is the only change required on the client side. Because the interceptor is deployed transparently on the client side, client code will never be aware of any underlying service-context propagation. The related implementation looks like:




    package rmicontext.interceptor;



    /**

    * This is the invocation handler class of the service context propagation

    * interceptor, which itself is a dynamic proxy.

    */

    public class ServiceContextPropagationInterceptor

       implements InvocationHandler {



       /**

        * The delegation stub reference of the original service interface.

        */

       private ServiceInterface serviceStub;



       /**

        * The delegation stub reference of the service interceptor remote interface.

        */

       private ServiceInterceptorRemoteInterface interceptorRemote;



       /**

        * Constructor.

        *

        * @param serviceStub The delegation target RMI reference

        * @throws ClassCastException as a specified uncaught exception

        */

       public ServiceContextPropagationInterceptor(ServiceInterface serviceStub)

          throws ClassCastException {



          this.serviceStub = serviceStub;

          interceptorRemote = (ServiceInterceptorRemoteInterface)

             PortableRemoteObject.narrow(serviceStub, ServiceInterceptorRemoteInterface.class);

       }



       /**

        * The invocation callback. It will call the service interceptor remote interface upon each invocation.

        *

        * @param proxy The proxy instance

        * @param m     The method

        * @param args  The passed-in args

        * @return Object The return value. If void, then return null

        * @throws Throwable Any invocation exceptions.

        */

       public Object invoke(Object proxy, Method m, Object[] args)

          throws Throwable {



          Object result;



          // In case the context is explicitly specified in the method signature as the last argument.

          if (args != null && args.length > 0) {



             Class[] argTypes = m.getParameterTypes();

             Class argType = argTypes[argTypes.length - 1];  // Last argument



             if (argType == ServiceContext[].class) {

                try {



                   return m.invoke(serviceStub, args);

                } catch (InvocationTargetException ex) {   // including RemoteException

                   throw ex.getCause();

                }

                // Ignore the IllegalAccessException

             }

          }



          try {

             if (args == null || args.length == 0) {

                result =

                   interceptorRemote.exec(m.getName(), args, new String[]{}, Current.getServiceContextList());

             } else {

                String[] argTypes = ClassUtil.getNames(m.getParameterTypes());



                result =

                   interceptorRemote.exec(m.getName(), args, argTypes, Current.getServiceContextList());

             }

             return result;   // Null if void

          } catch (RemoteException ex) {

             throw ex;

          } catch (InvocationTargetException ex) {

             throw ex.getCause();

          }

       }

    }



    Based on the groundwork we already established in the earlier steps, the above implementation is quite straightforward. One thing you must note is the exception-processing logic. Considering transaction-context propagation is mainly one-way and request context is more important, for simplicity, we don't piggyback the client-side service context in the response message, which is the return value of the invoke() method. However, adding the response service-context support does not require much work, so I leave this task to you.



    The final design is shown in Figure 5.










    Figure 5. ServiceInterceptorInterface class diagram




    I'd like to return to the ServiceInterceptorRemoteInterface and ServiceInterceptorInterface interfaces as an approach for eliminating the coupling with the server-side ServiceInterface implementations. A dynamic server-side skeleton interceptor could also be used for the same purpose. However, I consider server-side transparency to be less significant than on the client-side, and to increase runtime efficiency and reduce deployment overhead, I chose this simpler approach.



    However, my decoupling approach does incur some coding cost, mainly due to the JDK 1.4 rmic bug (bug-id: 5002152, reported by the author). When RMI/IIOP (rmic -iiop) is used, the ServiceInterceptorRemoteInterface interface must be redeclared for each subclass of the Service class. In some cases, this may cause problems, for instance, when the source code of the specialized Service implementation is not available. This bug does not apply to RMI/JRMP.

    Performance consideration

    The performance costs mainly come from reflection, both on the client and server sides:



    • Dynamic proxy creation for the interceptor on the client side—this is a one-time cost


    • Cost associated with dynamic proxy invocation handler implementation on the client side


    • Reflection cost for identifying the target method on the server side


    • Marshaling cost for passing argument type names



    Costs related to the service-context propagation function itself are not included. From the above analysis, we can see that the costs are mostly decided by the class signature, the number of overloaded methods, the target method signature, and the number of arguments. In other words, the total cost is static and does not depend on the size of instance data passed as arguments in the runtime, as opposed to RMI marshaling costs on the IIOP or JRMP layers. In most cases, the performance overhead is negligible, especially considering the overhead of RMI marshaling (let alone the IIOP marshaling).



    Some simple measurements show that on a standard PC environment, with JDK 1.4, the RMI invocation overhead will be less than 5 ms for methods that have at least two arguments and two overloaded variants. In reality, the average overhead could be lower. I don't have any performance numbers for the equivalent cost associated with IIOP service-context propagation. Regardless, it will be much smaller than the cost of argument data marshaling.

    Conclusion

    You've been presented with some ways that RMI can be extended to meet the challenging design requirements we face in building today's distributed applications. The common concepts of service context and interceptor were illustrated to establish the high-level application context.



    Many other items remain to be explored, such as a local method-invocation interceptor at the component level, a deployment strategy for registering, loading, configuring, and controlling service-specific interceptors, as well as further API-level abstraction. With all these further developments, the solution presented in this article can be easily made into a ready-to-use framework component.



    About the author

    Wenbo Zhu joined Sun Microsystems in 1997 as part of its Java development promotion force. For the past three years, he has been developing a carrier-grade network management application platform for Nortel as a senior Java designer. He's also studying as a part-time PhD student at Carleton University (Ottawa, Canada) in the real-time and distributed systems lab, focusing on software performance engineering and modeling for high-reliability distributed systems.





    Posted by 아름프로

    BLOG main image

    카테고리

    분류 전체보기 (539)
    이야기방 (19)
    토론/정보/사설 (16)
    IBM Rational (9)
    U-IT (0)
    SOA/WS/ebXML (110)
    개발방법론/모델링 (122)
    J2SE (34)
    J2EE (60)
    DataBase (39)
    Open Projects (30)
    BP/표준화 (50)
    Apache Projects (15)
    Web/보안/OS (22)
    Tools (7)
    AJAX/WEB2.0 (1)
    Linux/Unix (1)
    영어 (0)
    비공개방 (0)

    최근에 올라온 글

    최근에 달린 댓글

    최근에 받은 트랙백

    달력

    «   2024/05   »
    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 31

    글 보관함

    Total :
    Today : Yesterday :