Avalon's brief history, and creation all of its design principles Overview Things start with the Apache Jserve project. Stefano Mazzocchi and other people who assist in developing Apache Jserv recognize that some modes used in the project are very common enough to create a server framework. On January 27, 1999, Wednesday (after JSERV 1.0B was released for about one month), Stefano took out a proposal to launch a project called Java Apache Server Framework. Its goal is to be the basis for all Java server code for Apache. The idea is to set together some of the components and reuse code of the cross-entries by providing a framework. Stefano Mazzocchi, Federico Barbieri and Pierpaolo Fumagalli created the original version. At the end of 2000, Berin Loritsch and Peter Donald participated in the project. At that time, Pierpaolo and Stefano turned to other projects, and Java Apache Server Framework was called Avalon. These five developers are the main person in charge of the design and concepts used by the framework. The current version is very similar to the version issued in June 2000. In fact, the main difference is to reorganize the package and divide the project into a child project. The same design pattern and interface still exists today. What is Avalon? Avalon is a five child project: Framework, Excalibur, Logkit, Phoenix, and CornerStone. When you hear Avalon, most people will think of Framework, but Avalon more than includes Framework. Avalon starts as Java Apache Server Framework, which contains frames, tools, components, and server cores, which are in one project. Because different parts of Avalon have different maturity, the release cycle is also different, and we decided to divide Avalon into a small item mentioned earlier. This is also convenient for new developers to understand and learn from different parts of Avalon - this is almost unable to do before. Frameworkavalon Framework is the basis of all other projects under Avalon's big buugal. It defines the default implementation of the interface, contract, and Avalon. Framework places most of its work and is therefore the most mature project. ExcaliburaValon Excalibur is a set of server-side components that you can use them in your own project. It includes the implementation of pooling, database connection management, and other components management. Logkitavalon Logkit is a high-speed logging tool set, Framework, Excalibur, Cornerstone and Phoenix are used. Its model is the same principle as JDK 1.4 logging package, but is compatible with JDK 1.2 . Phoenixavalon Phoenix is the core of the server, its management service (Service, implemented as a server-side component, called Block) publishing and execution. CornerStoneavalon CornerStone is a group of Block or services that can be deployed in the phoenix environment. These blocks include the task schedule between Socket Management and Block. ScratchPadScratchPad is not a real formal project, but a temporary area of components that are not ready to put in Excalibur. These components are quite different, and their APIs are not guaranteed until they are upgraded to the Excalibur project.
In this overview, we focus on Avalon Framework, but will introduce enough Avalon Excalibur and Avalon Logkit to let you get started. We will show how to use Avalon in practice through an imaginary business server. Define a complete comprehensive methodology or introduce all the squares of all sub-projects beyond the scope of this summary. We will focus on Avalon Framework because it is the basis of all other projects. If you can understand the framework, you can understand any Avalon-based project. You will gradually be familiar with some programming habit (IDIOM) commonly used in Avalon. Another reason why they are focused on the frame and involving Avalon Excalibur and Avalon logkit projects is that they are officially released and supported. Where is Avalon? I have asked several times, asked to clarify what avalon is suitable for doing, not suitable for doing. Avalon focuses on server-side programming and making the design and maintenance of the server-centered project as the design and maintenance of the server. Avalon can be described as a frame that contains an implementation. Although Avalon's focus is a server-side solution, many people find that it is also useful to ordinary applications. The concepts used in Framework, Excalibur, and Logkit are very common enough to apply in any project. Two items that will focus more directly on the server are CornerStone and Phoenix. Framework1. A supportive or closed structure 2. One basic system or arrangement of the idea is widely used in the application. The focus is placed in a single industry as a vertical market framework, such as a pharmaceutical system or communication system. The reason is that the same framework cannot be eligible for other industries. It has good versatility, and the framework available in multiple industries is called the horizontal market framework. Avalon is a horizontal market frame. You can build a vertical market frame using Avalon's Framework. An example of the most convincing vertical market framework built with Avalon is the Apache Cocoon Publishing Frame. Apache Cocoon 2nd Edition is built using Avalon's Framework, Excalibur, and Logkit projects. It uses the interfaces and contracts in Framework, allowing developers to understand how Cocoon works with less time. It also effectively uses the data source management and component management code provided by Excalibur so that it does not have to re-invent the wheel. Finally, it uses Logkit to handle all log problems in the publishing frame. Once you understand the principles hidden behind the Avalon Framework, you can understand any system based on Avalon. Once you understand the system, you will capture the defects caused by misuse frames faster. There is no magic formula worth mentioning that anything trying to use some kind of tool as a successful magic formula is a trouble. Avalon is no exception. Since Avalon's Framework is designed for server-side solution, use it to build a graphical user interface (GUI) is not a good idea. Java already has a framework for building a GUI called Swing. Although you need to consider whether Avalon is suitable for your project, you can still learn something from its principle and design. What you need to ask yourself is: "Where will I use it?" If the answer is that it will run in a server environment, then Avalon will be a good choice, whether you are to create a Java Servlet or a special purpose Server application. If the answer is that it will run on a customer's machine, and there is no interaction with the server, then Avalon is not suitable. Even so, the component model is also very flexible, helping to manage complexity in large applications. The principle and mode AVALON is based on some specific design principles.
The most important two modes are inversion of control and Separation of Concerns. Component Oriented Programming, Aspect Oriented Programming and Service Oriented Programming also have an impact on Avalon. Each programming principle can write a book of several volumes, but they are some design thinking habits. The concept of reverse control reverse control (IOC) is that the components are always managed outside. This phrase is the most used by Brian Foote in his paper. Everything you need to make through contexts, configurations, and loggers give components. In fact, each phase in the component lifecycle is controlled by the code of the creation component. When you use this mode, you have implemented a method of component security interaction with your system. IOC and security are not equivalent! IOC provides a mechanism that allows you to implement an extensible security model. In order to make a system truly safe, each component must be secure, and no components can modify the content of the object passed to them, and all interactions must use known entities. Safety is a major problem, IOC is a tool in the programmer tool library for security. Separation Consideration You should look at your system from different thinking directions, which leads to the Separation of Concerns, SOC mode. An example is a web server from different perspectives from the same problem space. The web server must be secure, stable, manageable, configurable and meet HTTP specifications. Each property is a separate consideration. Some of this consideration is related to other considerations, such as security and stability (if a server is unstable, it is impossible). Separation considerations also lead to Aspect Oriented Programming (AOP). Researchers have found that many considerations cannot be processed on the particle size of the class or method. These considerations are called Aspect. Aspect's examples include the lifecycle of management objects, record logs, processing exceptions, and cleanup resources. Since there is no stable AOP implementation, the Avalon development team selection is implemented by providing some small interfaces and then implemented by components, thereby implementing aspect or consideration. Component Oriented Programming, COP is a thought of a component or facility to split the system into some components or facilities. Each facility has a work interface and a contract around the interface. This approach allows for easy replacement of components, while do not affect the code of the other parts of the system. The main difference between object orient programming, OOP and COP is integrated level. The complexity of the COP system is easier to manage, which is benefited from less interdependence between classes. This increases the degree of code reuse. One of the main benefits of COP is that some parts of the modification of the project code will not undermine the entire system. Another benefit is a variety of implementations of a component and can be selected at runtime. Service Oriented Programming, SOP is a service to divide the system into some services provided by the system. Services 1. Work or responsibilities for others 2. A facility that provides repair or maintenance 3. A facility for the public offering tools Avalon's Phoenix regards each of the facilities to be provided as a service, from Compose specific interfaces and related contracts. The implementation of the service is called block. A server program is made up of a variety of services, and it is important to know this. Taking the mail server as an example, it has protocol handling services, authentication, and authorization services, management services and core mail processing services.
Avalon's CornerStone offers some low-level services that you can use in your own system. The services provided include connection management, socket management, participant / role management, and scheduling. We are here to introduce the service because it is related to the process of decomposing our assumption system into different facilities. Decompose a system how you decide what to make a component? The key is to define the facilities needed for your solution to operate efficiently. We will use an imaginary business server to show how to identify and determine services and components. After we define some of the services used by the system, we will define the different components required by the service in one of these services. My goal is to pass some concepts that help you define your system into manageable parts. System Analysis - Identification Components Although it provides a complete comprehensive methodology is not the scope of this article, I am willing to discuss some questions. We will start from the ash-oriented definition of components and services and then provide a definition of practices. Components One component is a combination of a working interface and the implementation of the work interface. Using components provide loose coupling between objects, allowing changing implementation without affecting the use of it. Serving a service consists of one or more components, providing a complete solution. Examples of services include protocol processors, task schedulers, authentication, and authorization services, and more. Although these definitions provide a starting point, it does not provide a complete picture. In order to decompose a system (defined as a set of facilities, it makes up a project) to decompose into the necessary components, I built the top-down way. This approach can avoid falling into the quagmium in the detail before you understand what facilities. Determine your project range your project is expected to complete what features, you always have a general idea. In the commercial world, the initial work note is the completion of this work. In the world of open source, this is usually done by an idea or a brain force. I don't think of how to emphasize the importance of high-level views with a project. Obviously, a large project will consist of many different services, while the small project has only one or two services. If you start feeling a bit unknown, just remind your big project is actually a lot of small items under the big umbrella. In the end, you will understand the overall picture of the entire system. Work Description: Business Server Business Server (Business Server) is an imaginary project. For the purposes of our discussion, its function is to handle sales orders, automatically send bills to customers, and manage inventory control. The sales order must be processed, through some type of transaction system. After the sales order is filled out for 30 days, the server will automatically send a bill to the customer. Inventory is managed simultaneously by the current inventory of the server and factory or warehouse. The business server will be a distributed system, each of which communicates with other servers. Discovery services We will use this Business Server project to discover the service. Considering the overcompassing work instructions above, we can immediately see some of the services defined in the project description. The list of services can be divided into two major categories: explicit service (service exported directly from the work instructions) and implicit service (based on similar work discovery services, or services that are supported from the service). Please note that implementation of the company's companies don't have to develop all services - there are some commercial solutions. In those cases, we may develop a wrapper so that we can achieve interoperability with commercial products in a determined manner. Companies that implement system will build most of services. Explicit service From the work instructions, we can quickly export some services. But this initial analysis does not mean that our work has been completed because certain services need to be guaranteed by other services. The transaction service service work description clearly indicates that "it must be processed when the sales order arrives". This shows that we need a mechanism to accept sales requests and process them automatically. This is similar to the WEB server.
They receive requests for resources, process and return a result (such as HTML page). This is called transaction processing. Completely speaking, there are different types of transaction processing. This general transaction service is very likely to be decomposed into some more special things, such as "Sales Order Processors". The specific method depends on the versatility of your service. There is a balance between availability and reusability. The more you use the service, the more reuse it. Usually it is more difficult to understand. The dispatching service In some cases, when the transaction is completed, after a specific time, an event must be scheduled. Moreover, the inventory control process must periodically open the purchase order. Because the work description pointed out that "After the sales order is 30 days, the server automatically leaves bills", so we need a dispatch service. Fortunately, Avalon CornerStone provides us with one, so we don't have to write one yourself. The message service work description pointed out that "each server will communicate with other servers in our distributed system". Let us consider this problem, sometimes users need a specific product or a method they want. The message service is a preferred example of using other company products. It is very likely that we will use Java Messaging Service (JMS) as a Messaging Service interface. Because JMS is a standard, its interface is unlikely to change in the short term. From practical experience, a well-oriented system is stronger than object-oriented systems (such as EJB) in scalability. One reason for more scalability is that the news is usually concurrent memory overhead. Another reason is that it is easier to disperse the load on the message to all servers, rather than putting all processing in a small number of server clusters (even on one server). Inventory Control Services Although this is not a classic service in a textbook, it is a need for this system. The inventory control service is fixed to monitor the record of the factory or warehouse, and some events are triggered when the inventory begins. Implicit service uses experience gained in the past system, further decomposing other services, and some services that are not explicitly pointed out but is required. Because of the space relationship, we will not be fully decomposed. Certification and authorization service certification and authorization services are not explicitly mentioned in the work description, but all business systems must carefully consider security. This means that all the clients of the system must be authenticated, and all the behaviors of the user must be licensed. Workflow automation service workflow automation is a popular development field in the enterprise system. If you don't use a third-party workflow management server, you need to write one yourself. Usually, workflow automation is made to use a software system to arrange tasks throughout the company's business process. For more information, please refer to Workflow Management Council.com http://www.wfmc.org/. Document Center Service As a task's current status information, the definition of the word "Document Center" is very uncertain. In other words, when the company receives a purchase order, our system needs to be able to store and reset the purchase order information. All other processes in the bill and system have the same needs from inventory to new user requests. Summary I hope that the example of the service of the Business Server project can help you find more. You will find that when you gradually turn to a lower abstraction layer from a higher abstraction, you will find more types of services, such as the connection service for processing the requested on one open port. Some services we define will be implemented through a third-party system, such as message service and workflow management services. For these services, using a standard interface is the most in line with your interests so you can replace the supplier later. Some services are actually a large service consisting of multiple services. Some services have been provided in Avalon Excalibur or Avalon CornerStone. One thing that should be kept in mind when discovered a system in a system: A service should be a high-rise subsystem. This will help you define components through the analyst team.
Because we have identified major services, you can make multiple individuals (or teams) to decompose each service in parallel. Sub system boundaries are also well defined, and the possibility of overlapping is small. If you decide to perform parallel analysis, you should go back to identify the universal components so that you can reuse as much as possible. UML Diagram for the Business Server Discovery Components We will explain the process of identifying the appropriate components as an example with the document center service mentioned earlier. For the convenience of discussion, we now will now list the needs of the document center service. The document center will use a database to be used as a lasting storage, authorize the client, caching documents in memory. Components Practical Definition When we talk about components, you should consider the problem: What facilities do I need to do? Avalon believes the concept of the system projection (CAST). The developer of the system will face a list of responsibilities of a component, and the component is called its role (Role). What is the role? The concept of character comes from theater. A drama, music or movie will have a certain number of characters, and they played by actors. Although the actor seems to never shortage, the number of characters is limited. The script of the performance defines the function or behavior of the role. As in the same theater, the script determines how you interact with the component. Consider different roles in your system, you will use the projection of the components as a role and talk to it. A role is a contract of a class of components. For example, our document center service requires a database. Avalon Excalibur defines a component that is in line with the "Data Source" feet. There are two different components in Excalibur, which can meet the needs of this role. Which of the specific use depends on the environment in which the service is located, but they all meet the same contract. A large number of Avalon-based systems will only use only one activity components for each role. The script is the working interface: the interface between other components and interaction. When determining the interface of the component, you must have a determined contract and keep in mind. The contract provides for the user to provide anything, as well as what components produce. Sometimes you must include semantics in the contract. An example is the difference between temporary storage components and persistent storage components. Once the interface and protocol are defined, you can be committed to implementation. How to be a good candidate component? In our document center service, we have identified four possible components: DataSourceComponent (from Excalibur), Cache, Repository, Guardian. You should seek more likely to have a variety of implementations, and interactions with these implementations can be seamlessly. This example, you will find some cases you need to use a replaceable facility. In most cases, you will only use an implementation of the facility, but you need to upgrade it independently without affecting the rest of the system. In other cases, you need to use different implementations depending on the environment. For example, Excaliber defined "Data Source" typically handles all JDBC connect pools yourself, but sometimes you may want to use the amenities provided in Java 2 Enterprise Edition (J2EE). EXCALIBUR Solving this issue is that a "Data Source" component directly manages JDBC connection and pool, and another component uses Java's Naming and Directory Interface (JNDI) to get a specific connection. How do you not be a good component? People who are accustomed to using JavaBeans like to implement all things as a JavaBean. This means everything from the data model to the transaction. If you handle components in this way, you may get an overcomite system. Targe the assembly as a model of a service or facility, not a model of data. You can have components from other resource drawn data, but the data should still be maintained as data.
An example of this philosophy in Avalon Excalibur is a connection (Connection) is not a component. Another example is the Guardian component mentioned earlier. Probable controversy is that the logic contained in Guardian is too correlated with the document center service, and it cannot be used as a component in a completely different service. Although there are many ways to manage complexity, there are also many ways to make it flexible, but sometimes it is not worth it. In this case, you must weigh your decisions. If a logic of a potential component will be consistently applied, it may make sense to use it as a component. In one system, there can be multiple instances of components, which can be selected at runtime. If the logic of the potential component is only determined according to another component, you may be able to put these logic to another component. Through the example of the Guardian component and the Repository component, we can argue Guardian to focus on the repository, not as a component. Decomposition Document Center Services We will list components to be implemented, as well as their roles, root causes, and sources (if components already exist). DocumentRepositoryDocumentRepository is the parent component of the entire service. In Avalon, the service is implemented as Block, Block is a specific type of component. Block must have a work interface that extends the Service Marker interface. The Block interface has also expanded Avalon's Component interface. Note that Block and Service are interfaces included in Avalon Phoenix. Finally, Service is still a specific type of Component. DocumentRepository is a method of making the Document object from a persistent store. It interacts with other components in the service to provide security, functionality, and speed. This specific DocumentRepository will be connected to the database to build the Document object internally using the logic of the database. DataSourceComponentDataSourceComponent is provided by Avalon Excalibur. It is the way we get effective JDBC connection objects. Cachecache is a storage facility in short-term memory. DocumentRepository will use it to save the Document object and reference it through a hash algorithm. In order to improve the reusability of the CACHE component, the stored object must implement a cacheable interface. The role of Guardianguardian components is based on participant management licenses. Guardian will load the license rule set from the database. Guardian will use standard Java security models to ensure access to specific documents. Summary, what you should do if you have a good component. Examples describe all components in the Document Center service, briefly introduce them to work. Browse this list quickly, it reflects how to implement the facility as components rather than data. So far, you should be able to determine what components that you need to do. Framers and foundations We will describe the Avalon's contract and interface to lay the foundation for our actual writing components. Avalon Framework is the central part of the entire Avalon project. If you understand the contract and structure defined by the frame, you will understand any code that utilizes the frame. Keep in mind that we have discussed the principles and patterns. In this section, we will explain the concept of the role in practice, how to work in practice, and how the components work work. Define the role of the component in Avalon, all components play a role. The reason is that you get your components through the role. On this stage, our only thing to consider is the signature of the role. Looking back the second part, we define the components as "a combination of the implementation of the work interface". The working interface is the role.
Creating a role Under the interface you will see an example of an interface, as well as some of the best practices and reasons. package org.apache.bizserver.docs; public interface DocumentRepository extends Component {String ROLE = DocumentRepository.class.getName (); Document getDocument (Principal requestor, int refId);} · best practice comprises a character called "ROLE" is Strings, this is a formal name of the role. The name is the same as the fully qualified name of the working interface. This will help when we need to get an instance of a component in the future. · If possible, please extend the component interface. This will make you become easier when publishing components. If you are not responsible for controlling the work interface, then this is useless to you. The problem will not be too big, because you can always convert it to Component's instance when publishing. · Do one thing and do it well. The interface of the component should be as simple as possible. If your work interface extends other interfaces, it will make it difficult to understand the components. An old American acronym is very good to this: Keep IT Simple, Stupid (KISS). It's not difficult to be smarter than yourself (stalliler), I have done a few times. · Use only the methods you need. The client should not know any details, too many replacement methods will only bring unnecessary complexity. In other words, choose a way and insist on constant. Don't allow your role interface to extend any lifetime or survival interface. If you implement any such class or interface, you are trying to implement the specification. This is not a good model, will only bring debugging and implementation in the future. Select the role name in Avalon, each character has a name. It is a way you get other components in your system. The Avalon Development Team has summarized some habitual names for role. Naming habits • The full qualification name of the working interface is usually the role name. The exception is listed below in this general rule. In this example, we theoretically component name should be "org.apache.bizserver.docs.documentRepository". This is the name that should be included in the "role" property in your interface. • If we get the reference to the component through a component selector, we usually use the character name from the first rule, plus the word "Selector" at the end. The result of this naming rule will be "org.apache.bizserver.docs.documentRepositorySelector". You can get this name via DocumentRepository.Role "Selector". · If we have multiple components to implement the same work interface, but for different purposes, we will separate roles. One role is the purpose of the component in a system. Each role name will begin with the initial role name, but the name indicating the purpose of the role is attached in the form of / $ {purpose}. For example, we can have the following purposes for DocumentRepository: PurchaseOrder and Bill (bill). These two roles can be expressed as DocumentRepository.Role "/ purchaseorder" and docuementRepository.Role "/ bill".
Framework Interface Overview The entire Avalon Framework can be divided into seven major categories (according to API): API: Activity, Component, Configuration, Context, Logger, Parameters, Thread, and Miscellany. Each class (except Miscellany) expressed a consideration direction (Concern Area). One component usually implements several interfaces to indicate the direction of consideration it cares. This allows the components to manage each component in a consistent manner. The lifecycle of the Avalon interface When a frame implements a plurality of interfaces to separately consider all aspects of the component, there is a potential to invoke the order in order. Avalon Framework realized this, so we developed an agreement for the order of event lifecycle. If your component does not implement the related interface, simply jump to the next event to be processed. Because there is a way to create and prepare components, you can set a component when you receive an event. The life cycle of components is divided into three phases: initialization phase, activity service phase and destruction phase. Because these phases have occurred in turn, we will discuss these events in turn. Alternatively, because Java language reasons, construction and finalization behavior are implicit, so do not talk. We will list the method names and the required interface. In each stage, there will be some steps that are identified by the method name. If the component extends the interface specified in parentheses, these steps are executed sequentially. The steps below the initialization phase occur in turn, only once in the component survival period. 1. enableLogging () [LogEnabled] 2. contextualize () [Contextualizable] 3. compose () [Composable] 4. configure () [Configurable] or parameterize () [Parameterizable] 5. initialize () [Initializable] 6. start () [STARTABLE] The steps below the active service phase occur, but it may happen multiple times in the survival of the component. Note that if you choose a Suspendable interface, your component is responsible for ensuring the correct function when performing any RE steps. Suspend () [suspendable] 2. Recontextualize () [reconTextualizable] 3. Reconfigure () [recomponfigurable] 5. Resume () [suspendable] The following steps below the steps in turn, in the component Only once in the survival period. 1. STOP () [STARTABLE] 2. Dispose () [Disposable] Avalon Framework Contract In this section, we will introduce all the content in the order, except for the most important part: Component, we put it in the forefront. When I use "container" or "accommodation" to describe the component, I have special meanings. I refer to subcomponents that have been instantiated and controlled by the parent component. I don't mean the components obtained by ComponentManager or ComponentSelector. Further, some Avalon steps received by the container assembly must propagate all of its subcomponents, as long as these subcompons implements the corresponding interface. Specific interface refers to Initializable, Startable, Suspendable, and Disposable. This arrangement of the contract is that these interfaces have special implementation agreements. Component This is the core of Avalon Framework. This considering the interface defined in the direction will throw the ComponEnTexception.
Component Each Avalon component must implement the Component interface. Component Manager and Component Selector only processes Component. This interface does not define a method. It is just as a marker interface. Any component must use a default constructor without parameters. All configurations are done through the Configurable or Parameterizable interface. Composable A component that requires other components requires this interface. This interface has only one method compose (), which is the only parameter of a CoMPONENTMANAGER type. A contract around the interface is: in the survival of the component, compose () is called once and is only called once. This interface uses any other interface interface, which is used in reverse control mode. It is called by the component's container, and only those components required for the component will appear in the ComponentManager. Recomposable In a few cases, components require a new ComponentManager and new component-role mapping. In these cases, the Recomposable interface needs to be implemented. Its method is also different from the Composable method name, which is Recompose (). The contract around the interface is: Recompose () method can be called any multiple times, but cannot be called before the component is fully initialized. When the method is called, the component must update itself in a safe and consistent way. Usually this means that all operations performed by the components must stop between updates and continue after the update. Activity is related to the contract of the component lifecycle. If an error occurs during this set of interface calls, you can throw a universal Exception. Disposable If a component needs to know that you are not needed in a structured manner, it can use the Disposable interface. Once a component is released, it cannot be used again. In fact, it is waiting for garbage collection. This interface has only one method dispose (), which does not have a parameter. The contract around the interface is: Dispose () method is called once and the last method called in the component survival period. At the same time, the component will not be used, and the resources occupied by the component must be released. INITIALIZABLE Any component If you need to create other components, or you need to perform an initialization operation to get information from other initialization steps, you should use the initializable interface. This interface has only one initialize () method, which does not have a parameter. The contract around the interface is: the initialize () method is called once, it is the method of finally called during the initialization process. It also shows that the component is already active and can be used by other components in the system. Startable Any component If you continue to run in its survival, you will use the Startable interface. This interface defines two ways: start () and STOP (). There are no parameters in these two methods. A contract around the interface is: start () method is called once after the component is fully initialized. The STOP () method is called once before the component is destroyed. They will not be called twice. START () is always called before STOP (). The implementation of the interface is required to perform START () and STOP () methods (unlike thread.stop () methods) and will not cause system unstable. Suspendable Any component If you have been hang in its life, you should use the Suspendable interface. Although it is usually always used with the STARTABLE interface, it is not required. This interface has two methods: suspend () and resume (). There are no parameters in these two methods. Contracts around the interface is: suspend () and resume can be called any time, but cannot be called before the component is initialized and started, or after the component is stopped and destroyed.
Call the Suspend () method for the suspended component, or calling Resume () for the running component will have no effect. Configuration This set of interfaces describe the consideration of the configuration. If any problem occurs, such as there is no required Configuration element, you can throw the ConfigurationException exception. Configurables must implement this interface to get an instance of the Configuration object based on the configuration that determines its behavior based on the configuration. This interface has a configure () method, with only one parameter of the Configuration type. Contracts around the interface is: configure () method is called once in the survival of the component. The incoming Configuration object must not be NULL. The ConfigurationConfiguration object is a tree consisting of a configuration element, and the configuration element has some properties. To some extent, you can view the configuration object as a big simplified DOM. There are too many methods for the Configuration class, and it is inconvenient in this article. Please see the Javadoc documentation. You can get the values of String, int, long, float, or boolean types from the Configuration object, if the configuration is not available. The same is true for properties. You can also get the child Configuration object. The contract stipulates that the value of Configuration objects should not have any child objects, and the pair of child objects is like this. You will notice that you can't get the parent Configuration object. Design is doing this. In order to reduce the complexity of the configuration system, most of the cases transmit the sub-configuration object to the child component. Subcaps should not have access to the value of the parent. This approach may bring some inconvenience, but the Avalon team always chooses to put security first in the case of compromise. Reconfigurable implementation of the component behavior of the interface is very similar to the Recomposable component. It has only a reconfigure () method. Such design decisions are to reduce the difficulty of the interfaces of the beginning of RE. Reconfigurable is like Recomposable in Configurable. Contextavalon's concept originated from a mechanism to implement a simple object from the container to the component. The exact protocol and name bindings are intended to be unconventional to provide maximum flexibility to the bearers. Contracts around the use of Context objects are defined in your system, although the mechanism is the same. The ContextContext interface only defines a get () method. It has an object type parameter that returns an object with a parameter object as a key value. The Context object is assembled by the container and then passes to the child component, and the sub-component is only read permissions to context. There is no other contract except that the context pair subcomponents is always read only. If you extend Avalon's Context, please pay attention to the contract. It is part of the reverse control mode and is also part of a security design. In addition, it is not good to pass a reference to the container in Contex, the causes and context should be the same only. Contextualizable Wow INEA Components from the container's Context object should implement the interface. It has a method called Contextualize (), the parameters are the contrabilized Context objects. The contract around this interface is: Contextualize () is called once in the survival of the component, after the LOGENABLED, but before other initialization methods. Recontextualizable implements component behavior of this interface is very similar to the Recomposable component. It only has a method called ReconTextualize (). Such design decisions are to reduce the difficulty of the interface of the beginning of RE.
Recontextualizable is like Recomposable for Contextualizable. The ResolvableResolvable interface is used to identify some objects that need to be separated in some specific contexts. An example is: an object is shared by multiple context objects, and changes its own behavior based on a particular context. CONTEXT will call the resolve () method before the object is returned. Logger Each system requires the ability to have an event log log. It uses its Logkit project within Avalon. Although logkit has some ways to static access to a Logger instance, Framework wants to use reverse control mode. LOGENABLED Each component that requires a logger instance implements the interface. This interface has a method called Enablelogging (), passes the Logger instance of Avalon Framework to the component. Contracts around the interface is: only call once in the survival period of the component, before any other initialization step. The LoggerLogger interface is used to abstract different log libraries. It provides a unique client API. Avalon Framework provides three packages that implement the interface: LogkitLogger for Logkit, Log4jlogger for Log4j, and JDK14logger for JDK1.4 logging. Parametersavalon recognizes that the Configuration object hierarchy is too heavy in many occasions. Therefore, we propose a Parameters object to provide an alternative to the Configuration object, using the name-value method. Parameterizable Any component that wants to replace the Configuration object with Parameters will implement the interface. Parameterizable is only a method called parameterize (), with the parameter being the parameters object. The contract around the interface is: it is called once in the survival of the component. This interface is incompatible with the configurable interface. The ParametersParameters object provides a mechanism for acquiring values through a String type name. If the value does not exist, the convenient method allows you to use the default value, or you can get the value of any of the same format in the Configurable interface. Although the Parameters object is similar to the Java.util.Property object, they still have important semantic differences. First, Parameters are read-only. Second, Parameters is always easily exported from the Configuration object. Finally, the Parameters object is exported from the XML snippet, which looks like this:
SingleThreaded Components around the SingLethReaded component is not allowed to be simultaneously accessed by multiple threads. Each thread needs to have its own instance of the component. Another approach is to create a new instance when using a component pool instead of each requesting the component. In order to use the pool, you need to implement the POOLABLABLE interface of Avalon Excalibur instead of this interface. Threadsafe's contract around the Threadsafe component is: No matter how many threads accesses the components, their interfaces and implementations can work normally. Although this is an elastic design goal, it is sometimes unable to be implemented by the technology you are using. Components that implement this interface are typically only one instance in the system, and other components will use this instance. Other classes and interfaces in the root package of Avalon Framework include Exception Hierarchy and some universal tool classes. But there is a class worth mentioning. VersionJavatm version technology is a specified in the manifest file in the JAR package. The problem is that when JAR is unpack, you lose version information, and version information is placed in a text file that is easy to modify. When you put these questions together with a steeperse learning curve, check the version of the assembly and interface is more difficult. The Avalon Development team designed the Version object, allowing you to easily check the version and the comparison version. You can implement a Version object in your component, and test the appropriate components or the lowest version number will be easier. Implement Dream We will show you how to use Avalon Framework and Avalon Excalibur to implement your service application. How easy it will be displayed from Avalon. After you have finished your analysis, you need to create components and services that make up your system. If Avalon just describes some program habits you can use, then its use is not large. But even in this way, use these program habits and patterns will also help understand the entire system. Avalon Excalibur offers some useful components and tools that you can use them in your own system, which allows you to be more relaxed. As our demonstration, we take the whole process that defines a component to take out a document from a repository. If you remember our discussion of theoretical business server, we have determined this component as a service. In actual conditions, a component is a service. Implement this component here, we define how to implement our components. We will take the process of the processRepository component that implements the previously mentioned DocumentRepository components. The first thing we need to figure out is the field of our components. Then we need to figure out how to create and manage our components. Selecting Focus We have defined roles and interfaces in front of the DocumentRepository component, and we are ready to create implementations. Because the interface of DocumentRepository defines only one way, we have the opportunity to create a thread secure component. This is the most popular class because it allows only the least resource consumed. In order to make our implementation are thread safety, we do need to carefully consider how to implement the component. Since all our documents are stored in the database, and we want to use an external Guardian component, we will need to access other components. As a responsible developer, we want to record logs that help debug components, and track what happens within. The Avalon Framework is in that you only need to implement the interface you need, you can ignore those unwanted. This is the benefits of Separation of Concerns. When you find that you need to consider a new aspect, you only need to implement the relevant interface to add new features to the component. For some part of your component, you don't need to make any changes. Since the thread safety is a design goal, we already know that there is a need to implement the Threadsafe interface.
The DocumentRepository interface has only one method, so the use of the work interface of the component is to meet this demand. And we know that Component will not be used before it is fully initialized, and it will not be used after it is destroyed. In order to complete the design, we need to implement some implicit interfaces. We hope that the solution is secure enough, so that we may explicitly know whether the components have been fully initialized. In order to achieve this goal, we will implement Initializable and Disposable interfaces. Since information about environment may change, or may be customized, we need to make DocumentRepository implementation of the configurable interface, and the method of obtaining an instance of the required components provided by Avalon is to take advantage of a ComponentManager. We need to implement the Composable interface to get the component instance from the ComponentManager. Because DocumentRepository visits documents in the database, we need to make a decision. We want to take advantage of Avalon Excalibur DataSourceComponent, or want to realize the code of database connection management. In this article, we will use DataSourceComponent.
At this time, our class skeleton looks like: public class DatabaseDocumentRepositoryextends AbstractLogEnabledimplements DocumentRepository, Configurable, Composable, Initializable, Disposable, Component, ThreadSafe {private boolean initialized = false; private boolean disposed = false; private ComponentManager manager = null; private String dbResource = null;. / ** * constructor All Components need a public no argument constructor * to be a legal Component * / public DatabaseDocumentRepository () {} / ** * Configuration Notice that I check to see if the Component has.. * already been configured This is done to enforce the policy of * only calling Configure once * / public final void configure (Configuration conf) throws ConfigurationException {if (initialized || disposed) {throw new IllegalStateException ( "Illegal call")?.; } f (null == this.dbresource) {this.dbresource = conf.getchild ("dbpool"). getValue (); getLogger (). Debug ("Using Database Pool: this.dbResource); // Notice THE GetLogger ()? this is from abstr actLogEnabled // which I extend for just about all my components.}} / ** * Composition. Notice that I check to see if the Component has * already been initialized or disposed? This is done to enforce * the policy of proper lifecycle management . * / public final void compose (ComponentManager cmanager) throws ComponentException {if (initialized || disposed) {throw new IllegalStateException ( "Illegal call");} if (null == this.manager) {this.manager = cmanager;} } public final void initialize () throws exception {if (null == this.manager) {throw new illegalstateException ("not composed");} if (null ==
this.dbResource) {throw new IllegalStateException ( "Not Configured");} if (disposed) {throw new IllegalStateException ( "Already disposed");} this.initialized = true;} public final void dispose () {this.disposed = true; this.manager = null; this.dbResource = null;} public final Document getDocument (Principal requestor, int refId) {(! initialized || disposed) if {throw new IllegalStateException ( "Illegal call");} // TODO : Fill in logic}} You can find some structural modes in the above code. When you take into account security while designing, you should explicitly enforce each contract in the component. Safety intensity always depends on the weakest ring. Only when you are sure that a component is fully initialized, you can use it after it is destroyed, you will never use it. I am placing this logic because you will use the same way when you write your own class. Components instantiation and management components To allow you to understand how the container / component works, we will first discuss manual way of managing components. Next we will discuss how the Avalon's Excalibur component architecture hides complexity. You will still find that you would rather manage components. But most of the time, Excalibur's powerful and flexibility can meet your needs. The Manual Method All Avalon components are created somewhere. The code for creating the component is the container of the component. The container is responsible for managing components from constructing a life cycle of the descent. The container can have a static "main" method that allows it to call from the command line, or it can also be another container. When you design the container, remember the reverse control mode. Information and method calls will only flow from the container to the component. Subversion Of Control Subversion Control is the reverse mode of reverse control. When you pass the reference to the container to the component, subversive control is achieved. This is also in this case when you let a component manage its own lifecycle. The code operated in this way should be considered defective. When you mix the container / component relationship together, their interaction will make the system difficult to debug and are difficult to audit security. To manage subcomponents, you need to save them a reference to them throughout the same period. It must be initialized before the container and other components can use the sub-assembly.
Our DocumentRepository, the code may look like the following way: class ContainerComponent implements Component, Initializable, Disposable {DocumentRepository docs = new DatabaseDocumentRepository (); GuardianComponent guard = new DocumentGuardianComponent (); DefaultComponentManager manager = new DefaultComponentManager (); public void initialize () throws Exception {Logger docLogger = new LogKitLogger (Hierarchy.defaultHierarchy () .getLoggerFor ( "document")); this.docs.enableLogging (docLogger.childLogger ( "repository")); this.guard.enableLogging (docLogger .childLogger ( "security")); DefaultConfiguration pool = new DefaultConfiguration ( "dbpool"); pool.setValue ( "main-pool"); DefaultConfiguration conf = new DefaultConfiguration ( ""); conf.addChild (pool); this. Manager.addcomponent (DocumentRepository.Role, this.docs); this.Manager.addcomponent (GuardianComponent.Role, this.guard); this.docs.compose (this.manager); this.guard.compose (this.manager); THIS.DOCS.CONFIGURE (conf); this.guard.initialize (); this.d Ocs.initialize ();} public void dispose () {this.docs.dispose (); this.guard.dispose ();}} For the sake of brevity, I removed the explicit check from the above code. You can see that manual creation and management components are very detailed. If you forget to do some steps in the component lifecycle, you will find bugs. This also requires some in-depth understanding of the components you are instantiated. Another approach is to add some methods to the ContainerComponent to dynamically process the initialization of the component. Automated Autonomy developers are lazy, so they will spend time writing a special ComponentManager as a container of all components in the system. In this way, they don't have to understand the interfaces of all components in the system. This may be a frustrating task. Avalon's developer has created such a monster. A ComponentManager includes a ComponentManager in the component architecture of Avalon Excalibur. There is a compromise when you hand over the responsibility of the management component to the ComponentManager of Excalibur. You abandoned all of which components contained in the compomentManager. However, if your system is quite large, you will find manual controls to be a frustrating job. In this case, it is preferable to manage all components in the system in a local centralized manner for considering system stability.
Since there is a different level of integration with Excalibur's component architecture, we will start from the lowest level. Excalibur has a group of ComponentHandler objects that are separate containers for each type of component. They manage the entire life cycle of your components. Let us introduce the concept of a living mode (LIFESTYLE) interface. A survival interface describes how the system treats one component. Since the component's survival is influenced, we need to discuss some of the significance of some current survival: · org.apache.avalon.framework.thread.singLethReadedo is not a thread safe or reused. o If there is no other way to survive mode, the system is considered to be this. o Create a new instance when you request a component. o The creation of the example and initialization is delayed when the request component is requested. Org.apache.avalon.framework.thread.threadsafeo component is completely reusable and meets the principles of all thread safety. o The system creates an instance, all Composable components are shared on it. o Creating and initialization of an instance is done when CoMPONENTHANDLER is created. · Org.apache.avalon.excalibur.pool.pooLableo is not a thread, but it is completely reusable. o Creating a set of instances in the pool, and when the Composable component requests, the system provides an available. o Creating and initialization of an instance is done when CoMPONENTHANDLER is created. The ComponentHandler interface is very simple. You initialize the constructor through the Java class, Configuration object, ComponentManager object, Context object, and RoleManager object. If you know that your components will not need one of the above, you can upload a null at its location. After that, you call the "GET" method when you need a reference to the component. When you run out, you call the "Put" method to return the component to ComponentHandler. The following code makes us understand this.
class ContainerComponent implements Component, Initializable, Disposable {ComponentHandler docs = null; ComponentHandler guard = null; DefaultComponentManager manager = new DefaultComponentManager (); public void initialize () throws Exception {DefaultConfiguration pool = new DefaultConfiguration ( "dbpool"); pool.setValue ( "main-pool"); DefaultConfiguration conf = new DefaultConfiguration ( ""); conf.addChild (pool); this.docs.configure (conf); this.docs = ComponentHandler.getComponentHandler (DatabaseDocumentRepository.class, conf, this.manager , null, null); this.guard = ComponentHandler.getComponentHandler (DocumentGuardianComponent.class, null, this.manager, null, null); Logger docLogger = new LogKitLogger (Hierarchy.defaultHierarchy () .getLoggerFor ( "document")); this .docs.enableLogging (docLogger.childLogger ( "repository")); this.guard.enableLogging (docLogger.childLogger ( "security")); this.manager.addComponent (DocumentRepository.ROLE, this.docs); this.manager. Addcomponent (Guardia Ncomponent.Role, this.guard); this.guard.initialize (); this.docs.initialize ();} public void dispose () {this.docs.dispose (); this.guard.dispose ();}} Here, we only write a few lines of code. We still created a Configuration object in hand, or set up Logger, or to initialize and destroy the ComponentHandler object. Here we do just to prevent the impact of the interface changes. You will find that it is good for the code in this way. EXCALIBUR did a more step. Most complex systems have some configuration files. They allow administrators to adjust critical configuration information. Excalibur can read configuration files in the following format and create components of the system.
Moreover, now we have some specific configuration information about the Guardian components. In order to read these systems into your system, the Avalon framework provides you with some convenience: DefaultConfigurationBuilder Builder = New DefaultConfigurationBuilder (); configuration systemconf = builder.buildfromfile ("/ path / to / file.xconf"); this is really for us The code that manually constructs the configuration element in front play a simplified role, and it limits the information we need to know when programming. Let us look at the Container class and see if there is really a thing. Remember that we specify 5 components (ComponentSelector is as a component), as well as configuration information for each component. class ContainerComponent implements Component, Initializable, Disposable {ExcaliburComponentManager manager = new ExcaliburComponentManager (); public void initialize () throws Exception {DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder (); Configuration sysConfig = builder.buildFromFile ( "./ conf / system.xconf") ; this.manager.setLogger (Hierarchy.getDefaultHierarchy () .getLoggerFor ( "document")); this.manager.contextualize (new DefaultContext ()); this.manager.configure (sysConfig); this.manager.initialize (); } public void dispose () {this.manager.dispose ();}} Is it uncomfortable? We initialize the number of more than twice as many, and the amount of code is more than double (6 line code, not 13 lines). This profile has a shortcoming that it looks a bit crazy, but it will drop the number of code required to the lowest. A lot of activities have occurred behind the ExcaliburcomponentManager. Each "Component" element in the configuration file, EXCALIBUR creates a ComponentHandler for each class's entry (entry), and establishes a correspondence with the role (Role). "Component" element and all of its sub-elements are the configuration of the component. When the component is an ExcaliburComponentSelector, Excalibur reads each "Component-Instance" element and performs the same type of operation, this time is the correspondence with Hint Entry. Let the profile look like we can use an alias to change the appearance of the configuration file. Excalibur uses a roleManager to provide an alias for the configuration system. RoleManager can be a class you created specifically, or you can use DEFAULTROLEMANAGER and pass it into a Configuration object. If I use defaultroleManager, I will hide the role profile and the rest of the system in the JAR file. This is because the role profile will only be changed by developers.
Here is RoleManager Interface: interface RoleManager {String getRoleForName (String shorthandName); String getDefaultClassNameForRole (String role); String getDefaultClassNameForHint (String hint, String shorthand);} Let's look at how to use Excalibur is our framework of RoleManager. First, the Excalibur reads all the child elements of the root element. This includes all "Component" elements, but this Excalibur does not recognize the name of the elements, and it asks if RoleManager we will use this component. If roleManager returns NULL, then the element and all its sub-elements are ignored. Next, Excalibur exports class names from the role name. The final method is to dynamically correspond to the subtype of the class name with the ComponentsElectror. Excalibur provides a RoleManager's default implementation that uses an XML configuration file. The tag is quite simple, it hides all the additional information you don't want administrators to see.
To show you how to get the XML file from the class loader, I will show below the tips: DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder (); Configuration sysConfig = builder.buildFromFile ( "./ conf / system.xconf"); Configuration roleConfig = builder.build (this.getClass () getClassLoader () .getResourceAsStream ( "/ org / apache / bizserver / docs / document.roles").); DefaultRoleManager roles = new DefaultRoleManager (); roles.enableLogging (Hierarchy.getDefaultHierarchy () .getLoggerFor ( "document.roles")); roles.configure (roleConfig); this.manager.setLogger (Hierarchy.getDefaultHierarchy () .getLoggerFor ( "document")); this.manager.contextualize (new DefaultContext () this.manager.setrolemanager (Roles); this.manager.configure (sysconfig); this.manager.initialize (); Since we add 6 lines of code, you have to take a look.
Our ultimate profile can be written like this:
Initialization and Disposal Approachclass MyClass implements Component, Composable, Disposable {ComponentManager manager; Guardian myGuard;. / ** * Obtain a reference to a guard and keep the reference to * the ComponentManager * / public void compose (ComponentManager manager) throws ComponentException {if (this.manager == null) {this.manager = manager; myguard = (guardian) this.manager.lookup (Guardian.Role);}} / ** * this is the method That Uses the Guardian. * / public void Mymethod () THROWS SecurityException {this.myguard.checkpermission (New BasicPermission ("test"));} / ** * Get rid of} * / public void dispose () {this.Manager.Release (this.myguard); This.Myguard = null; this.manager = null;}} You can see from the sample code, which is easy to do so. When the object receives the ComponentManager for the first time, it achieves a reference to a Guardian component. If you can guarantee that the Guardian component is a thread secure (implementing the Threadsafe interface), just do these things. Unfortunately, from the long run, you can't guarantee this. In order to properly manage resources, we must release references to components after running the components. That's why we keep a reason for the reference to ComponentManager. This mode is mainly disadvantaged in processing components in the component pool. The reference to the component maintains the life of the component. If the survival period of the object is short, this may not be a problem; however, if the object is a component managed by the Excalibur component management architecture, as long as there is a reference to it, its survival will continue. This means that we actually turn the component pool into a component factory. The main benefit of this method is that the code to get and release the assembly is clear. You don't have to understand the code that is processed. Another thin difference, you bundle Guardian's presence with the ability to initialize this object. Once an exception is thrown during the initialization phase of an object, you have to think that the object is not an effective object. Sometimes you want to make the program failure when the required components do not exist, then this is not a problem. When designing components, you really need to pay attention to this layer implies.
Exception Handling Approachclass MyClass implements Composable, Disposable {ComponentManager manager;. / ** * Obtain a reference to a guard and keep the reference to * the ComponentManager * / public void compose (ComponentManager manager) throws ComponentException {if (this.manager == null) {this.manager = manager;}} / ** * This is the method that gets the Guardian * / public void myMethod () throws SecurityException {Guardian myGuard = null;. try {myGuard = (Guardian) this.manager. lookup (Guardian.ROLE); this.criticalSection (myGuard);} catch (ComponentException ce) {throw new SecurityException (ce.getMessage ());} catch (SecurityException se) {throw se;} finally {if (myGuard =! null) {this.manager.release (myGuard);}.}} / ** * Perform critical part of code * / public void criticalSection (Guardian myGuard) throws SecurityException {myGuard.checkPermission (new BasicPermission ( "test")); } This code is somewhat complicated as you see. In order to understand it, you need to understand an abnormality. This may not be a problem, because most Java developers know how to handle exceptions. In this way, you don't need to worry too much about the way of survival, because once we don't need it, it releases it. The main disadvantage of this approach is to increase the abnormal processing code because it is more complicated. In order to minimize complexity, let the code easier maintenance, we extract the work code and put it in another method. Keep in mind that in the TRY sentence block, how many components we want to get, you can get it. The main benefit of this way is that you can manage component references more efficiently. Similarly, if you are using the Threadsafe component, there is no substantial difference, but if you are using the components in the component pool, there is a difference. At a time you use a component, you have a little slight overhead when you get a new reference, but it is forced to create a new component instance. Like initialization and destruction, you must also understand a subtle difference. If the manager can't find the component, the way the abnormality process does not make the program fails when initialization. As mentioned earlier, this is not completely unreasonable. Many times, you want a component to exist, but if the desired component does not exist, the program does not need to fail. Getting a component from ComponentSelector For most operations, you only need to use ComponentManager. Since we decided that we need multiple instances of DataSourceComponent, we need to know how to get the instance we want.
ComponentSelector is slightly more complicated than ComponentManagers, because there is a promise to get the desired reference when processing. One component belongs to a specific role, which we have already said very clearly. However, sometimes we need to select one from a plurality of components of a role. ComponentSelector uses an arbitrary object as a hint. Most of the time, this object is a String, although you may want to use a Locale object to get a correct and international component. In the system we have established, we choose to use the string to select the correct example of DataSourceComponent. We even gave yourself a Configuration element to indicate what is required to get the correct components. This is a good practice, you can do it as it makes system management easier. Compared to the system administrator to remember these magical configuration values, this is more likely to see reference to other components. From a conceptual perspective, it is not different from the ComponentSelector to obtain a component from ComponentManager. You only have a step. Keep in mind that the ComponentsElectror is also a component. When you look for the character of ComponentSelect, ComponentManager will prepare the ComponentSelector component and return it to you. Then you need to select components through it. To illustrate this, I will extend the code of the abnormal processing method discussed earlier. public void myMethod () throws Exception {ComponentSelector dbSelector = null; DataSourceComponent datasource = null; try {dbSelector = (ComponentSelector) this.manager.lookup (DataSourceComponent.ROLE "Selector"); datasource = (DataSourceComponent) dbSelector.select (this .useb); this.Process (DataSource.getConnection ());} catch (exception e) {throw E;} finally {if (datasource! = null) {dbselector.release (Datasource);} if (dbselector! = null ) {this.manager.release (dbselector);}}} You can see that we get a reference to ComponentSelector by using the role of the specified component. We abide by the role naming specification mentioned earlier, and add "Selector" as a suffix at the end of the character name. You can use a static interface to handle all the character names of the system to reduce the number of string connections in the code. This is also acceptable. Next, we have to be referenced from the ComponentSelector to the DataSource component. Our sample code assumes that we have obtained the information you need from the Configuration object and put it in a class variable called "Usedb". Excalibur's tool class is the last section introduces you to several types of components and tool classes in the Apache Avalon Excalibur. These tools are robust and can be used in actual production systems. We have an informal hierarchical project called "scratchpad", in which we have solved the implementation details of potential new tool classes. The quality of tool classes in ScratchPad has different, and their usage cannot be guaranteed, although you may feel good.
Command Line Interface (CLI) CLI Tool class is used in some projects, including Avalon Phoenix and Apache Cocoon for processing command line parameters. It provides a mechanism for printing help, and can process parameter options in a short name or long name. The Collection Tool Class Collection Tool class has some enhancements to the JavaTM Collections API. These enhancements include identifying the functions of the intersections and a priorityQueue in two LISTs, which is the enhancement of Stack, allowing the priority of the object to change the simple advanced STACK implementation. Component Management We have discussed the usage in the previous area. This is the most complex monster in Excalibur, but it provides a lot of features in fewer classes. There is also a poolable type outside of the two management types of simple SingLethreaded or Threadsafe. If a component implements an Excalibur's pooLable interface, not a SingLethReaded interface, then it will maintain a component pool and reuse instances. This work is very good in most cases. In the case where a few components cannot be reused, use the SingLethReaded interface. Logkit Management Avalon Development Team aware of many people need a simple mechanism to create complex log target hierarchies. For the idea of Rolemanager, the team developed LogkitManager, which can be used by the Excalibur Component Management system mentioned earlier. Based on the "Logger" property, it will give a corresponding Logger object for different components. Thread Tools The CONCURENT package provides some auxiliary multithreaded programming classes: Lock (Mutex Implementation), DjikstraseMaphore, ConditionALEVENT, and Threadbarrier. DataSources This is based on Javax.sql.DataSource class, but simplifies. DataSourceComponent has two implementations: an explicitly uses JDBC connection pool, another Javax.sql.DataSource class using the J2EE application server. The Input / Output (IO) Tool class IO tool class provides some FileFilter classes and File and IO-related tool classes. The pool implements the pool that POOL implementation can be used in various situations. One of them is very fast, but can only be used in a thread, which is used to implement Flyweight mode is good. There is also a defaultpool that does not manage the number of objects in the pool. SoftResourceManagingPool determines whether it exceeds a threshold when the object is returned, and if it exceeds it, the object "retire". Finally, HardResourceManagingPool will throw an exception when you reach the maximum number of objects. The three pools behind are Threadsafe. The Property Tools Property Tool class is used with the Context object. They allow you to extend "Variables" in the Resolvable object. It works this way: "$ {resource}" will look for a value called "Resource", and use this value instead of this symbol. Conclusion Avalon has been tested for time, you can use it. Evidence provided in this section can help persuade yourself and others, using a mature framework to create a better than yourself. You may have been convinced, but you need some help to convince your colleagues, let them believe avalon is the correct choice. Maybe you also need to convince yourself. In any case, this chapter will help you organize your ideas and provide some evidence of persuasiveness.
We need to fight against the open source mode (Fear, Uncertainty, And DouBt, FUD). With regard to the effectiveness of the validity of the open source, I recommend you to read Eric S. Raymond's excellent discussion on this topic N400017. No matter what you hold, what is the view of the article, the cathedral and the bazaar Information will be provided to accept open source from the overall. Avalon can work Our bottom line is Avalon to complete the goal to achieve when it is originally designed. Avalon has not introduced new concepts and ideas, but uses some concepts that have been tested and standardize them. The latest concept that affects Avalon is Separation of Concerns mode, which is approximately proposed in 1995. Even at that time, separation consideration is also a standardized method for system analysis techniques. Avalon's number of users is hundreds. Some items such as Apache Cocoon, Apache James, and JESKTOP are based on Avalon. Developers of these items are users of Avalon Framework. Because Avalon has such a large number of users, it gets a good test. The authors of Avalon designed by the best people realize that we are not the only group of experts calculated by the server. We use the concept and idea of research from other people. We respond to feedback from users. Avalon is not only designed by the five developers described earlier, and they brought reverse control, separation, considering and facing component programming, and designed it. Open source code is in that the result is the best idea and the fusion of optimal code. Avalon has been tested at the stage of test ideas and refused some ideas because there is a better solution. You can use the knowledge gained by the Avalon Development Team and use it in your own system. You can use Excalibur in your own project to pre-defined components, they have been tested and can run under heavy load. Compatibility license Apache Software License (ASL) can be compatible with any other known license. The most known exception is GNU Public License (GPL) and Lesser GNU Public License (LGPL). The important thing is that ASL is quite friendly for cooperation. If you don't want, it will not force you to issue source code. The HTTP server in the Apache Software Foundation name is the same license. The clustered R & D Most Avalon users make their contribution in some way. This is scattered in some users in the workload of development, debugging and document. This also shows that Avalon's code has passed a broader peer review, which is impossible in company development. Moreover, Avalon's users support AVALON. Although the project of open source code usually does not help platform or phone supports hot money, we have a mailing list. Many of your questions can be quickly answered through the mailing list, which is better than some support hotline. Simplified analysis and design based on Avalon development helps developers reach a mental state. In this mental state, the developer's work is intended to find components and services. Since the details of the survival of components and services have been analyzed and design, developers only need to choose what they need. It is important to point out that the beginning of Avalon does not replace traditional object-oriented analysis and design, but it has been enhanced. You still use the technology used before, but now you have a set of tools to achieve your design faster. Avalon is ready Avalon Framework, Avalon Excalibur, and Avalon Logkit are ready to make you. They have matured and will only get better and better.