|
Presentation / Components | org.jaffa.presentation.portlet.component |
Jaffa is based on a component framework. At a high level you have an application, it is broken into modules,
and each module is futher broken down into components.
A component in Jaffa terms is a 'usable unit of software, comprising of a user interface, and business logic to achieve a
given piece of functionality'. We normally define these components at a level which would allow us to maximize there re-use.
For example we have in our patterns a 'finder' and 'viewer' component. Typically a finder has two screens (criteria and results)
and a view just has one. You could make a viewer that more complex and use multiple screens, and conversly make a finder that
has its criteria and results on the same page.
The diagram above is a logical view of a component. It contains...
- Its presentation elements (For each screen we woul normally have a JSP, FormBean and Action)
- Its Component Controller, responsible for controlling the presentation flow of the screens and
interacting with the business logic
- Its Transaction Controller which is the entry point for providing the business functionality.
It is the job of the transaction controller to interact with any common business logic helpers, and any
domain objects needed to perform the component funtion.
- The domain objects are not considered part of the component, and they are reused by many components. The goal
is to make the Transaction Contollers as lightweight as possible and put as much logic in the domain objects or
other reusable service (or helper) classes
- In the middle we have 'data transfer object' (aka javabeans or POJOs - plain old java objects). This along with the
Interface class that the Trasaction Controller implements provide the documented functions and data that will be
passed between presentation and business tiers. Bear in mind that are goal here is for corse grain stateless function
so it will be easy to deploy the business tier in a distributed environment (if required)
|
IComponent and Component base class |
All components must implement the IComponent Interface, but in reality we expect most uses to extend
the abstact base class Component .
A component typically has to implement only two methods (the rest are done in the base class)
public FormKey display() throws FrameworkException, ApplicationExceptions
public void quit();
display();
The display method must return a FormKey to indicate the first page to display when running this component.
Typically this can be done in a single statement. The code below is an example from our 'Finder' component which
decides, based on a value whether to display the criteria or results screen on initial invocation. The display
method is only calle once when the component is initially created.
Taken from UserFinderComponent in the SampleApp |
public FormKey display() throws ApplicationExceptions, FrameworkException {
if (getDisplayResultsScreen() != null && getDisplayResultsScreen().booleanValue())
return displayResults();
else
return displayCriteria();
}
public FormKey displayCriteria() throws ApplicationExceptions, FrameworkException {
initCriteriaScreen();
return new FormKey(UserFinderCriteriaForm.NAME, getComponentId());
}
public FormKey displayResults() throws ApplicationExceptions, FrameworkException {
doInquiry();
return new FormKey(UserFinderResultsForm.NAME, getComponentId());
}
|
quit();
The quit method is just used for the component to perform some clean up, releasing of resources for when a component
is destroyed.
This may be called by the component memory manager to kill inactive components, or by the user session manager to kill all
components for a user that as logged off, or who's session has expired.
The quit() trigger is not defined as abstact as there is a default implementation. For this if you do
implement this method you MUST perform a super.quit() to guarentee correct memory management.
|
Setting up component.xml |
Without going into a full description of the security arround the component framework, a component can be defined in a
couple of lines of xml inside the 'components.xml' file.
By default the components.xml file is located in classpath:///resources/components.xml , but can be loacted
anywhere as long as org/jaffa/config/framework.properties is updated to point to its location.
An example custom definition in framework.properties |
framework.ComponentsFile=classpath:///org/jaffa/config/myComponents.xml |
Using the UserFinder in the sample app the definition for the component looks like
<component id="User.UserFinder">
<class>org.jaffa.applications.sample.modules.user.components.userfinder.ui.UserFinderComponent</class>
<type>ObjectFinder</type>
</component>
|
The key values here are...
- id - This attribute is the logical name for the component, typically in the Component class itself we create a
static String called NAME, to also hold this value, so programatically you only need to change the name in one place.
- class - This is the class name of the component controller. This will be used by the component factory to
create a instance of the component.
- type - This allows component to be categorized, typically we use 'ObjectFinder','ObjectViewer',
'ObjectLookup','ObjectMaintenance' when these are generated from the patterns, other common types are 'Custom',
when it is not based on a pattern. You are free to use this however you like, but for legacy reasons it is
mandatory in the components.dtd!
|
Running a Component |
Ok, this is the simple bit...
http://localhost:8080/MyApp/startComponent.do?component=MyComponent
|
The above URL, based on the host, port, web app name, and component can be used to directly run your component.
Assuming all is well, this will call the display() method that will refer to a form name, which the underlying
Struts architecture will translate to the name of the JSP to be displayed, and render that JSP.
What may trip you up on more complex examples ...
- Normally *.do is protected by server authentication, so you must log-in
- A user sesion should have been created, either by the UserSessionFilter, or by the WebAuthenticationManager
- Not definiting the component correctly in components.xml
- Any security you have put on the component.
- Not having struts-config.xml set up correctly with your action, formbean and global forward
- Having compile or runtime issues on your JSP or formbean
|
|