Domain Model Exploration

sponsored links
The system has to take stock of your practice, try the Domain Model. But the overall feel that their ideas are not enough system that it liked.
However, on the other hand "system things" may never be achieved, the lives of the lost target will be more boring.
So I decided to own the Domain Model design practice and thinking about a clean breast, can be considered start a discussion. Welcome to the discussion, met with your viewpoints, and hope to adopt a tolerant attitude to face the same direction we go on as partners and not enemies. :)

Before I discuss in depth some of the principles and concepts first throw, and finally you will see the power of these concepts and principles.
1. In accordance with the principles of the concept of reliance to organize the business layer.
2. The business activities (business process) model into a class.
3. With the business activities (business process) as the various objects associated with the business layer of the skeleton.
4. Carved in operational activities extension point, using different interfaces separating the different nature of the business object.
5. To understand the object's storage concept for the business layer.
......

The concept of dependence

I think this is a good business layer can be the most important concept.
In my system framework design will be completed to begin the design involved in the business layer, I head a blank book, we mostly discuss the structure of the system to the service layer from the UI layer to the data access layer to the database. In the end how the organization of the business layer? Martin Fowler's POEAA book did not answer. Find related books are also too vague. Martin Fowler's analysis patterns of some use, but not systematic. By Martin fowler site, I got
Domain Driven Design of pre-release versions. The book gave me great insight. Main points are:
On the association:
1.Imposing a traversal direction (force an associated navigation directions)
......
About Responsibility Layers (business functions layer) of the division:
On three guiding principles are given: Conceptual dependency. (The concept of dependence) as one of them.
The book gives a description of the operational responsibilities of the upper layer of the object need to lower the object to the concept of integrity,
On the contrary the lower object can exist independent of the meaning of the upper object. Such natural objects relative to the upper lower and more stable object. And the process of evolution in the future, so that with the expansion approach to improve the system, not the way to change the object.
Through practice, I think that this principle can be applied to any two objects associated with the business. Can usually rely on first establishing the concept of a navigation direction. This can satisfy most needs. When do need to reverse navigation,
Added at any time as long as justified, and if the two objects previously placed in different packages, then they need to be merged into a single package.
I have seen a bad design. Customer Flag were labeled with many of the customers if they report the loss, frozen, cancel and so on.
Usually called the client state, but this is wrong, contrary to the principle of single responsibility. In fact in addition to write-off plug should not be counted as loss and freezing of the essential attribute of Customer. On the contrary I see them as a constraint, and then to report the loss as a protocol ..... because the concept of Customer may not rely on the concept of reporting the loss and freezing the contrary, have to rely on reporting the loss and freezing
Customer concept, it should be the subject of their actions.
The outset the same way as Customer has GetAccount bad. Because the concept does not rely on Customer Account
XXXAccount it can have the properties of Customer, Account conceptually dependent on Customer.

In accordance with the principles of the concept of dependence that we can better understand the level of division of operational responsibilities. DDD duties proposed in the following layer.
By highest to lowest were:

Dependent on the direction of

Decision
Policy
Commitment
Operation
V Potential

Potential to include a similar Customer, Employee and other Party's class. Corresponding to support the business.
Operation includes the core business such as deposit, transaction and operations associated with these Account, Product, etc..
Commmitment for clients including the agreements signed with customers. For the employees, including the authorization.
Policy including the calculation of certain fees and charges policy, such as telecommunications charges algorithms. Corresponding to support the business.
Decision, including the main corresponds to the management business. Monitoring system and more in this layer.
Observations from top to bottom, very good idea to follow the principle of reliance.
From another perspective, the development over time according to the order of the concept to establish the relationship between objects. This will naturally meet the principles of the concept of dependence.
Developed the concept behind the front can rely on existing concepts, which in turn, this can not be. This is the system the key to stability.
The various agreements signed with the customer can continue to develop, but the client object is stable.
Similarly charging strategy can change, but ultimately reflected in the account of the changes are only on the Balance. Therefore, pricing strategy more volatile than the account.
Target customers are also stable than the account object.

In accordance with the direction of stability from the dependency principle, we can get one-way dependency between objects. Of course, there will be two-way associated with the object, but this is not in my practice a lot. And once you understand the benefits of a one-way association, you will be careful to use two-way association. Abuse association will make the whole business layer as DDD said, and turned into a large "jelly" to whatever you touch a piece of jelly, the jelly will tremble.
Similarly, to simplify the design, object relations-many relationships to avoid. If you can limit the role through the conversion to many or one to one relationship.

These are dependent on the concept of the concept, let's take a look at how to model business activities.
One approach is to use the model in the control class map directly to the design of the class. It seems to me that this is not good practice.
Here to talk about the difference between analysis and design.
From the analysis point of view, the business entity is always passive. Business is by controlling the operation of business entities object to be completed.
Analysis we are concerned about what it is. This requires us to describe objective reality.
In the design stage our concern is how to solve the problem. Exert control object operations and business entities to join does not involve a third party, then this operation can be incorporated into the operation of the entity class. However, the concept of the control object is so profound, so that only involves Customer's ChangePassword method became the place where the problem. Classes are not
"A concept the concept of interest + property + the ultimate imposition of these attributes on the operation" of the package, then what is it?
The following question is how to model the operation across multiple business entities?
For example: opening a bank account.
Now suppose that when opening a number of operations related to the following object.
Create a Customer object.
Create a CapitalAccount object.
Deposit a certain amount of cash.
Record an account water.
The business activities, I can be modeled as OpenCustomerAct object. Pseudo code is as follows:

 
public

 class OpenCustomerAct extends

 CustomerAct 
{ 
... 
public

 void override doRun() 
{ 
Customer customer = Customer.create(...); 
CapitalAccount capitalAccount = CapitalAccount.create(customer,...); 
capitalAccount.deposit(...); 
OpenCustomerLog.create(this

); 
} 
... 
} 


Parameters required by the constructor are.
All business activities will be modeled as an Act, it is very important. You can even put in the Session in an Act to represent the ongoing business. All extensions are starting from the Act.
If you want to put a check on the Act, then the intercept of the doRun way to achieve that purpose.
Use cases can be reduced to only process the same token Act can also be done.
For as RichClient interactive mode, usually only in the final submission of business in the middle of the interaction are ready to submit data.
So the method call in the middle can not only new XXXAct Executive doRun operation. This is because the middle of the call may be used as a context XXXAct. Fortunately, I do not think the middle of this process, how to trigger pre-implantation to donRun check? Perhaps you can create an empty subclass of doRun overwrite the actual operation of the parent class?

 
Act 

public

 interface

 Act 
{ 
Operator getOperator();// Who   


Date getOccurDate();// What time of day   


String

 getOccurPlace();// What locations   


BusinessType getBusinessType();// What business   


  ActState getActState();// The current state of business operations   


} 


"Who what when and where and what to do business."
This describes the essential aspects of any business. From a philosophical point of view, "we get Act, we have the foundation of things."
When we describe a specific business, if the caller needs to expose specific properties.
We can always add to the Act of the sub-interface.
For example, associated with the Customer's Act can be defined as:

 
public

 interface

 CustomerAct extends

 Act 
{ 
Cutomer getCustomer();// For which customer   


} 


In more complex cases, such as business collaboration requires people to complete, can achieve their goals through the combination mode.

 
public

 interface

 CompositeAct extends

 Act 
{ 
Act[] getActs(); 
} 


Involves a period of time have intermediate workflow also can be used as a sub-interface extensions Act.
But I have not done this attempt.

The Act into the Session

The Act makes it possible to easily get into the Session to running a business context. And by extending the Act.
From the Act or its sub-interfaces have wanted anything, which makes no extensions are possible.

Here to explain the position should be placed in Class Act Potential layer, and together with the Operator.
Potential business object layer as needed to maintain operations.
If your frame Sesion in the more basic package, you can empty the contents to Act a parent interface, where the package into the Session.

 
public

 interface

 AbstractAct 
{ 
} 

public

 interface

 Act extends

 AbstractAct 
{ 
... 
} 
Session With the entry to get AbstractAct  . 
public

 class Session 
{ 
... 
static

 public

 AbstractAct getAbstractAct() 
{ 
return

 Instance().abstractAct; 
} 
... 
} 


Act on the extension points

In accordance with the hierarchical view, does not allow reliance on lower top, but the business object is to complete a collaborative purposes.
And as long as the business object needs to maintain, you need the relevant Act.
For example: deposit money banks in business, refer to the above layer, we put it into the Operation layer.
In the saving business, we need to check whether the client has done a report of loss. The report of loss agreement that we are on the Commitment level.
Clearly, Operation layer can not directly call Commitment layer protocol.
DIP model spoke up "with me."
Commitment is defined in the Operation layer layer interface, and a factory, using reflection to achieve this call. Call in the Act.

 
abstract

 public

 class ActImpl 
extends

 abstractActImpl 
implements

 Act 
{ 
public

 virtual void run() 
{ 
doPreprocess(); 
doRun(); 
doPostprocess(); 
} 
abstract

 public

  doPreprocess(); 
abstract

 public

  doRun(); 
abstract

 public

  doPostprocess(); 
} 

public

 interface

 CustomerCommitment 
{ 
void affirmCanDo(); 
} 

abstract

 public

 class CustomerActImpl 
extends

 ActImpl 
implements

 CustomerAct 
{ 
... 
public

 override void doPreprocess() 
{ 
... 
// Extension points   


CustomerCommitment customerCommitment = CustomerCommitmentFactory.create(this

); 
customerCommitment.affirmCanDo(); 
... 
} 
... 
} 

public

 interface

 InnerCustomerCommitment 
{ 
void affirmCanDo(CustomerAct customerAct); 
} 

public

 class CustomerCommitmentImpl implements

 CustomerCommitment 
{ 
private

 CustomerAct customerAct; 

public

 CustomerCommitmentImpl(CustomerAct customerAct) 
{ 
this

.customerAct = customerAct; 
} 

public

 void affirmCanDo() 
{ 
... 

// By configuring the corresponding need to get this customerAct check constraint  , Includes the Protocol, Checklist  . 


DomainObjectCollection commitmentTypes = CustomerCommimentRepository.findByBusinessType(customerAct.getBusinessType()); 

... 
foreach( CommitmentType typeItem in commitmentTypes ) 
{ 
InnerCustomerCommitment commitment = getCommitment(typeItem); 
commitmentItem.affirmCanDo(customerAct); 
} 
... 
} 
} 

public

 class CustomerLostReportAgreementChecker implements

 InnerCustomerCommitment 
{ 
public

 void affirmCanDo(CustomerAct customerAct) 
{ 
Check.require(customerAct.getCustomer() != null

," The customer does not exist  "

); 

CustomerLostReportAgreement customerLostReportAgreement = 
CustomerLostReportAgreementRepository.find(customerAct.getCustomer()); 

if

(customerLostReportAgreement != null

) 
{ 
agreement.affirmCanDo(customerAct); 
} 

} 
} 

public

 class CustomerLostReportAgreement 
{ 
... 
public

 void AffirmCanDo(CustomerAct customerAct) 
{ 
if

(customerAct.getOccurDate <= expiringDate) 
throw

 new

 CustomerLossReportedException(customer); 
} 
... 
} 


Similarly, the object can be used for other upper DIP so dependent inversion.
Such as: telecommunications costing. On the doRun can insert in the CustomerAct extension points to implement.
Such a complex billing algorithm was encapsulated in the interface later. Can allocate additional staff to develop.
Business process activities are still clearly visible.
Yes ah, this is the power of interfaces, most of the design pattern is based on this principle is not it?

There are points in the Act on the extension can be divided into two categories, explicit and implicit.
Telecom is the explicit calculation of the cost, because CustomerAct need to know the calculation, the amount to be deducted from your account.
The inspection report of loss agreement is implicit, CustomerAct can know nothing about this.

By the Act on the extension, we can expand upward.
This seems kind of fungus on the tree, huh, huh.

DIP VS Facade

For the above situation, another approach is to use Facade.
Let us compare the two.
Facade briefly explain the practice:

 
abstract

 public

 class CustomerActImpl 
extends

 ActImpl 
implements

 CustomerAct 
{ 
... 
public

 override void doPreprocess() 
{ 
... 

// Note  : Here the passed parameters, will make available  Facade Way of the dissenters  . 


// In accordance with the requirements of the current delivery of loss  getBusinessType(),getCustomer(),getOccurDate() Is enough   


// But for all the CustomerCommitment these parameters is not necessarily enough  . 


// For example,  : Customer may specify employee agreement signed  .( Refers to only allow protocol specified in the business of the staff operations  ) 


// The interface needs to be added  getOperator() Parameters  . 


// The interface becomes unstable  . 


CustomerCommitmentManager.affirmCanDo(getBusinessType(),getCustomer(),getOccurDate(),?,...); 
... 
} 
... 
} 


Facade can be made in the Act is only a call point, but because it is not dependent on the relationship upside down, had shown the need to use parameters.
Instead use the DIP model, the interface is defined in Act interface, while the Act can be extensible. (Whether to expand all of the objects to see whether the top).
It is precisely because the corresponding CustomerCommitment always need to check the XXXAct in the upper. This specific CustomerCommitment
Can always rely on XXXAct. So you want to get any information available.

The same calculation for the cost of telecommunications example, because the parameters passed is CustomerAct interfaces. So for any possible future expansion of the interface is not changing.
Able to do this, thanks to the fully costed into the Operation of the upper Policy, you can appreciate the essentials it?

Image point, using the DIP model, taken to be an expert mode.
DIP of the Act says that: "CustomerCommitment you look at my current situation, but also to run it?"
Instead Facade pattern, it is boring chatter mode.
Facade of the Act says that: "CustomerCommitment, that the implementation of the client is XXX, business is XXX, time is XXX, ... you can tell I can run forever?"
DIP obviously much more to casual.

VS implement an interface inherits the parent class

A slight digression here to discuss about interfaces with the question of succession.
When using the interface? When to use inheritance?
This seems to be feeling and experience of the problem. Or we will prefer to use interface, and less use of inheritance.
Could it further?
The following is my opinion:

"Interface is the result of the caller asked, and inheritance is thought to achieve the product side."

After all, if we define the interface is not used, then it is of no use.
The purpose of the development of virtual interfaces standard, so that the caller does not depend on the implementation side.
The succession of a parent class is largely based on "lazy" and consider what already exists, why not use a little?
Of course, this ignores the real meaning of inheritance - single point of maintenance.

Therefore, the definition of XXXAct interface, you need to take account of the upper object needs to provide any Act of the feature, how to use it.

Interfaces belong to the caller.

Persistent business objects

A controversial issue will be, is the business layer will involve the concept of business object persistence.
The answer is yes.
DDD in the description The life cycle of a domain object when given two forms of persistence.
Store and Archive. We use the more is the Store.

But this does not mean that the business layer depends on the data access layer. Instead dependency should be reversed. Data access layer relies business layer. Usually we use the Mapper to achieve, through the hibernate configuration for this purpose.
To do business layer does not depend on the data access layer, with interfaces to do the same.
Data access in the business layer defines the interfaces, to facilitate the, Ke Yi to use a class to encapsulate the Operation .

 
public

 interface

 CustomerFinder 
{ 
Customer findByID(ID id); 
Customer findByCode(String

 code); 
DomainObjectCollection findByName(String

 name); 
... 
} 

public

 class CustomerRepository 
{ 
private

 static

 CustomerFinder finder = null

; 
private

 static

 CustomerFinder getFinderInstance() 
{ 
if

 (finder == null

) 
{ 
finder = (CustomerFinder)FinderRegistry.getFinder("CustomerFinder"

); 
} 
return

 finder; 
} 

public

 static

 Customer findByID(ID id) 
{ 
Customer obj = getFinderInstance().findByID(id); 
Check.require(obj != null

, 
" ID is not found  :"

 + id.toString() + 
" The corresponding   Customer."

); 
return

 obj; 
} 
... 
} 


In the data access layer to achieve these interfaces. Data access layer because it is dependent on the business layer, so you can use a variety of techniques to achieve,
Use of open source projects like hibernate, or hand-written Mapper.

ID id

Another controversial issue is whether the Domain layer of non-business related to the introduction of ID to identify the different objects it?
My experience is in the business layer to introduce the concept of ID make a lot of things easier.
Such as: Lazyload.
Is this not the scope of business? Is not a business concept. But business is not without the corresponding concept.
For example: customer order information stored order is the order number as identification, which is used by people.
The use of computers, we can also give an understanding of the unity of object identification, this is the ID.
Also do not use the concept of business as the primary keys and foreign keys, because they are not the database concept.
Otherwise, it will make the business concept of confusion with the concept with the database.

ID is normally choose more efficient long type.
However, the realization that we go further, we will be the package for the ID object.

Service layer

Now we look at the business layer wrapped up the service layer.
Service layer is set up in the application layer and business layer of the bridge, used to package the business layer access, service layer can be seen as an intermediary, as two roles:
One. Realize the application layer interface requirements of the interfaces;
2. As a business layer appearance.
The typical service layer call is as follows:

 
public

 interface

 CustomerServices 
{ 
void openCustomer(CustomerInfo cutomerInfo); 
void customerLostReport(String

 customerCode,Date expiringDate,String

 remark); 
CutomerBasicInfo getCutomerBasicInfo(String

 customerCode); 
... 
} 

public

 class CustomerServicesImpl 
extends

 ServiceFacade 
implements

 CustomerServices 
{ 
... 
public

 void openCustomer(CustomerInfo cutomerInfo) 
{ 
try

 
{ 
init(); 

OpenCustomerAct openCustomerAct = 
new

 OpenCustomerAct(customerInfo.name, 
customerInfo.code, 
customerInfo.address, 
customerInfo.plainpassword 
... 
); 
openCustomerAct.run(); 

commit(); 
} 
catch

(Exception e) 
{ 
throw

 ExceptionPostprocess(e); 
} 
} 

public

 void customerLostReport(String

 customerCode,Date expiringDate,String

 remark) 
{ 
try

 
{ 
Check.require(customerCode != null

 && customerCode != "", 
" The client code is not valid  :"

 + customerCode); 
init(); 

CustomerLostReportAct customerLostReportAct = 
new

 CustomerLostReportAct(customerCode, 
expiringDate, 
remark); 
customerLostReportAct.run(); 

commit(); 
} 
catch

(Exception e) 
{ 
throw

 ExceptionPostprocess(e); 
} 
} 

public

 CutomerBasicInfo getCutomerBasicInfo(String

 customerCode) 
{ 
try

 
{ 
Check.require(customerCode != null

 && customerCode != "", 
" The client code is not valid  :"

 + customerCode); 
init(); 
Customer customer = CustomerRepository.findByCode(customerCode); 

// Here is thrown out at CustomerRepository  CustomerNotFoundException Exception  , 


// Another approach is to throw at CustomerRepository  CustomerNotFoundException Exception  . 


// Because CustomerRepository is from client code to find the corresponding customer  . As regards whether should throw   


// The exception is handed over to the business tier or service layer to handle  . 


// There are subtle differences, throw  CustomerNotFoundException Who's responsibilities?  ? 


// What are your thoughts with other users.  ?:) 


if

(customer == null

) 
throw

 new

 CustomerNotFoundException(customerCode); 

CutomerBasicInfo cutomerBasicInfo = CutomerBasicInfoAssembler.create(customer); 
return

 cutomerBasicInfo; 
} 
catch

(Exception e) 
{ 
throw

 ExceptionPostprocess(e); 
} 
} 

... 
} 


Service layer code is very simple, is not it?

The above code can be further simplified by AOP. I hope to use AOP to achieve this simple code like the following.

public
 class CustomerServicesImpl 
implements
 CustomerServices 
{ 
... 
public
 void openCustomer(CustomerInfo cutomerInfo) 
{ 
OpenCustomerAct openCustomerAct = 
new
 OpenCustomerAct(customerInfo.name, 
customerInfo.code, 
customerInfo.address, 
customerInfo.plainpassword 
... 
); 
openCustomerAct.run(); 
} 

public
 void customerLostReport(String
 customerCode,Date expiringDate,String
 remark) 
{ 
Check.require(customerCode != null
 && customerCode != "", 
" The client code is not valid  :"
 + customerCode); 
CustomerLostReportAct customerLostReportAct = 
new
 CustomerLostReportAct(customerCode, 
expiringDate, 
remark); 
customerLostReportAct.run(); 
} 

public
 CutomerBasicInfo getCutomerBasicInfo(String
 customerCode) 
{ 
Customer customer = CustomerRepository.findByCode(customerCode); 
if
(customer == null
) 
throw
 new
 CustomerNotFoundException(customerCode); 

CutomerBasicInfo cutomerBasicInfo = CutomerBasicInfoAssembler.create(customer); 
return
 cutomerBasicInfo; 
} 

 




DTO or Not

I think it depends on the size of the project using the DTO, the development team's structure and the evolution of the expected results of the assessment project.
Do not use DTO directly passed to the application layer using the PO apply to a person while the application layer and business layer is responsible for short-term simple projects;
Once adopted the model as a framework, I do not know whether the service layer could be called object-oriented.
The following reasons:
1. DTO using PO assume responsibility passed to the application layer, forced the PO can not contain business logic, it will be exposed to the application business logic layer.
Business logic classes will be similar to the XXXManager commitment, so it seems PO have more reuse opportunities because getXXX with setXXX PO contains only similar attributes.
However, this is similar to the example of process-oriented model, using the method of operation of the structure, procedures, how many returned to the process-oriented approach.
2. The PO directly passed to the application layer, forcing the application layer depends on the business level, if a person is also responsible for the application layer and business layer so no problem;
If it is developed by different people, will allow application-level developers must understand the details of the structure of business object layer, application layer increased the scope of the developer's knowledge.
At the same time as this coupling, the parallel development of affected exchanges increased.
3. In addition, it also allows the business layer in the Construction of PO to be especially careful when, because of the need to consider transmission efficiency to the application layer, business layer in the building need to consider the application layer of the need to address the problem is not strange?

Some people will complain too much trouble to write XXXAssember, my experience is XXXAssembler very simple.

We use the phone, you will find most of the phones available to the interface are the same, including the 0-9 number keys, the green answer button, the red hang up key, there are a display.
Whether I get NOkIA, or a MOTO phone, I can use as a mobile phone user I do not need to know the structure of cell phone interface, not concerned about using a SmartPhone or Symbian.

Indeed, the application layer service layer and business layer as a black box is much better than as a white box.
  • del.icio.us
  • StumbleUpon
  • Digg
  • TwitThis
  • Mixx
  • Technorati
  • Facebook
  • NewsVine
  • Reddit
  • Google
  • LinkedIn
  • YahooMyWeb

Related Posts of Domain Model Exploration

  • DWR filters and exception handling

    Just modify dwr.xml: <dwr> <allow> <create javascript="UserService" creator="spring"> <param name="beanName" value="userService"> </ param> </ create> <! - Call UserService of

  • struts2 ajax verify the existence of input values

    struts2 ajax verify the existence of input values Today to do the struts2 ajax validate input regarding the existence of the function, and now share with everyone, I hope everyone many opinions!!! input.jsp page code: <html> <body> <s: ...

  • Ext2.2 + json + jsp questions to obtain background data - Ajax

    Ext-2.2 in the study, we will first study it usually comes with some examples, today found an example about paging, it is to use php access to json format data, And I found a lot of people online through java access to background data, so I wrote a jsp ac

  • Struts Spring Hibernate test Noodles

    Hibernate working principle and why to use? Principle: 1. To read and parse configuration file 2. Read and analytic mapping information, create a SessionFactory 3. Open Sesssion 4. Create Affairs transation 5. Persistence operation 6. Submitted Services 7

  • js examples of common events

    <html> <head> <script type="text/javascript"> / / Which mouse button is clicked function whichButton1 (event) ( if (event.button == 2) ( alert ( "You clicked the right mouse button!") ) else ( alert ( "You c ...

  • SUI-JavaScript rich UI library integration solution

    Introduction: SUI is not a class implementation of the UI, nor is it a standard set of UI markup language, it is just to help the existing UI frameworks (such as Ext, YUI like) to mark the way to the statement and the creation of UI. The names of these ta

  • FLEX: integrating Spring + Hibernate

    Before a friend also wanted to study development of FLEX. Asked me to help him to be a small sample. Spent a weekend time, to integrate a sampleproject. Client: FLEX Server: Spring2.5 + Hibernate3.2 + Hibernate-annotations3.3.1 + MySQL5 FDS: BlazeDS3 IDE:

  • [Reprint] Java professionals required books and list of sites

    Concurrent Programming in Java: Design Principles and Patterns (Doug Lea) Concurrent Programming in Java: Design Principles and Patterns, 2nd edition (Doug Lea; Addison-Wesley, 1999 years) Java Concurrent Programming - Design principles and patterns (seco

  • In the servlet use Bean

    According to Sun's definition, JavaBean is a reusable software components. In fact JavaBean is a Java class, through the package into a property and methods of treatment of a function or a business object, referred to as bean. Because JavaBean is ...

blog comments powered by Disqus
Recent
Recent Entries
Tag Cloud
Random Entries