Tìm hiểu cách dễ dàng để được đào tạo và được cấp chứng chỉ với DB2 cho Linux, UNIX và 
Windows với bộ e-kit DB2 của IBM cho những người chuyên nghề cơ sở dữ liệu. Hãy đăng ký 
ngay bây giờ và mở rộng danh mục các kỹ năng của bạn hoặc mở rộng sự hỗ trợ của nhà cung 
cấp DBMS của bạn để bao gồm cả DB2.
Bài viết này cung cấp cho bạn một tổng quan về một ứng dụng FileNet P8 của IBM đầy đủ, độc 
lập. P8 là một nền tảng của IBM về Quản lý nội dung doanh nghiệp (ECM-Enterprise Content 
Management). Mặc dù hầu hết các chương trình P8 trong thế giới thực là một phần của một 
khung công tác lớn hơn như J2EE hay .Net, là một nhà phát triển, nhiều khả năng điểm bắt đầu 
có thể của bạn là một chương trình độc lập. Bằng cách sử dụng một chương trình độc lập, bạn có 
thể tập trung vào các chi tiết P8 mà không cần phải tập trung vào sự phức tạp của khung công tác 
lớn hơn
                
              
                                            
                                
            
                       
            
                 14 trang
14 trang | 
Chia sẻ: lylyngoc | Lượt xem: 2182 | Lượt tải: 1 
              
            Bạn đang xem nội dung tài liệu Viết mã thú vị với các API FileNet P8 của IBM Phần 1: Hello, Document!, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
Viết mã thú vị với các API FileNet P8 của IBM 
Phần 1: Hello, Document! 
Hãy làm quen với HelloDocument 
Bộ e-kit (dụng cụ-điện tử) DB2 của IBM cho các người 
chuyên nghề cơ sở dữ liệu 
Tìm hiểu cách dễ dàng để được đào tạo và được cấp chứng chỉ với DB2 cho Linux, UNIX và 
Windows với bộ e-kit DB2 của IBM cho những người chuyên nghề cơ sở dữ liệu. Hãy đăng ký 
ngay bây giờ và mở rộng danh mục các kỹ năng của bạn hoặc mở rộng sự hỗ trợ của nhà cung 
cấp DBMS của bạn để bao gồm cả DB2. 
Bài viết này cung cấp cho bạn một tổng quan về một ứng dụng FileNet P8 của IBM đầy đủ, độc 
lập. P8 là một nền tảng của IBM về Quản lý nội dung doanh nghiệp (ECM-Enterprise Content 
Management). Mặc dù hầu hết các chương trình P8 trong thế giới thực là một phần của một 
khung công tác lớn hơn như J2EE hay .Net, là một nhà phát triển, nhiều khả năng điểm bắt đầu 
có thể của bạn là một chương trình độc lập. Bằng cách sử dụng một chương trình độc lập, bạn có 
thể tập trung vào các chi tiết P8 mà không cần phải tập trung vào sự phức tạp của khung công tác 
lớn hơn. 
Ứng dụng ví dụ HelloDocument thực hiện một số nhiệm vụ, một số trong đó bạn có thể không 
cần biết về nó, tuy nhiên, bạn có thể muốn làm một điều riêng biệt nào đó trong ứng dụng đó. 
Ngoài ra, bạn có thể sử dụng các kỹ thuật được minh họa trong mã này và mở rộng chúng để làm 
những việc phù hợp hơn với các trường hợp sử dụng của mình. Có lẽ cũng quan trọng không 
kém, một khi bạn có HelloDocument đang chạy, bạn có thể tự tin rằng môi trường của bạn được 
cấu hình đúng. Điều này cho phép bạn sau đó tập trung vào các chi tiết ứng dụng của mình mà 
không còn vương vấn nghi ngờ về môi trường của bạn nữa. 
Để hiểu bài viết này, bạn cần có một sự hiểu biết cơ bản về Java™ và có thể làm theo các mô tả 
của mã nguồn Java. Bài viết này không mô tả tất cả các dòng mã của HelloDocument.java mà, 
thay vào đó, đi vào những điểm nổi bật để minh họa các quan điểm API của Máy nội dung (CE-
Content Engine). Mã này có rất nhiều chú thích và nếu bạn thích phiêu lưu, bạn có thể bỏ qua bài 
viết này và đi ngay vào chính mã nguồn của nó (xem phần Tài nguyên). 
HelloDocument được cấu trúc như một tệp nguồn Java duy nhất có 400-500 dòng. Thậm chí khi 
tính đến nhiều chú thích trong mã nguồn, vẫn còn rất nhiều dòng chỉ để làm quen. Có một số thứ 
trong HelloDocument.java mà bạn muốn di chuyển vào các lớp hoặc các tệp nguồn riêng biệt . 
Chúng được trình bày tất cả ở một chỗ duy nhất để cho bạn có thể chắc chắn là bạn có mọi thứ. 
Ví dụ, chuỗi đăng nhập Dịch vụ xác thực và ủy quyền Java (JAAS) đầy đủ, bao gồm một lớp bên 
trong xử lý các cuộc gọi lại, được bao gồm trong tệp nguồn HelloDocument.java. Điều đó chắc 
chắn sẽ là một sự lựa chọn khác thường với một ứng dụng thực tế. Lớp HelloDocument triển 
khai thực hiện giao diện PrivilegedAction và gói hầu hết logic nghiệp vụ của mình bên trong 
một phương thức chạy chỉ để dễ dàng minh họa mô hình đăng nhập JAAS rõ ràng. Logic nghiệp 
vụ cho HelloDocument hóa ra không quá 50 -100 dòng. 
Bài viết này được viết khi bản phát hành hiện tại trong lĩnh vực này đã là P8 4.0.1 và P8 4.5.0 đã 
đến cuối chu kỳ phát triển của nó. Mã này chạy được trong cả hai bản phát hành. (Bài viết này và 
các bài viết khác trong loạt bài này không dành nhiều thời gian cho các API từ P8 3.x. Trong một 
số trường hợp, các API này là hoàn toàn khác nhau). Vì các lớp API và các phương thức được 
dùng làm lõi cho các API, chúng rất ổn định. Nhiều khả năng là HelloDocument sẽ chạy mà 
không cần thay đổi gì trong một số chu kỳ phát hành P8 sắp tới. HelloDocument được viết bằng 
Java. Vì API của Content Java P8 khác với API của Content .Net P8 chủ yếu trong quy ước đặt 
tên và các lý do phụ khác, nên để viết lại HelloDocument bằng một ngôn ngữ .Net giống như C# 
sẽ chỉ là một việc chuyển chữ đơn giản. (Trong lĩnh vực xác thực có sự không giống nhau giữa 
hai API. Mặc dù bài viết này bàn về xác thực Java cho HelloDocument, nhưng việc thảo luận 
chung về xác thực nằm ngoài phạm vi của bài viết này.) 
Vậy thì, HelloDocument thực sự làm cái gì? Nó tạo ra một tài liệu, tải nội dung từ một tệp lên, 
kiểm tra tệp và đặt tệp đó trong một thư mục. Sau đó nó đọc lại tệp đó và so sánh nội dung được 
tải về với nội dung tệp gốc. Theo tùy chọn, bạn có thể cấu hình ứng dụng để bỏ qua một phần 
của tệp trong quá trình tải về và so sánh. Mặc dù việc tạo và lưu các tài liệu thành tệp là phổ biến 
cho nhiều trường hợp sử dụng, nhưng lại không có các bước so sánh. Trong thực tế, bạn chưa 
bao giờ phải kiểm tra nội dung mà bạn đã tải lên. Các phần bổ xung trong khi tải về chỉ có nghĩa 
minh họa một số khía cạnh viết mã API. HelloDocument được thiết kế để cho bạn không phải 
làm bất kỳ thiết lập cụ thể nào trong Máy nội dung (CE) trước khi bạn chạy nó (ngoài việc bảo 
đảm chắc chắn rằng bạn có các quyền truy cập để tạo các thư mục và các tài liệu mới). Một khi 
bạn có nó đang chạy trong môi trường của mình, bạn có thể chạy nó nhiều lần mà không bị lỗi. 
Về đầu trang 
Cấu hình 
Cấu hình nhúng 
Một số các mục trong cấu hình điều khiển HelloDocument, chẳng hạn như URI (Uniform 
Resource Identifier-Trình nhận dạng tài nguyên thống nhất) của kết nối Máy nội dung (CE), là 
chung cho hầu hết các ứng dụng P8. Những mục khác là dành riêng cho ví dụ HelloDocument. 
Trong một ứng dụng thực tế, bạn sẽ gần như chắc chắn không mã hóa cứng các mục cấu hình 
này. Bạn sẽ sử dụng các đối số dòng lệnh, một tệp cấu hình hoặc một số cơ chế khác để tách cấu 
hình ra khỏi mã của chính ứng dụng. Để cho thuận tiện, HelloDocument định nghĩa tất cả các 
mục cấu hình đó như là các hằng số trong một lớp bên trong tĩnh tên là ConfigInfo, được hiển 
thị dưới dạng viết tắt trong Liệt kê 1. Ở đây bạn thấy các tham chiếu tới 
ConfigInfo.SOME_VALUE rải rác trong mã đó, chúng đang tham chiếu đến các hằng số này. 
Liệt kê 1. Lớp bên trong tĩnh ConfigInfo 
private static final class ConfigInfo 
{ 
 // . . . 
 /** 
 * This URI tells us how to find the CE and what protocol to use. 
 */ 
 static String CE_URI = ""; 
 /** 
 * This ObjectStore must already exist. 
 */ 
 static String OBJECT_STORE_NAME = "MyObjectStore"; 
 // . . . 
} 
Mỗi mục trong ConfigInfo có các chú thích giải thích cách sử dụng nó. Bạn nên xem xét từng 
mục và đặt nó tới một giá trị thích hợp cho môi trường của bạn. 
ConfigInfo 
Các mục cấu hình khác 
Vì đây là một bài viết về cách viết mã, nó không đi sâu vào nhiều chi tiết về cách thiết lập đường 
dẫn lớp Java và các mục cấu hình bên ngoài khác của bạn. Tài liệu về nền tảng P8 mô tả cách 
thiết lập một môi trường khách không rõ ràng. Nó là khác với mỗi nhánh của máy chủ ứng dụng 
J2EE. Phần tương tự của tài liệu đó cũng mô tả cách cấu hình các giá trị cài đặt JAAS của bạn. 
Các ví dụ và các hướng dẫn trong phần còn lại của bài viết này dựa trên điều kiện mọi giá trị ấy 
được cấu hình đúng. 
Về đầu trang 
Nhận hay tìm nạp? 
Một đối tượng Java trong API không phải là thứ giống hệt như một đối tượng trong một kho lưu 
trữ CE. Nó chỉ đại diện cho một tham chiếu đến đối tượng CE qua đó bạn có thể kiểm tra các giá 
trị đặc tính, chuyển hướng bằng cách đi theo các đặc tính do đối tượng định giá (các OVP) và 
thực hiện nhiều kiểu cập nhật. Sự phối hợp thực sự giữa đối tượng API và đối tượng CE xảy ra 
khi API thực hiện một chuyến đi khứ hồi (truyền dữ liệu khứ hồi) đến máy chủ. Số các chuyến đi 
khứ hồi đến máy chủ nhiều lần là yếu tố chi phối hiệu năng của một ứng dụng, vì vậy API cung 
cấp việc kiểm soát chặt chẽ hơn khi các chuyến đi khứ hồi thực sự xảy ra và dữ liệu nào truyền 
trên dây cho mỗi chuyến đi khứ hồi ấy. HelloDocument khá cẩn thận về giảm thiểu các chuyến 
đi khứ hồi, nhưng nó đặc biệt không lưu ý về việc giảm thiểu số lượng dữ liệu liên quan đến các 
yêu cầu hoặc các đáp ứng. Bạn có thể điều chỉnh các kích cỡ tải đó thông qua các bộ lọc đặc tính 
và các cơ chế khác. Các bộ lọc đặc tính này được thảo luận chi tiết hơn trong một bài viết sắp tới 
của loạt bài này. Bây giờ, tất cả mọi thứ mà bạn thực sự cần biết là API được thiết kế để làm việc 
mà nếu bạn không sử dụng các bộ lọc đặc tính thì cũng chẳng có gì bất ngờ cả. Một khi bạn có 
được một sự hiểu biết cơ bản về API, chắc chắn bạn sẽ muốn sử dụng các bộ lọc đặc tính vì 
chúng có thể cải thiện đáng kể hiệu năng, cả hai vừa bằng cách giảm kích cỡ tải trọng và vừa 
bằng cách kết hợp một số chuyến đi khứ hồi. 
Khi bạn đang tạo một đối tượng Java, API có một quy ước có ích. Các tên của các phương thức 
factory (nhà máy) (và một số các kiểu phương thức khác) sử dụng tiền tố get (nhận) để biểu thị 
một hoạt động cục bộ và tiền tố fetch (tìm nạp) để biểu thị rằng một chuyến đi khứ hồi sẽ được 
thực hiện với máy chủ CE. (Cũng có một động từ thứ ba nữa: create (tạo) được sử dụng khi ý 
định của bạn không chỉ là tạo một đối tượng Java, mà còn là tạo một đối tượng CE mới trong 
một kho lưu trữ hoặc ở nơi nào đó khác). Trong biệt ngữ API, việc tạo một đối tượng Java mà 
không có một chuyến đi khứ hồi đến máy chủ được gọi là fetchless instantiation (tạo đối tượng 
không tìm nạp). Vì vậy, ví dụ, conn = 
Factory.Connection.getConnection(ConfigInfo.CE_URI) là cục bộ. Ở nhiều vị trí trong 
mã nguồn HelloDocument, một chú thích no R/T được sử dụng để nhấn mạnh đến việc tạo đối 
tượng không tìm nạp hoặc hoạt động khác mà một người nào đó có thể ngây thơ nghĩ rằng cần có 
một chuyến đi khứ hồi. Lưu ý rằng các phương thức get được sử dụng bất cứ nơi nào có thể. 
Một điều kỳ lạ có thể xảy ra khi bạn sử dụng việc tạo đối tượng không tìm nạp. API tin rằng các 
đối tượng CE mà bạn tham chiếu thực sự tồn tại. Nếu bạn thích nó, bạn có thể nói dối hoàn toàn 
với API biết, mặc dù điều này thường không có ích. Sự tính toán này chỉ cần đến khi một chuyến 
đi khứ hồi xảy ra liên quan đến đối tượng đó. Tại thời điểm đó, máy chủ CE chấp nhận một cách 
có phương thức các tham chiếu đối tượng của bạn với các đối tượng CE thực tế. Đương nhiên, 
việc tạo ra một đối tượng CE là một trường hợp đặc biệt được xử lý theo cách bạn mong đợi. Có 
một số trường hợp khác (nằm ngoài phạm vi của bài viết này), ở đó có thể có ích để tham chiếu 
các đối tượng CE không tồn tại; chúng đơn thuần phải tồn tại vào lúc CE nghe về chúng. 
Điểm mấu chốt là bạn có được một cải tiến hiệu năng bằng cách sử dụng việc tạo đối tượng 
không tìm nạp, nhưng các giá tương ứng phải trả là việc xử lý lỗi của ứng dụng của bạn có thể 
phải đối phó với việc thiếu các đối tượng ở giai đoạn sau. Trên thực tế, giá phải trả cho việc xử 
lý lỗi đó không quá nghiêm trọng. 
Về đầu trang 
Bắt đầu ObjectStore 
Phương thức HelloDocument.run là nơi diễn ra logic nghiệp vụ chính từ trên xuống. Việc bắt 
đầu của phương thức này, cùng với biến cá thể cho một Connection (kết nối), minh họa một mô 
hình mã hóa rất phổ biến (xem Liệt kê 2). Không nghi ngờ gì, hầu hết các ứng dụng nội dung chỉ 
xử lý các đối tượng bên trong các kho lưu trữ CE và hầu hết trong số chúng chỉ xử lý một kho 
lưu trữ duy nhất. 
Liệt kê 2. HelloDocument.run và bạn bè 
/** 
 * All interaction with the server will make use of this Connection object. 
 * Connections are actually stateless, so you don't have to worry about 
 * holding open some CE resource. 
 * 
 * no R/T 
 */ 
private Connection conn = 
Factory.Connection.getConnection(ConfigInfo.CE_URI); 
// ... 
/** 
 * This method contains the actual business logic. Authentication has 
 * already happened by the time we get here. 
 */ 
public Object run() 
{ 
 // Standard Connection -> Domain -> ObjectStore 
 //no R/T 
 Domain dom = Factory.Domain.getInstance(conn, null); 
 //no R/T 
 ObjectStore os = Factory.ObjectStore.getInstance(dom, 
 ConfigInfo.OBJECT_STORE_NAME); 
 String containmentName = createAndFileDocument(dom, os); 
 File f = new File(ConfigInfo.LOCAL_FILE_NAME); 
 long fileSize = f.length(); 
 System.out.println("Local content size is " + fileSize + " for file " 
 + 
ConfigInfo.LOCAL_FILE_NAME); 
 long skipPoint = 0L; 
 if (ConfigInfo.USE_SKIP) 
 { 
 long midPoint = fileSize / 2; 
 // pick a random point in the second half of the content 
 skipPoint = midPoint + (long)Math.floor((Math.random() * midPoint)); 
 } 
 System.out.println("Will skip to " + skipPoint + " of " + fileSize); 
 readAndCompareContent(os, containmentName, skipPoint); 
 return null; 
} 
Mô hình mã hóa để bắt đầu một ObjectStore như sau: 
ObjectStore 
1. Nhận một đối tượng Connection. 
2. Nhận một đối tượng Domain. 
3. Nhận một đối tượng ObjectStore. 
Một đối tượng Connection là một lớp khá nhẹ. Nó nói cho API cách kết nối với máy chủ CE. Vì 
các tương tác giữa API và máy chủ CE là không trạng thái theo quan điểm của máy chủ CE, nên 
đối tượng Connection không duy trì mở bất kỳ tài nguyên phía máy chủ đắt giá nào. Mục thông 
tin chính được duy trì trong đối tượng Connection là URI được sử dụng. API suy diễn cả hai 
phương thức để nối và định vị CE từ URI. Cụ thể là, bạn nên lưu ý đối tượng Connection không 
giữ thông tin người dùng. Có thể thiết lập các tham số cấu hình bổ sung cho một đối tượng 
Connection, nhưng cơ chế đó không được mô tả trong bài viết này. 
Domain (miền) là một đối tượng giữ tài nguyên P8 ở mức ObjectStore hoặc trên mức này. Để 
tạo một đối tượng Domain của Java, bạn cần một đối tượng Connection và một tên miền. Hiện 
nay, một bản cài đặt P8 chỉ có một miền duy nhất, do đó, API cho phép bạn chuyển một giá trị 
bằng không cho tên miền vào phương thức Factory. Tên của miền được thiết lập trong thời gian 
cài đặt P8 và nếu có lúc nào bạn muốn tìm hiểu về nó, thì bạn có thể xem xét giá trị đặc tính 
Name của đối tượng Domain. 
Một đối tượng ObjectStore biểu diễn một kho lưu trữ CE. Lưu ý rằng phương thức Factory để 
tạo ra một đối tượng ObjectStore không lấy một đối tượng Connection. Thay vào đó, nó lấy 
một đối tượng Domain. (Thật đúng khi nói rằng một đối tượng Domain điều khiển một đối tượng 
ObjectStore, nhưng bài viết này không nói nhiều hơn về các mục đích này). Ở bên trong, API 
sử dụng cùng một đối tượng Connection cho đối tượng Domain và các đối tượng được tạo từ nó. 
Sau đó, khi chính ObjectStore được sử dụng để tạo các đối tượng, đối tượng Connection sẽ tự 
động được chuyển đi cùng với chúng trong các API. 
Phần mã này cũng là một nơi thích hợp để lưu ý đến việc sử dụng các phương thức factory nói 
chung. API của CE có một số lượng lớn các lớp factory (nhà máy): ước chừng có một lớp factory 
cho mỗi lớp CE. Các lớp này được sắp xếp cho thuận tiện vào các lớp lồng nhau bên trong lớp 
com.filenet.api.core.Factory. Để tìm ra lớp factory cho bất kỳ lớp CE đặc biệt nào, hãy 
tìm kiếm bên trong Factory một lớp bên trong có tên là Document (Tài liệu) hoặc Folder (Thư 
mục) hoặc bất cứ lớp CE nào mà bạn đang tìm kiếm. Trong phạm vi lớp bên trong ấy, bạn sẽ tìm 
thấy chỉ có một ít phương thức thích hợp để khởi tạo các đối tượng Java cho lớp CE đó. Thật dễ 
dàng để tìm ra những tham số nào dành cho các phương thức nhà máy này. Các phương thức nhà 
máy là an toàn-kiểu theo nghĩa là chúng trả về các kiểu cụ thể. Ví dụ, các phương thức 
Factory.Folder mỗi phương thức trả về một đối tượng kiểu Folder. Ý tưởng đằng sau các 
phương thức nhà máy và an toàn-kiểu nói chung là để giảm các khả năng mắc lỗi lập trình. Vì 
bạn không phải phải ép kiểu, có nhiều khả năng là trình biên dịch sẽ bắt được bất kỳ vấn đề nào. 
Điều đó thích hợp hơn cho việc kiểm tra-kiểu thời gian chạy. 
Có một họ các phương thức khác, nhỏ hơn (không được sử dụng nhiều trong HelloDocument) 
đó là không an toàn-kiểu. Trong biệt ngữ API, đây là các phương thức tiện nghi (commodity 
methods). Một ví dụ là phương thức ObjectStore.getObject, có thể trả về các đối tượng của 
hầu như bất kỳ lớp CE độc lập nào. Ý định của phương thức tiện nghi là để sử dụng trong các mô 
hình mã hóa ứng dụng cụ thể xử lý nhiều kiểu theo một mẫu chung. Thường không có nhiều lý 
do về việc sử dụng các phương thức tiện nghi khi bạn đang xử lý các kiểu cụ thể được biết trước. 
Về đầu trang 
Tạo một cá thể Document mới 
Tập hợp các dòng đầu tiên bên trong phương thức HelloDocument.createAndFileDocument 
đặt nền móng cho việc tạo ra một tài liệu mới có nội dung (xem Liệt kê 3). Ở cuối các dòng mã 
đó, cá thể Document Java được chuẩn bị với hầu hết các hành động mà bạn muốn có, nhưng cá 
thể Document của CE vẫn chưa được tạo ra (vì bạn vẫn chưa thực hiện chuyến đi khứ hồi cần 
thiết tới máy chủ). 
Liệt kê 3. Bên trong HelloDocument.createAndFileDocument, Phần 1 
//no R/T 
ContentTransfer ct = Factory.ContentTransfer.createInstance(); 
ct.setCaptureSource(fis); 
// optional 
ct.set_RetrievalName(ConfigInfo.LOCAL_FILE_NAME); 
// optional 
ct.set_ContentType("application/octet-stream"); 
ContentElementList cel = Factory.ContentElement.createList(); 
cel.add(ct); 
//no R/T 
Document doc = Factory.Document.createInstance(os, null); 
//not required 
doc.getProperties().putValue("DocumentTitle", ConfigInfo.DOCUMENT_TITLE); 
doc.set_ContentElements(cel); 
//no R/T 
doc.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY, CheckinType.MAJOR_VERSION); 
Chuỗi các hoạt động trong Liệt kê 3 có vẻ hơi khó hiểu cho đến khi bạn bắt đầu biết mô hình đối 
tượng CE, đặc biệt là mối quan hệ giữa một cá thể Document và nội dung của nó. Một đoạn nội 
dung duy nhất (ví dụ, một bảng tính hoặc một tài liệu văn bản) nằm trong một đối tượng gọi là 
một content element (phần tử nội dung). Cụ thể hơn, vì nội dung được lưu trữ trong kho lưu trữ 
với Document, nên bạn sử dụng lớp con của phần tử nội dung gọi là ContentTransfer. (Lớp con 
khác, ContentReference, được sử dụng khi các bit thực tế được lưu trữ ở một nơi khác). Một 
Document có thể có số lượng phần tử nội dung bất kỳ và vì chúng là các đối tượng phụ thuộc 
theo biệt ngữ của CE (chúng không thể tồn tại một mình; chúng cần một Document chứa đựng), 
đặc tính Document ContentElements là kiểu ContentElementList. 
Bây giờ, hy vọng rằng, mọi thứ rõ ràng hơn một chút. Bạn sử dụng các phương thức factory để 
tạo ra một đối tượng ContentTransfer, một đối tượng ContentElementList, và một đối tượng 
Document. Bạn thêm đối tượng ContentTransfer vào đối tượng ContentElementList, rồi bạn 
thiết lập giá trị đặc tính ContentElements của Document từ ContentElementList. Có một chút 
linh hoạt về trình tự làm những việc này, vì thế bạn có thể sắp xếp lại chúng trong ứng dụng 
riêng của mình sao cho có ý nghĩa hơn. 
Mã này là một minh chứng tốt về việc sử dụng các phương thức người truy cập (accessor) của 
đặc tính an toàn-kiểu. Ví dụ, khi đặt tên truy tìm cho các phần tử nội dung (một đặc tính tùy chọn 
dùng như là một tên tệp gợi ý cho các ứng dụng sau đó tải về nội dung), bạn gọi 
ct.set_RetrievalName(ConfigInfo.LOCAL_FILE_NAME). Phương thức đó chỉ chấp nhận một 
đối số chuỗi ký tự, do đó, sẽ có một lỗi thời gian-biên dịch nếu bạn cố sử dụng một số nguyên. 
Phương thức getter tương ứng, ContentTransfer.get_RetrievalName, cũng an toàn-kiểu và 
trả về một giá trị chuỗi ký tự. Quy ước đặt tên API Java của set_ và get_ (với một dấu gạch dưới) 
có tác dụng như một tín hiệu để báo cho bạn biết bạn đang xử lý một đặc tính theo nghĩa kho lưu 
trữ CE chứ không chỉ đơn thuần là một trường đối tượng Java điển hình. Mỗi đặc tính do hệ 
thống định nghĩa trên mỗi lớp CE có các phương thức người truy cập an toàn-kiểu. Đối với các 
đặc tính vốn dĩ chỉ đọc, không có phương thức setter an toàn-kiểu nào. 
Thiết lập về đặc tính DocumentTitle trông hơi khác một chút so với các cuộc gọi phương thức 
setter khác: doc.getProperties().putValue("DocumentTitle", 
ConfigInfo.DOCUMENT_TITLE). Điều gì đang xảy ra ở đây? Nhiều người không nhận ra rằng 
DocumentTitle không phải là một đặc tính do hệ thống định nghĩa (theo quan điểm máy chủ CE, 
ở đó có một đặc tính do hệ thống định nghĩa là một đặc tính mà máy chủ CE tạo một giá trị cho 
nó hoặc nó có ảnh hưởng đến hành vi của máy chủ CE hoặc cả hai). Thay vào đó, DocumentTitle 
được định n