Note that there are some explanatory texts on larger screens.

plurals
  1. PODescribe the architecture you use for Java web applications?
    text
    copied!<p><strong>Let's share Java based web application architectures!</strong></p> <p>There are lots of different architectures for web applications which are to be implemented using Java. The answers to this question may serve as a library of various web application designs with their pros and cons. While I realize that the answers will be subjective, let's try to be as objective as we can and motivate the pros and cons we list.</p> <p>Use the detail level you prefer for describing your architecture. For your answer to be of any value you'll at least have to describe the major technologies and ideas used in the architecture you describe. And last but not least, <em>when</em> should we use your architecture?</p> <p>I'll start...</p> <hr> <h1>Overview of the architecture</h1> <p>We use a 3-tier architecture based on open standards from Sun like Java EE, Java Persistence API, Servlet and Java Server Pages.</p> <ul> <li>Persistence</li> <li>Business</li> <li>Presentation</li> </ul> <p>The possible communication flows between the layers are represented by:</p> <pre><code>Persistence &lt;-&gt; Business &lt;-&gt; Presentation </code></pre> <p>Which for example means that the presentation layer never calls or performs persistence operations, it always does it through the business layer. This architecture is meant to fulfill the demands of a high availability web application.</p> <h2>Persistence</h2> <p>Performs create, read, update and delete (<a href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete" rel="noreferrer">CRUD</a>) persistence operations. In our case we are using (<a href="http://java.sun.com/javaee/technologies/persistence.jsp" rel="noreferrer">Java Persistence API</a>) JPA and we currently use <a href="http://www.hibernate.org/" rel="noreferrer">Hibernate</a> as our persistence provider and use <a href="http://www.hibernate.org/397.html" rel="noreferrer">its EntityManager</a>.</p> <p>This layer is divided into multiple classes, where each class deals with a certain type of entities (i.e. entities related to a shopping cart might get handled by a single persistence class) and is <em>used</em> by one and only one <em>manager</em>.</p> <p>In addition this layer also stores <a href="http://en.wikipedia.org/wiki/Java_Persistence_API#Entities" rel="noreferrer">JPA entities</a> which are things like <code>Account</code>, <code>ShoppingCart</code> etc.</p> <h2>Business</h2> <p>All logic which is tied to the web application functionality is located in this layer. This functionality could be initiating a money transfer for a customer who wants to pay for a product on-line using her/his credit card. It could just as well be creating a new user, deleting a user or calculating the outcome of a battle in a web based game.</p> <p>This layer is divided into multiple classes and each of these classes is annotated with <code>@Stateless</code> to become a <a href="http://en.wikipedia.org/wiki/Session_Beans" rel="noreferrer">Stateless Session Bean</a> (SLSB). Each SLSB is called a <em>manager</em> and for instance a manager could be a class annotated as mentioned called <code>AccountManager</code>.</p> <p>When <code>AccountManager</code> needs to perform CRUD operations it makes the appropriate calls to an instance of <code>AccountManagerPersistence</code>, which is a class in the persistence layer. A rough sketch of two methods in <code>AccountManager</code> could be:</p> <pre><code>... public void makeExpiredAccountsInactive() { AccountManagerPersistence amp = new AccountManagerPersistence(...) // Calls persistence layer List&lt;Account&gt; expiredAccounts = amp.getAllExpiredAccounts(); for(Account account : expiredAccounts) { this.makeAccountInactive(account) } } public void makeAccountInactive(Account account) { AccountManagerPersistence amp = new AccountManagerPersistence(...) account.deactivate(); amp.storeUpdatedAccount(account); // Calls persistence layer } </code></pre> <p>We use <a href="http://java.sun.com/javaee/5/docs/tutorial/doc/bncij.html" rel="noreferrer">container manager transactions</a> so we don't have to do transaction demarcation our self's. What basically happens under the hood is we initiate a transaction when entering the SLSB method and commit it (or rollback it) immediately before exiting the method. It's an example of convention over configuration, but we haven't had a need for anything but the default, Required, yet.</p> <p>Here is how The Java EE 5 Tutorial from Sun explains the <a href="http://java.sun.com/javaee/5/docs/tutorial/doc/bncij.html" rel="noreferrer">Required transaction attribute</a> for Enterprise JavaBeans (EJB's):</p> <blockquote> <p>If the client is running within a transaction and invokes the enterprise bean’s method, the method executes within the client’s transaction. If the client is not associated with a transaction, the container starts a new transaction before running the method.</p> <p>The Required attribute is the implicit transaction attribute for all enterprise bean methods running with container-managed transaction demarcation. You typically do not set the Required attribute unless you need to override another transaction attribute. Because transaction attributes are declarative, you can easily change them later.</p> </blockquote> <h2>Presentation</h2> <p>Our presentation layer is in charge of... presentation! It's responsible for the user interface and shows information to the user by building HTML pages and receiving user input through GET and POST requests. We are currently using the old <a href="http://java.sun.com/products/servlet/" rel="noreferrer">Servlet</a>'s + Java Server Pages (<a href="http://java.sun.com/products/jsp/" rel="noreferrer">JSP</a>) combination.</p> <p>The layer calls methods in <em>managers</em> of the business layer to perform operations requested by the user and to receive information to show in the web page. Sometimes the information received from the business layer are less complex types as <code>String</code>'s and <code>int</code>egers, and at other times <a href="http://en.wikipedia.org/wiki/Java_Persistence_API#Entities" rel="noreferrer">JPA entities</a>.</p> <h1>Pros and cons with the architecture</h1> <h2>Pros</h2> <ul> <li>Having everything related to a specific way of doing persistence in this layer only means we can swap from using JPA into something else, without having to re-write anything in the business layer.</li> <li>It's easy for us to swap our presentation layer into something else, and it's likely that we will if we find something better.</li> <li>Letting the EJB container manage transaction boundaries is nice.</li> <li>Using Servlet's + JPA is easy (to begin with) and the technologies are widely used and implemented in lots of servers.</li> <li>Using Java EE is supposed to make it easier for us to create a high availability system with <a href="http://en.wikipedia.org/wiki/Load_balancing_(computing)" rel="noreferrer">load balancing</a> and <a href="http://en.wikipedia.org/wiki/Failover" rel="noreferrer">fail over</a>. Both of which we feel that we must have.</li> </ul> <h2>Cons</h2> <ul> <li>Using JPA you may store often used queries as named queries by using the <code>@NamedQuery</code> annotation on the JPA entity class. If you have as much as possible related to persistence in the persistence classes, as in our architecture, this will spread out the locations where you may find queries to include the JPA entities as well. It will be harder to overview persistence operations and thus harder to maintain.</li> <li>We have JPA entities as part of our persistence layer. But <code>Account</code> and <code>ShoppingCart</code>, aren't they really business objects? It is done this way as you have to touch these classes and turn them into entities which JPA knows how to handle.</li> <li>The JPA entities, which are also our business objects, are created like Data Transfer Objects (<a href="http://en.wikipedia.org/wiki/Data_Transfer_Object" rel="noreferrer">DTO</a>'s), also known as Value Objects (VO's). This results in an <a href="http://en.wikipedia.org/wiki/Anemic_Domain_Model" rel="noreferrer">anemic domain model</a> as the business objects have no logic of their own except accessor methods. All logic is done by our managers in the business layer, which results in a more procedural programming style. It's not good object oriented design, but maybe that's not a problem? (After all object orientation isn't the only programming paradigm which has delivered results.)</li> <li>Using EJB and Java EE introduces a bit of complexity. And we can't use purely Tomcat (adding an EJB micro-container isn't <em>purely</em> Tomcat).</li> <li>There are lots of issues with using Servlet's + JPA. Use Google for more information about these issues.</li> <li>As the transactions are closed when exiting the business layer we can't load any information from JPA entities which is configured to be loaded from the database when it's needed (using <code>fetch=FetchType.LAZY</code>) from inside the presentation layer. It will trigger an exception. Before returning an entity containing these kinds of fields we have to be sure to call the relevant getter's. Another option is to use Java Persistence Query Language (<a href="http://java.sun.com/javaee/5/docs/tutorial/doc/bnbtg.html" rel="noreferrer">JPQL</a>) and do a <code>FETCH JOIN</code>. However both of these options are a little bit cumbersome.</li> </ul>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload