Great book written by Rod Johnson.
I wanted to share few important points i found from this book.
1) Goals of an Enterprise Architecture
a) Be robust Enterprise software is important to an organization. Its users expect it to be reliable and bugfree.Hence we must understand and take advantage of those parts of J2EE that can help us build robust solutions and must ensure that we write quality code.
b) Be performant and scalable
Enterprise applications must meet the performance expectations of their users. They must also exhibit sufficient scalability – the potential for an application to support increased load, given appropriate hardware. Scalability is a particularly important consideration for Internet applications, for which it is difficult to predict user numbers and behavior. Understanding the J2EE infrastructure is essential for meeting both these goals. Scalability will typically require deploying multiple server instances in a cluster. Clustering is a complex problem requiring sophisticated application server functionality. We must ensure that our applications are designed so that operation in a cluster is efficient.
c) Take advantage of OO design principles
OO design principles offer proven benefits for complex systems. Good OO design practice is promoted by the use of proven design patterns – recurring solutions to common problems.
d) Avoid unnecessary complexity
Practitioners of Extreme Programming (XP) advocate doing "the simplest thing that could possibly work". We should be wary of excessive complexity that may indicate that an application architecture isn't working. Due to the range of components on offer, it's tempting to over-engineer J2EE solutions, accepting greater complexity for capabilities irrelevant to the business requirements. Complexity adds to costs throughout the software lifecycle and thus can be a serious problem. On the other hand, thorough analysis must ensure that we don't have a naïve and simplistic view of requirements.
e) Be maintainable and extensible
Maintenance is by far the most expensive phase of the software lifecycle. It's particularly important to consider maintainability when designing J2EE solutions, because adopting J2EE is a strategic choice. J2EE applications are likely to be a key part of an organization's software mix for years, and must be able to accommodate new business needs. Maintainability and extensibility depend largely on clean design. We need to ensure that each component of the application has a clear responsibility, and that maintenance is not hindered by tightly-coupled components.
f) Be delivered on time
Productivity is a vital consideration, which is too often neglected when approaching J2EE.
g) Be easy to test
Testing is an essential activity throughout the software lifecycle. We should consider the implications of design decisions for ease of testing.
h) Promote reuse
Enterprise software must fit into an organization's long term strategy. Thus it's important to foster reuse, so that code duplication is minimized (within and across projects) and investment leveraged to the full. Code reuse usually results from good OO design practice, while we should also consistently use valuable infrastructure provided by the application server where it simplifies application code.
2) Compelling Arguments for Using EJB
Here are a few arguments that strongly suggest EJB use:
To allow remote access to application components This is a compelling argument if remote access over RMI/IIOP is required. However, if web services style remoting is required, there's no need to use EJB.
To allow application components to be spread across multiple physical servers EJBs offer excellent support for distributed applications. If we are building a distributed application, rather than adding web services to an application that isn't necessarily distributed internally, EJB is the obvious choice.
To support multiple Java or CORBA client types If we need to develop a Java GUI client (using Swing or another windowing technology), EJB is a very good solution. EJB is interoperable with CORBA's IIOP and thus is a good solution for serving CORBA clients. As there is no web tier in such applications, the EJB tier provides
the necessary middle tier. Otherwise, we return to the days of client-server applications and limited scalability because of inability to pool resources such as database connections on behalf of multiple clients.
To implement message consumers when an asynchronous model is appropriate Message-driven beans make particularly simple JMS message consumers. This is a rare case in which EJB is "the simplest thing that could possibly work".
3) EJBs are a good solution to problems of distributed applications and complex transaction management. However, many applications don't encounter these problems. EJBs add unnecessary complexity in such applications. An EJB solution can be likened to a truck and a web application to a car. When we need to perform certain tasks, such as moving large objects, a truck will be far more effective than a car, but
when a truck and a car can do the same job, the car will be faster, cheaper to run,more maneuverable and more fun to drive.
4) Good OO design practice is fundamental to a sound architecture. J2EE technologies should be applied in pursuit of a sound object model, and should not dictate the object model itself.
5) Top Mistakes in Choosing an Application Server
In my experience, the following are some of the commonest (and costliest) mistakes in choosing an application server:
o Delusions of grandeur. Spending money and resources on a complex solution to a problem you don't have, even if it's a good solution. A special case of this is the scalability delusion. Although the usage of web applications can increase rapidly, it isn't always vital to be able to support a vast user population, and for many organizations it never will be. This mistake often leads to the waste of money on unnecessarily expensive licenses. An even more harmful result can be increase in costs throughout the project lifecycle because an unnecessarily sophisticated product is unnecessarily complex to administer, given the actual business requirements.
o Failure to consider total cost of ownership, and that license costs are only a part of it.
o Choosing a server without hands-on experience. No amount of third-party reports,benchmarks, and marketing hype substitutes for hands-on experience in-house by the developers who will build the applications that run on the server.
o Decisions handed down by senior management without consulting mere developers and architects.This mistake is sadly prevalent, and usually reflects a fear-based culture that will cripple projects in other ways.
6) What Makes a Good Test Case?
Writing good test cases takes practice. Our knowledge of the implementation (or likely implementation, if we're developing test-first) may suggest potential problem areas; however, we must also develop the ability to think outside the developer role. In particular, it's important to view the writing of a failing test as an achievement, not a problem. Common themes of testing will include:
o Testing the most common execution paths (these should be apparent from the application use cases)
o Testing what happens on unexpected arguments
o Testing what happens when components under test encounter errors from components they use
7) As J2EE applications tend to be large and complex, it's vital that we follow sound OO design practice, adopt consistent coding conventions, and leverage existing investment – whether our own or that of third parties.
The first two concern code quality, at object-design and code level. What are we trying to achieve? What is good code? These are a few of its characteristics:
Good code is extensible without drastic modification. It's easy to add features without tearing it apart.
Good code is easy to read and maintain.
Good code is well documented.
Good code makes it hard to write bad code around it. For example, objects expose clean,easy-to-use interfaces that promote good use. Both good code and bad code breed.
Good code is easy to test.
Good code is easy to debug. Remember that even if a piece of code works perfectly, it's still a problem if it doesn't favor debugging. What if a developer is trying to track down an error in imperfect code, and the stack trace disappears into perfect but obscure code?
Good code contains no code duplication.
Good code gets reused.
8) Program to interfaces, not classes. This decouples interfaces from their implementations.Using loose coupling between objects promotes flexibility. To gain maximum flexibility,declare instance variables and method parameters to be of the least specific type required.
9) Object composition (in which new functionality is obtained by assembling or composing objects) is more flexible than concrete inheritance, and Java interfaces make delegation natural. Object composition allows the behavior of an object to be altered at run time, through delegating part of its behavior to an interface and allowing callers to set the implementation of that interface. The Strategy and State design patterns rely on this approach.
10) The Template Method Design Pattern
One good use of concrete inheritance is to implement the Template Method design pattern.The Template Method design pattern (GoF) addresses a common problem: we know the steps of an algorithm and the order in which they should be performed, but don't know how to perform all of the steps.This Template Method pattern solution is to encapsulate the individual steps we don't know how to perform as abstract methods, and provide an abstract superclass that invokes them in the correct order. Concrete
subclasses of this abstract superclass implement the abstract methods that perform the individual steps. The key concept is that it is the abstract base class that controls the workflow. Public superclass methods are usually final: the abstract methods deferred to subclasses are protected. This helps to reduce the likelihood of bugs: all subclasses are required to do, is fulfill a clear contract.
The centralization of workflow logic into the abstract superclass is an example of inversion of control. Unlike in traditional class libraries, where user code invokes library code, in this approach framework code in the superclass invokes user code. It's also known as the Hollywood principle: "Don't call me, I'll call you".Inversion of control is fundamental to frameworks, which tend to use the Template Method pattern heavily.
For example, consider a simple order processing system. The business involves calculating the purchase price, based on the price of individual items, checking whether the customer is allowed to spend this amount,and applying any discount if necessary. Some persistent storage such as an RDBMS must be updated to reflect a successful purchase, and queried to obtain price information. However, it's desirable to separate this from the steps of the business logic.
Use the Template Method design pattern to capture an algorithm in an abstract superclass, but defer the implementation of individual steps to subclasses. This has the potential to head off bugs, by getting tricky operations right once and simplifying user code. When implementing the Template Method pattern, the abstract superclass must factor out those methods that may change between subclasses and ensure that the method signatures enable sufficient flexibility in implementation.
11) The Strategy Design Pattern
An alternative to the Template Method is the Strategy design pattern, which factors the variant behavior into an interface. Thus, the class that knows the algorithm is not an abstract base class, but a concrete class that uses a helper that implements an interface defining the individual steps. The Strategy design pattern takes a little more work to implement than the Template Method pattern, but it is more flexible. The advantage of the Strategy pattern is that it need not involve concrete inheritance. The class that implements the individual steps is not forced to inherit from an abstract template superclass.
I use the Strategy pattern in preference to the Template Method pattern under the following circumstances:
a) When all steps vary (rather than just a few).
b) When the class that implements the steps needs an independent inheritance hierarchy.
c) When the implementation of the steps may be relevant to other classes (this is often the case
with J2EE data access).
d) When the implementation of the steps may need to vary at run time. Concrete inheritance can't accommodate this; delegation can.
e) When there are many different implementations of the steps, or when it's expected that the number of implementations will continue to increase. In this case, the greater flexibility of the Strategy pattern will almost certainly prove beneficial, as it allows maximum freedom to the implementations.
12) The Observer Design Pattern
Like the use of interfaces, the Observer design pattern can be used to decouple components and enable extensibility without modification (observing the Open Closed Principle). It also contributes to achieving separation of concerns.
13) It's helpful to use an IDE that supports refactoring. Eclipse is particularly good in this respect.I believe that refactoring can be extended beyond functional code. For example, we should continually seek to improve in the following areas:
Error messages
A failure with a confusing error message indicates an opportunity to improve the error message.
Logging
During code maintenance, we can refine logging to help in debugging. We'll discuss logging below.
Documentation
If a bug results from a misunderstanding of what a particular object or method does,
documentation should be improved.
14) Inner Classes and Interfaces
Inner classes and interfaces can be used in Java to avoid namespace pollution. Inner classes are often helpers,and can be used to ensure that the outer class has a consistent responsibility.
Understand the difference between static and non-static inner classes. Static inner classes can be instantiated without the creation of an object of the enclosing type; non-static inner classes are linked to an instance of the enclosing type. There's no distinction for interfaces, which are always static.
Inner interfaces are typically used when a class requires a helper that may vary in concrete class, but not in type, and when this helper is of no interest to other classes (we've already seen an example of this).
15) Another OO principle – the Open Closed Principle – states that an object should be open to extension, but closed to modification. By overriding concrete methods, we effectively modify an object, and can no longer guarantee its integrity. Following the Open Closed Principle helps to reduce the likelihood of bugs as new functionality is added to an application, because the new functionality is added in new code, rather than by modifying existing code, potentially breaking it.
Especially in the case of classes that will be overridden by many different subclasses, making superclass methods final when methods cannot be private (for example, if they implement an interface and hence must be public) will simplify the job of programmers developing subclass implementations. For example, most programmers will create subclasses using IDEs offering code helpers: it's much
preferable if these present a list of just those non-final methods that can – or, in the case of abstract methods, must – be overridden.
Making methods final will produce a slight performance gain, although this is likely to be too marginal to be a consideration in most cases.
Note that there are better ways of extending an object than by overriding concrete methods. For example, the Strategy design pattern (discussed earlier) can be used to parameterize some of the object's behavior by delegating to an interface. Different implementations of the interface can be provided at runtime to alter the behavior (but not compromise the integrity) of the object. I've used final methods as
suggested here in several large projects, and the result has been the virtual elimination of bugs relating to corruption of superclass state, with no adverse impact on class reusability.
Final methods are often used in conjunction with protected abstract methods. An idiomatic use of this is what I call "chaining initializers". Consider a hypothetical servlet superclass, AbstractServlet. Suppose that one of the purposes of this convenient superclass is to initialize a number of helper classes required by subclasses. The AbstractServlet class initializes these helper classes in its implementation of the Servlet API init() method.
To preserve the integrity of the superclass, this method should be made final (otherwise, a subclass could override init() without invoking AbstractServlet's implementation of this method, meaning that the superclass state wouldn't be correctly initialized). However, subclasses may need to implement their own
initialization, distinct from that of the superclass. The answer is for the superclass to invoke a chained method in a final implementation of init(), like this:
public final void init() {
// init helpers
//…
onInit();
}
protected abstract void onInit();
The onInit() method is sometimes called a hook method.
16) Below table describes advantages and disadvantages of few techniques.
| Technique | Advantages | Disadvantages |
| Code to interfaces, not concrete classes.The relationship between application components should be in terms of interfaces,not classes. | Promotes design flexibility.Works well when interfaces are implemented by JavaBeans,configured through their bean properties.Doesn't preclude use of concrete inheritance. Implementations can have a parallel but distinct inheritance hierarchy from interfaces. | Marginally more complex to implement than use of concrete inheritance. |
| Prefer object composition to concrete inheritance. | Promotes design flexibility.Avoids problems with Java's lack of multiple concrete inheritance.Enables class behavior to be changed at runtime. | May lead to an increased number of classes. May be overkill for simple requirements. |
| Use the Template Method design pattern when you know how to implement a workflow but not how all individual steps should be implemented. | Ensures that the workflow can be implemented and tested once.Ideal for resolving portability issues in J2EE. | Sometimes delegation is a better model, and the Strategy pattern is preferable. |
| Use the Strategy design pattern as an alternative to the Template Method pattern when the flexibility of delegation, rather than concrete inheritance, is desirable. | There's greater freedom when implementing the interface than using concrete inheritance.The implementation can vary at runtime.The implementation can be shared with other classes | Slightly more complex to implement than the Template Method pattern, which is often an alternative. |
| Use the Observer design pattern. | Promotes separation of concerns by decoupling listeners from the execution of business logic that generates events.Enables extensibility without modification of existing code. | Introduces complexity that isn't always warranted. Requires an event publication infrastructure, and event classes. A rogue observer that blocks can lock an application using this pattern. May not always work in a clustered environment. |
| Use unchecked exceptions for unrecoverable errors,and checked exceptions when calling code is likely to be able to handle the problem. | Less code. More readable code; business logic won't be obscured by catching exceptions that can't be handled. Enhanced productivity. No need to catch, wrap and rethrow exceptions; less likelihood of losing stack traces. | Many Java developers are used to using checked exceptions almost exclusively. When using unchecked exceptions be sure to remember to document those that may be thrown the compiler can't assist. |
| Use final methods appropriately. | Final methods can be used to prevent subclasses incorrectly modifying superclass behavior by overriding methods. | Limits the scope of subclasses to customize superclass behavior. However, overriding concrete methods is a poor way to achieve extensibility. |
17) If we want a distributed application based on RMI/IIOP, EJB is the perfect J2EE technology to help us implement it.
18) Programming Restrictions Applying to EJBs
The individual restrictions can be attributed to three main purposes:
o Clustering
EJBs must be able to run in a cluster, and the EJB container must be free to manage bean instances across a cluster. This means that we cannot rely on assumptions - such as the behavior of static fields,and the implications of synchronization - that hold true within one JVM.
o Thread management
The EJB container must be able to manage threads, and EJBs must not be able to hijack such management by creating their own threads or affecting the execution of container-managed threads.
o Security
The EJB container must be able to manage the security environment of EJBs. Declarative or programmatic security guarantees are worthless if an EJB behaves in an uncontrolled manner.
Below are the few restrictions:
a) EJBs should not use read/write behavior in a cluster.
b) An EJB must not use thread thread synchronized.
c) An EJB must not Threads.This includes starting,stopping, suspending or resuming a thread, or changing a thread's priority or name.
d) An EJB must not attempt to components, so there is no output informatuion to a GUI display or a keyboard display.
e) EJB must not accept Connections on a socket for multicast.
f) EJB Must not attempt to create a classloader or obtain the current classloader.
g) EJB must not attempt to load a native library.
h) An EJB must not attempt to pass this as an argument or method result through its component interface.
19) Transaction Isolation
Transaction isolation levels determine database behavior, but are managed by the J2EE server, which is responsible for overall transaction co-ordination. Transaction isolation levels control the degree of isolation between concurrent transactions accessing the same database. SQL92 defines four transaction isolation levels,which are supported in the JDBC API. In decreasing order of isolation, these are:
o TRANSACTION_SERIALIZABLE
o TRANSACTION_REPEATABLE_READ
o TRANSACTION_READ_COMMITTED
o TRANSACTION_READ_UNCOMMITTED
The higher the level of isolation for a transaction, the greater the guarantee that its work will not be corrupted by other concurrent transactions, but the greater its impact will be on the total throughput of the resource. In the case of a relational database, the transaction isolation level will control the locking of rows or tables (see http://www.onjava.eom/pub/a/onjava/2001/05/23/j2ee.html?page=2 for a good, concise, summary of SQL92 transaction isolation levels).
Most databases don't support all four transaction isolation levels, meaning that aJ2EE server may be unable to guarantee the expected behavior. For example, Oracle does not support the TRANSACTION_READ_UNCOMMITTED isolation level. However, Oracle does guarantee non-blocking reads,which preserve the intent of the READJJNCOMMITTED isolation level.
20) There are two major alternatives for the object granularity entity beans should model: fine-grained and coarse-grained entity beans. If we're working with an RDBMS, a fine-grained entity might map to a row of data in a single table. A coarse-grained entity might model a logical record, which may be spread across multiple
tables, such as a User and associated Invoice items.
21) If using entity beans, below are few overall guidelines:
o Don't use entity beans if your EJB container supports only EJB 1.1
Entity beans as specified in EJB 1.1 were inadequate to meet most real-world requirements.
o Use CMP, not BMP The greater control over the management of persistence offered by BMP is largely illusory. BMP entity beans are much harder to develop and maintain than CMP entity beans, and usually deliver worse performance.
o Use ejbHome() methods to perform any aggregate operations required on your data
ejbHome () methods, which can act on multiple entities, help to escape the row-level access imposed by the entity bean model, which can otherwise prevent efficient RDBMS usage.
o Use fine-grained entity beans
The "Composite Entity" pattern, often recommended for EJB 1.1 development, is obsolete in EJB 2.0. Implementing coarse-grained entities requires a lot of work, and is likely to deliver a poor return on investment. If fine-grained, EJB 2.0 style, entity beans don't meet your requirements,it's likely that use of entity beans is inappropriate.
o Don't put business logic in entity beans
Entity beans should contain only persistence logic. When using EJB, business logic should normally go in session beans.
o Investigate your EJB container's locking and caching options for entity beans
Whether or not entity beans are a viable option depends on the sophistication of your EJB container's support for them. How you structure your entity bean deployment may have a big effect on your application's performance.
The following guidelines apply primarily to distributed applications:
o Never allow remote clients to access entity beans directly; mediate entity bean access through session beans, using the Session Facade pattern If remote clients access entities directly, the result is usually excessive network traffic and unacceptable performance. When any components outside the EJB tier access entity beans directly (even within the same JVM), they arguably become too closely coupled to the data access strategy in use.
o Give entity beans local interfaces, not remote interfaces
Accessing entity beans through remote interfaces has proven too slow to be practical. Remote clients should use a session facade.
22) The Challenges of Web Development
Why is designing web interfaces so hard and why are the consequences of getting it wrong so dire? Some of the many reasons include the following:
o Web interfaces change frequently
For example, re-branding may change the look and feel, but not necessarily the workflow, of a web application. A successful application can accommodate such change without the need to change business objects or even web-tier control code.
o Web interfaces involve complex markup
Typical web sites contain nested tables and lengthy JavaScripts; pages may even be designed using GUI tools that produce hard-to-read markup. Usually only a small proportion of the content is dynamic. It's vital that the generation of complex markup doesn't obscure the generation of dynamic content. Getting this markup right is the business of specialists; Java developers are seldom good at it and their skills are better employed elsewhere. Thus separation of the roles of markup developer and Java developer is crucial.
o Web interfaces use a very different model compared to traditional UIs in languages such as Java The web programming model is punctuated by requests and responses; it's impossible to update GUI components dynamically when an underlying model changes, as in a traditional MVC approach such as Java Swing.
o HTTP requests can carry only string parameters Thus we frequently need to convert string values to and from Java objects. This can be difficult and error-prone.
o Web interfaces make it difficult to validate user input, as we have limited control over the client browser We must be prepared to reject invalid user input and make users resubmit it. In contrast, we can use custom controls to prevent users entering invalid data in Swing or VB interfaces, as we have complete control over UI presentation.
o HTML offers a limited choice of UI controls Again, this is in sharp contrast to traditional GUI applications, which offer a rich range of controls and the ability to implement custom controls.
o Ensuring that a web site looks right and works correctly in all common browsers can be difficult This can significantly complicate markup and add to the challenge of separating presentation issues from Java programming issues.
o There are many efficiency considerations Often we cannot restrict or predict the number of users using a web application. Both performance and concurrency are likely to be particularly important in web applications.
o Web interfaces are relatively hard to test This is one of many reasons that we should ensure that as little application functionality as possible is web-specific.
23) Java Class Loading Concepts
The following two basic principles will always apply:
o Each class retains an association with the class loader that loaded it. The getClassLoader() method of java.lang.Class returns the class loader that loaded the class, which cannot be changed after the class is loaded. This is the class loader that will be used if the class attempts to load classes by name.
o If the same class is loaded by two class loaders, classes loaded by the two class loaders will not be type compatible (although serialization will work).
24) The documentation of the java.lang.ClassLoader class further defines the following behavior for class loaders:
o Class loaders are hierarchical. When a class loader is asked to load a class, it first asks its parent class loader to try to load the class. Only if the parent (and parent's ancestors) cannot load the class, will the original classloader attempt to load the class. The top of the class loader hierarchy is the
bootstrap loader built into the JVM, which loads java.lang.Object().
o Although a class loader can see classes loaded by its parent(s), it cannot see classes loaded by its children.
25) Class Loading in J2EE
J2EE servers use multiple class loaders, largely because this allows dynamic application reloading. Clearly we don't want to reload all the application server's own classes on redeploying an application. This would mean that the application server would always need to be restarted. So application servers use different class loaders for application code to those they use for their own standard libraries, for example. Typically one or more new class loaders will be created for each application deployed on a server.
However, multiple class loaders are not usually used for different application-specific classes in the same application unless we use EJB (JSP pages may be given a separate class loader, but this doesn't usually affect application code).
As I've previously mentioned, using EJB considerably complicates the deployment model, compared to that for a pure web application. This is also true of class loading. In a WAR, we can simply include all binary dependencies in the /WEB-INF/ lib directory. However, things get more complicated when WARs access EJBs.
To see why, let's consider a common approach to implementing class loading in application servers. In an application deployed as an integrated enterprise application in an EAR, the EJB class loader is often the parent of the WAR class loader. Orion and WebLogic, for example, both use this approach. This is a natural
implementation approach, as WARs will typically access EJBs (and therefore need to be able to see at least EJB client classes), while EJBs do not access web components.
26) Thread Context Class Loader
It's also possible to try to resolve class loading problems by using the Java Thread API to obtain a class loader programmatically. Section 6.2.4.8 of the J2EE 1.3 specification requires all J2EE containers to support the use of the getContextClassLoader() method on java.util.Thread.
The J2EE specification isn't entirely clear regarding context class loading. However, the intent appears to be to allow portable classes, such as value objects, to load application classes in whatever container (such as EJB or web container) they may run in. In practice, the context class loader appears to be in the context of the current container. To clarify this behavior, let's consider the effect of the following two calls, made by a helper class that is loaded by the EJB class loader but used in both EJBs and classes running in the web container:
o Class.forName (classname): Will use the class loader of the helper class: in this case, the EJB class loader. This means that, if the EJB class loader is the parent of the WAR class loader, the helper will never be able to load classes in the WAR by name.
o Class.forName(classname, true, Thread.currentThread().getContextClassLoader()):
Will use the current container's class loader. This means that the helper will behave differently wherever it is running. If the EJB class loader is the parent of the WAR class loader, when the helper is used in the EJB container, it will only be able to load EJB classes and classes loaded by higher class loaders. If the helper is used in the WAR, it will be able to load WAR classes as well.Many frameworks, such as Web Work, use this approach to avoid problems caused by hierarchical class loading. However, it's not usually required in application code, which should normally only load classes by name using an abstraction layer that should conceal any use of the context class loader.
27) The Servlet 2.3 Specification's Class Loading Recommendations
Not only do implementations of class loading differ, but different J2EE specifications differ regarding class loading.
The Servlet 2.3 specification (9.7.2) states that "It is recommended also that the application class loader be implemented so that classes and resources packaged within the WAR are loaded in preference to classes and resources residing in container-wide library JARs".
This clearly conflicts with the standard J2SE class loading behavior, as described in the Javadoc for the java.lang.ClassLoader class. As the WAR class loader must be a dynamic class loader, it must be the child of another class loader provided by the application server. Hence the Servlet 2.3 recommendation is the opposite of normal Java 2 class loading behavior, which clearly states that classes will be loaded from the child class loader (in this case the WAR class loader) only if they cannot be resolved by the ancestor class loaders.
This recommendation (note that it is not a requirement) is also unclear on where EJBs fit into the proposed class loading model. EJBs are presumably not considered to be "classes and resources residing in container-wide library JARs", in which case the requirement does not apply to them.
The contradiction between the Servlet 2.3 and normal Java 2 class loading behavior is underlined by the fact that Sun's J2EE 1.3 Compatibility Test Suite fails on servers that default to implementing Servlet 2.3-style inverted class loading. For this reason, many servers either don't implement the Servlet 2.3 recommendation, or offer it only as a configuration option. The JBoss/fetty bundle used in the sample application defaults to using normal Java 2 class loading behavior, although it can be configured to use Servlet 2.3 WAR-first behavior.Oracle iAS takes the same approach.
28) Performance and throughput should be tested as early as possible in a project lifecycle through implementing a "vertical slice" or "spike solution". If such metrics are left until an implementation is functionally complete, rectifying any problems may require major changes to design and code.
Often the vertical slice will implement some of the functionality that we suspect will have the worst performance in the application and some of the functionality that will be most heavily used in production. However, we should try to back suspicions about likely performance problems with evidence. It's not always possible to predict where problem areas will be.
Hope you enjoy reading this book
About the Author
Rod Johnson is an enterprise Java architect specializing in scalable web applications. He has worked with both Java and J2EE since their release, and he is a member of JSR 154 Expert Group defining the Servlet 2.4 specification.
4 comments:
Hey....r u trying to crack jokes on this site :)..u read a book in a day and seems t be reading 10 books a the same time...why dont u try u r name is giness book of word records......i guess u buy a book then paste few things on u r blog and u got a template for writing this blog always starting from "Just" lolz
Thanks for sharing your thoughts about golf balls titleist pro v1x.
Regards
Also visit my website; 6 volt golf cart batteries cheap
I like the valuable info you provide in your articles.
I'll bookmark your blog and check again here regularly. I'm quite sure I will learn lots of new stuff right here!
Good luck for the next!
Also visit my web site ... completegolfsets.net
Hey there! This is my first comment here so I just wanted to
give a quick shout out and tell you I truly enjoy reading
your articles. Can you recommend any other blogs/websites/forums that go
over the same subjects? Thanks a lot!
Also visit my blog; gas golf carts for sale in the villages
Post a Comment