import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class ScriptDemo {
public static void main(String[] args) {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
try {
String expression = "3+4";
Object result = engine.eval(expression);
System.out.println(expression+" = "+result);
} catch(ScriptException se) {
se.printStackTrace();
}
}
}
Wednesday, September 30, 2009
Math Expression evaluator
Apache Poi example
package hsenidmobile.idews.datacollector;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.RichTextString;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
public class POIExcelReader {
public POIExcelReader() {
}
public void displayFromExcel(String xlsPath) {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(xlsPath);
}
catch (FileNotFoundException e) {
System.out.println("File not found in the specified path.");
e.printStackTrace();
}
try {
Workbook wb = WorkbookFactory.create(inputStream);
Sheet sheet = wb.getSheetAt(29);
Iteratorrows = sheet.rowIterator();
System.out.println("get the new sheet ?>>>>>");
while (rows.hasNext()) {
Row row = rows.next();
System.out.println();
System.out.println("Row No.: " + (row.getRowNum() + 1));
Iteratorcells = row.cellIterator(); |
while (cells.hasNext()) {
Cell cell = cells.next();
switch (cell.getCellType()) {
case Cell.CELL_TYPE_FORMULA: {
switch(cell.getCachedFormulaResultType()){
case Cell.CELL_TYPE_NUMERIC:{
System.out.print(" Cell No.: " + cell.getColumnIndex());
System.out.print(" Numeric value: " + cell.getNumericCellValue());
break;
}
}
break;
}
case Cell.CELL_TYPE_NUMERIC: {
System.out.print(" Cell No.: " + cell.getColumnIndex());
System.out.print(" Numeric value: " + cell.getNumericCellValue());
break;
}
case Cell.CELL_TYPE_STRING: {
RichTextString richTextString = cell.getRichStringCellValue();
if(richTextString.getString()!=null && !richTextString.getString().trim().equals("")){
System.out.print(" Cell No.: " + cell.getColumnIndex());
System.out.print(" String value: " + richTextString.getString());
}
break;
}
default: {
// System.out.print(" Type not supported.");
break;
}
}
}
}
}
catch (IOException e) {
e.printStackTrace();
} catch (InvalidFormatException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
POIExcelReader poiExample = new POIExcelReader();
// String xlsPath = "/home/rasika/dev/idews/Data_Vekpro_2006.xls";
String xlsPath = "/home/rasika/dev/idews/Mg_01.xls";
poiExample.displayFromExcel(xlsPath);
}
}
Monday, September 21, 2009
Hibernate: Session and sessionfactory
Hibernate’s SessionFactory interface provides instances of the Session class, which represent connections to the database. Instances of SessionFactory are thread-safe and typically shared throughout an application. Session instances, on the other hand, aren’t thread-safe and should only be used for a single transaction or unit of work in an application.
The Configuration class kicks off the runtime portion of Hibernate
There are three ways to create and initialize a Configuration object.
Configuration cfg = new Configuration();
SessionFactory factory = cfg.configure().buildSessionFactory();
The configure() method tells Hibernate to load the hibernate.cfg.xml file. Without that, only hibernate.properties would be loaded from the classpath.
Configuration cfg = new Configuration();
cfg.addFile("com/manning/hq/ch03/Event.hbm.xml");
Configuration cfg = new Configuration();
cfg.addClass(com.manning.hq.ch03.Event.class);
Or you can also do this programmatically with the Configuration class:
Configuration.addJar(new java.io.File("application.jar"));
Instances of the Session class represent the primary interface to the Hibernate framework.
Persisting objects
Persisting a transient object with Hibernate is as simple as saving it with the Session instance:
Event event = new Event();
// populate the event
Session session = factory.openSession();
session.save(event);
session.flush();
Suppose you want to retrieve an Event instance from the database. If you have the Event ID, you can use a Session to return it:
Event event = (Event) session.load(Event.class, eventId);
session.close();
Notice that you’re careful to close the Session. returning the database connection to the pool.There is no need to flush the Session, since you’re not persisting objects.
This example returns a collection of all Event instances.
One easy way to improve performance within the Hibernate service, as well as your applications, is to cache objects. By caching objects in memory, Hibernate avoids the overhead of retrieving them from the database each time.
Session session = factory.openSession();
Event e = (Event) session.load(Event.class, myEventId);
e.setName("New Event Name");
session.saveOrUpdate(e);
// later, with the same Session instance
Event e = (Event) session.load(Event.class, myEventId);
e.setDuration(180);
session.saveOrUpdate(e);
session.flush();
All the updates made to the Event instance are combined into a single
update when you flush the Session.
Each object placed into the cache is keyed on the class type.
The Configuration class kicks off the runtime portion of Hibernate
There are three ways to create and initialize a Configuration object.
- (1) This first snippet loads the properties and mapping files defined in thehibernate.cfg.xml file and creates the SessionFactory:
Configuration cfg = new Configuration();
SessionFactory factory = cfg.configure().buildSessionFactory();
The configure() method tells Hibernate to load the hibernate.cfg.xml file. Without that, only hibernate.properties would be loaded from the classpath.
- (2) The Configuration class can also load mapping documents programmatically:
Configuration cfg = new Configuration();
cfg.addFile("com/manning/hq/ch03/Event.hbm.xml");
- (3) Another alternative is to have Hibernate load the mapping document based on the persistent class. The following code causes Hibernate to look for a file named com/manning/hq/Event.hbm.xml in the classpath and load the associated class:
Configuration cfg = new Configuration();
cfg.addClass(com.manning.hq.ch03.Event.class);
- (4) The hibernate.cfg.xml file supports adding all mapping files in a JAR file.
Or you can also do this programmatically with the Configuration class:
Configuration.addJar(new java.io.File("application.jar"));
Instances of the Session class represent the primary interface to the Hibernate framework.
Persisting objects
Persisting a transient object with Hibernate is as simple as saving it with the Session instance:
Event event = new Event();
// populate the event
Session session = factory.openSession();
session.save(event);
session.flush();
- Calling save(...) for the Event instance assigns a generated ID value to the instance and persists the instance. (Keep in mind that Hibernate doesn’t set the ID value if the generator type is assigned.)
- The flush() call forces persistent objects held in memory to be synchronized to the database.( Sessions don’t immediately write to the database when an object is saved. Instead, the Session queues a number of database writes to maximize performance.) which closes the JDBC connection and performs some internal cleanup.
- update(...) doesn’t assign an ID value to the object.
- saveOrUpdate(...) if use this unsaved-value attribute should be set to identify the save() state. otherwise update().
Suppose you want to retrieve an Event instance from the database. If you have the Event ID, you can use a Session to return it:
Event event = (Event) session.load(Event.class, eventId);
session.close();
Notice that you’re careful to close the Session. returning the database connection to the pool.There is no need to flush the Session, since you’re not persisting objects.
This example returns a collection of all Event instances.
Query query = session.createQuery("from Event where name = ?", "Opening Presentation");
query.setParameter(0,"OpeningPresentation", Hibernate.STRING);
List events = query.list();
The question mark in the query string represents the variable, which is similar to the JDBC PreparedStatement interface. The second method parameter is the value bound to the variable, and the third parameter tells Hibernate the type of the value. (The Hibernate class provides constants for the built-in types, such as STRING, INTEGER, and LONG, so they can be referenced programmatically.
The Session cache
query.setParameter(0,"OpeningPresentation", Hibernate.STRING);
List events = query.list();
The question mark in the query string represents the variable, which is similar to the JDBC PreparedStatement interface. The second method parameter is the value bound to the variable, and the third parameter tells Hibernate the type of the value. (The Hibernate class provides constants for the built-in types, such as STRING, INTEGER, and LONG, so they can be referenced programmatically.
The Session cache
One easy way to improve performance within the Hibernate service, as well as your applications, is to cache objects. By caching objects in memory, Hibernate avoids the overhead of retrieving them from the database each time.
Session session = factory.openSession();
Event e = (Event) session.load(Event.class, myEventId);
e.setName("New Event Name");
session.saveOrUpdate(e);
// later, with the same Session instance
Event e = (Event) session.load(Event.class, myEventId);
e.setDuration(180);
session.saveOrUpdate(e);
session.flush();
All the updates made to the Event instance are combined into a single
update when you flush the Session.
Each object placed into the cache is keyed on the class type.
Sunday, September 20, 2009
Hibernate: Mapping definition xml
- The mapping definition starts with the hibernate-mapping element.
- The package attribute sets the default package for unqualified class names in the mapping.With this attribute set, you need only give the class name for other persistent classes listed in the mapping file
- To refer to a persistent class outside the given package, you must provide the fully qualified class name within the mapping document.
- If Hibernate has trouble locating a class because of a missing package on, for instance, a many-to-one element, Hibernate throws a MappingException.
- Immediately after the hibernate-mapping tag, you encounter the class tag. The class tag begins the mapping definition for a specific persistent class.
- The table attribute names the relational table used to store the state of the object.
- The id element describes the primary key for the persistent class as well as how the key value is generated.
- Each persistent class must have an id element declaring the primary key for the relational table.
- The name attribute defines the property in your persistent class that will be used to store the primary key value.
- If the column for the primary key has a different name than your object property, the column attribute is used.
- The values of the type and unsaved-value attributes depend on the generator used.
- The generator creates the primary key value for the persistent class. Hibernate provides multiple generator implementations that use various methods to create primary key values. Ex : assigned, native
- The native generator returns a short, integer, or long value. You’ve set the type attribute to long, and the id property in the Event object has a type of java.lang.Long. The value of the type attribute and the property type in the object must be the same.
- The unsaved-value attribute describes the value of the id property for transient instances of this class. The unsaved-value attribute affects how objects are stored.
- Each property element corresponds to a property in the java object. The name attribute contains the property name, whereas the type attribute specifies the property object type.
- The column used to store the property value defaults to the property name. The column attribute overrides this default behavior.
- If the type attribute is omitted, Hibernate determines the type using runtime reflection. In certain cases, you must provide the property type, since reflection may not be able to determine the desired type (such as differentiating between the Hibernate DATE and TIMESTAMP types).
- The property element may also contain the name of a serializable Java class or a user-defined type. You create a new user-defined type by implementing either the org.hibernate.UserType or org.hibernate. CompositeUserType interface.
Many-to-one element
Many-to-one associations use foreign keys to maintain the association between two persistent classes. Although the figure doesn’t display it, this association is unidirectional, meaning you can navigate from the Event instance to the Location but not from the Location to the Event instance.
Figure 3.2 page 60
<many-to-one name="location" column="location_id" class="Location">
The name attribute gives the name of the property in the object, and the optional column attribute specifies the column used to store the foreign key to the locations table. If you don’t give a column attribute, the name attribute is used as the column name. The class attribute names the associated persistent class.
many-to-one relationship lazy
lazy meaning that the associated object won’t be retrieved when the parent object is retrieved. The solution is to use proxied objects.
Object proxies can be defined in one of two ways. First, you can add a proxy attribute to the class element. You can either specify a different class or use the persistent class as the proxy. For example:
<class name="Location"
proxy="com.manning.hq.ch03.Location"...>...
</class>
The second method is to use the lazy attribute. Setting lazy="true" is a shorthand way of defining the persistent class as the proxy. Let’s assume the Location class is defined as lazy:
<class name="Location" lazy="true"...>...</class>
The lazy attribute is true by default in Hibernate 3.
An easy way to disable all proxies, including lazy collections, is to set the default-lazy attribute to true in the hibernate-mapping element
Session session = factory.openSession();
Event ev = (Event) session.load(Event.class, myEventId);
Location loc = ev.getLocation();
String name = loc.getName();
session.close();
The returned Location instance is a proxy. Hibernate populates the Location instance when getName() is called.
If you’ve guessed that you can call loc.getId() without invoking a call to the database, you’re correct. The proxied object already contains the ID value
Collections
The collections are defined as sets, meaning Hibernate manages the collections with the same semantics as a java.util.Set:
<set name="speakers">
<key column="event_id"/>
<one-to-many class="Speaker"/>
</set>
This definition declares that the Event class has a property named speakers, and that it’s a Set containing instances of the Speaker class.
The key element defines the foreign key from the collection table to the parent table. In this case, the speakers table has an event_id column referring to the id column in the events table. The one-to-many element defines the association to the Speaker class.
We’ve only touched on persisting collections with Hibernate. In addition to Sets, Hibernate also supports persistent Maps and Lists, as well as arrays of objects and primitive values.
Location of the mapping file
Suppose the class file for the Event object is stored in the com/manning/hq directory and therefore in the com.manning.hq package. The Event.hbm.xml file should also be stored in the com/manning/hq directory inside the JAR archive.
Cascades
Hibernate supports ten different types of cascades that can be applied to many-to-one associations as well as collections. The default cascade is none. Each cascade strategy specifies the operation or operations that should be propagated to child entities. The cascade types that you are most likely to use are the following:
The cascade element is added to the desired many-to-one or collection element. For example, the following configuration instructs Hibernate to delete the child Speaker elements when the parent Event is deleted:
<set name="speakers" cascade="delete">
<key column="event_id"/>
<one-to-many class="Speaker"/>
</set>
It’s important to note that Hibernate doesn’t pass the cascade off to the database. Instead, the Hibernate service manages the cascades internally. This is necessary because Hibernate has to know exactly which objects are saved, updated, and deleted.
When an object has one or more associated objects, there are two options. You can either retrieve associated objects using an outer join or by using a separate SELECT statement.
<many-to-one name="location" class="Location" fetch="join"/>
When an Event instance is loaded, the associated Location instance will
be loaded using an outer join. If you wanted to use a separate select,
the many-to-one element would look like this:
<many-to-one name="location" class="Location" fetch="select"/>
This also applies to child collections, but you can only fetch one collection using a join per persistent object. Additional collections must be fetched using the SELECT strategy.
The collections are defined as sets, meaning Hibernate manages the collections with the same semantics as a java.util.Set:
<set name="speakers">
<key column="event_id"/>
<one-to-many class="Speaker"/>
</set>
This definition declares that the Event class has a property named speakers, and that it’s a Set containing instances of the Speaker class.
The key element defines the foreign key from the collection table to the parent table. In this case, the speakers table has an event_id column referring to the id column in the events table. The one-to-many element defines the association to the Speaker class.
We’ve only touched on persisting collections with Hibernate. In addition to Sets, Hibernate also supports persistent Maps and Lists, as well as arrays of objects and primitive values.
Location of the mapping file
Suppose the class file for the Event object is stored in the com/manning/hq directory and therefore in the com.manning.hq package. The Event.hbm.xml file should also be stored in the com/manning/hq directory inside the JAR archive.
Cascades
Hibernate supports ten different types of cascades that can be applied to many-to-one associations as well as collections. The default cascade is none. Each cascade strategy specifies the operation or operations that should be propagated to child entities. The cascade types that you are most likely to use are the following:
- all—All operations are passed to child entities: save, update, and delete.
- save-update—Save and update (INSERT and UPDATE, respectively) are passed to child entities.
- delete—Deletion operations are passed to child entities.
- delete-orphan—All operations are passed to child entities, and objects no longer associated with the parent object are deleted.
The cascade element is added to the desired many-to-one or collection element. For example, the following configuration instructs Hibernate to delete the child Speaker elements when the parent Event is deleted:
<set name="speakers" cascade="delete">
<key column="event_id"/>
<one-to-many class="Speaker"/>
</set>
It’s important to note that Hibernate doesn’t pass the cascade off to the database. Instead, the Hibernate service manages the cascades internally. This is necessary because Hibernate has to know exactly which objects are saved, updated, and deleted.
When an object has one or more associated objects, there are two options. You can either retrieve associated objects using an outer join or by using a separate SELECT statement.
<many-to-one name="location" class="Location" fetch="join"/>
When an Event instance is loaded, the associated Location instance will
be loaded using an outer join. If you wanted to use a separate select,
the many-to-one element would look like this:
<many-to-one name="location" class="Location" fetch="select"/>
This also applies to child collections, but you can only fetch one collection using a join per persistent object. Additional collections must be fetched using the SELECT strategy.
Hibernate: Introduciton
Hibernate, an object/relational mapping framework for Java applications. Hibernate provides the bridge between the data-base and the application by storing application objects in the database for the developer, rather than requiring the developer to write and maintain mountains of code to store and retrieve objects.
Hibernate is a solid, productive Object Relational Mapping (ORM) tool that lets developers think and work with objects rather than tables and columns.
Developers don’t work with Hibernate in a vacuum. In addition to stan-dard Java, developers often use Hibernate with a host of other third-party (often open source) tools and libraries, including J2EE (web applica-tions); build tools like Ant; unit-testing frameworks like JUnit; and frame-works like XDoclet, Struts, WebWork, Tapestry, and Spring.
Hibernate is a solid, productive Object Relational Mapping (ORM) tool that lets developers think and work with objects rather than tables and columns.
Developers don’t work with Hibernate in a vacuum. In addition to stan-dard Java, developers often use Hibernate with a host of other third-party (often open source) tools and libraries, including J2EE (web applica-tions); build tools like Ant; unit-testing frameworks like JUnit; and frame-works like XDoclet, Struts, WebWork, Tapestry, and Spring.
- How to generate your database from Hibernate mappings using the SchemaExport tool ? (discuss later)
Hibernate allows you to use basic java.util collections classes to express both one-to-many and many-to-many relationships between entities.
- How and why you can use Hibernate’s custom types, which let you define new datatypes that can map to database columns ? (discuss later).
- Hibern8IDE, a tool that lets you rapidly test and try your queries.
- Few patterns like the Data Access Object (DAO) and Layer Super types.
- In addition, we explain how to generate your configuration files, hibernate.cfg.xml, using XDoclet.
- JUnit and DBUnit, to verify that your Hibernate application works as expected.
- When refer to persistence in this book, we’re referring to storing application data in a relational database.
The model used by relational databases, called the relational model, represents data in two-dimensional tables.
However, when you’re working with object-oriented applications, you may encounter a problem when you try to persist objects to a relational model.
Resolving the avbove two model differences has been the subject of much debate over the years and has been referred to as the object/relational impedance mismatch or just impedance mismatch.
If tables refer to each other through columns other than primary keys, your chosen ORM solution may have trouble adapting to the legacy schema.
Alternative solutions, such as iBATIS, may be a better candidate for persisting legacy databases. (iBATIS (www.ibatis.com) is an alternative to Hibernate.)
ORM is a good solution for legacy databases when the schema
- Is highly normalized
- Has primary keys
- Has foreign key relationships referring to primary keys, not col- umns
A domain model is the collection of related objects describing the problem domain for an application. Each object in the domain model represents some significant component in the application.
For example you have the JDBC resultset, Now that you have the results, how should you return the data to the application? There are two options: You can convert the results either into a list of Event objects or into a list of Map instances.
After examining the shortcomings in our persistence techniques using direct JDBC, let’s discuss the benefits of using Hibernate for application persistence.
The core benefits of Hibernate are simplicity, flexibility, completeness, and performance.
Rather than the handful of classes and configuration properties required by some persistence solutions, such as EJBs, Hibernate requires requires a single runtime configuration file and one mapping document for each application object to be persisted.
- The runtime configuration file can be a property file or an XML file. or can be done programmatically.
- Lazy collections provide another performance enhancement. Rather than load collections of objects when the parent object is loaded, collections are populated only when they’re accessed by the application.
- Let’s say you have a User class with a oneto-one association to a Department class. When you’re retrieving a User instance, you don’t always need the associated Department instance, so you can declare that the object should be retrieved only when needed by setting outer-join to false.
- It’s also possible to declare proxies for objects, resulting in the objects being populated only when accessed by the developer. When you declare a proxy, Hibernate creates an unpopulated representation of the persistent class. The proxy is replaced with the actual instance of the persistent class only when you access the object by calling one of its methods.
- Proxies are related to the outer-join setting we just mentioned. Usingthe same brief example, if the Department class is declared to have aproxy, you don’t need to set the outer-join from the User to theDepartment to false—the Hibernate service will only populate theDepartment instance when needed.
- Object caching also plays a large role in improving application performance. Hibernate supports various open-source and commercial caching products. Caching can be enabled for a persistent class or for acollection of persistent objects,
- Query results can also be cached, but doing so only benefitsqueries that run with the same parameters. Query caching doesn’t significantly benefit application performance, but the option is availablefor appropriate cases.
- By using Hibernate, you can avoid writing vendor-specificJDBC code.
- Hibernate works with various supportservices, such as connection pools, caching services, and transactionmanagers. It also lets you maintain additional support services byimplementing simple interfaces.
- Hibernate provides two alternative configuration files: a standard Javaproperties file called hibernate.properties and an XML formatted file called hibernate.cfg.xml.
- If both the hibernate.properties and hibernate.cfg.xml files are found in the application classpath, then hibernate.cfg.xml overrides the settings found in the hibernate.properties file.
- Database connections may be provided by the Hibernate framework or from a JNDI Data Source. Athird method, user-provided JDBC connections, is also available, but it’s rarely used.
- Since you’re not specifying a connection pool, which we cover later in this chapter, Hibernate uses its own rudimentary connection-pooling mechanism. The internal pool is fine for basic testing, but you shouldn’t use it in production.
- The dialect property tells Hibernate which SQL dialect to use for certain operations. Although not strictly required, it should be used toensure Hibernate Query Language (HQL) statements are correctly converted into the proper SQL dialect for the underlying database.
- Mapping definitions for persistent objects may be stored together in asingle mapping file. since storing the definitions for a large number of persistent classes in one mapping file can be cumbersom. If you have all mapping definitions in a single file, it may be hard to debug and isolate any error to a specific class definition.
log4j configuration
--------- go to page 44 get the ant file definistions as a image, log4j basic fonfiguration
Ant xml definitions
-------- go to page 36 get the ant file definistions as a image, ant definition
-------- go to page 52 get the ant file definistions as a image, ant definition
-------- go to page 55 get the ant file definistions as a image, ant definition
-------- go to page 52 get the ant file definistions as a image, ant definition
-------- go to page 55 get the ant file definistions as a image, ant definition
Configure Mysql with firewall
if you have firewall software installed, such as Norton Internet Security, you’ll need to configure the firewall to permit access for outgoing connections from your local computer with IP address 127.0.0.1 (localhost) to your MySQL server at port 3306.
Monday, September 14, 2009
Patterns - 027: Structural patterns ( Remote Proxy )
sometimes a client object may not be able to access a service provider object (also referred to as a target object) by normal means. This could happen for a variety of reasons depending on:
- The location of the target object — The target object may be present in a different address space in the same or a different computer.
- The state of existence of the target object —The target object may not exist until it is actually needed to render a service or the object may be in a compressed form.
- Special Behavior —The target object may offer or deny services based on the access privileges of its client objects. Some service provider objects may need special consideration when used in a multithreaded environment.
In such cases, the Proxy pattern suggests using a separate object referred to as a proxy to provide a means for different client objects to access the target object in a normal, straightforward manner.
- The Proxy object offers the same interface as the target object.
- The Proxy object interacts with the target object on behalf of a client object and takes care of the specific details of communicating with the target object.
- A client can call the Proxy object through its interface and the Proxy object in turn forwards those calls to the target object.
Proxy
- – The client object cannot access the target object directly.
- – A proxy object provides access control to the target object (in the case of the protection proxy).
- – A proxy object does not add any additional functionality.
- – A Proxy object represents a single object. – The client object cannot access the target object directly.
- – A Proxy object provides access control to the single target object.
- – Client requests are first received by the Proxy object, but are never processed directly by the Proxy object.
- – Client requests are always forwarded to the target object.
- – Response to the request is guaranteed, provided the communication between the client and the server locations is working.
Example
In reality, when the client invokes a method such as saveCustomerData on the CustomerFacade remote object, the CustomerFacade_stub object, which is local to the client, first receives it. The CustomerFacade_stub then transmits the method call to the server for processing.
On the server side the CustomerFacade_skel is responsible for receiving the method call through the lower levels of the communication network. It then dispatches it to the actual CustomerFacade object on the server. In case of the saveCustomerData method, the CustomerFacade object creates the necessary subsystem objects and invokes the required methods on these objects to validate and save the customer data. The result of the processing is carried back to the client in the reverse manner.
As can be seen from above, the CustomerFacade_stub class enables the client object to invoke methods on the remote CustomerFacade object as if it is present locally, which, otherwise, is not accessible by normal means. Thus the stub functions as a remote proxy.
Saturday, September 5, 2009
Patterns - 026: Structural patterns ( facade )
In real world applications, a subsystem could consist of a large number of classes. Clients of a subsystem may need to interact with a number of subsystem classes for their needs. This kind of direct interaction of clients with subsystem classes leads to a high degree of coupling between the client objects and the subsystem.
Whenever a subsystem class undergoes a change, such as a change in its interface, all of its dependent client classes may get affected.
The Façade pattern is useful in such situations. The Façade pattern provides a higher level, simplified interface for a subsystem resulting in reduced complexity and dependency. This in turn makes the subsystem usage easier and more manageable.
With a Façade object in place, clients interact with the Façade object instead of interacting directly with subsystem classes. The Façade object takes up the responsibility of interacting with the subsystem classes.
Example
Let us build an application that:
- Accepts customer details (account, address and credit card details)
- Validates the input data
- Saves the input data to appropriate data files
In order to validate and save the input data, the client AccountManager would:
- Create Account, Address and CreditCard objects
- Validate the input data using these objects
- Save the input data using these objects
Before applying the facade
Applying the Façade pattern, let us define a Façade class CustomerFacade that offers a higher level, simplified interface to the subsystem consisting of customer data processing classes (Address, Account and CreditCard).
The CustomerFacade class offers a higher level business service in the form of the saveCustomerData method. Instead of interacting with each of the subsystem components directly, the client AccountManager can make use of the higher level, more simplified interface offered by the CustomerFacade object to validate and save the input customer data.
Here are few notes to consider while applying the Façade pattern:
- A façade should not be designed to provide any additional functionality.
- Never return subsystem components from Façade methods to clients. As an example, having a method as CreditCard getCreditCard() , would expose the subsystem to clients and the application may not be able o realize the full benefits of using the Façade pattern.
Patterns - 025: Structural patterns ( chain of responsibility )
When there is more than one object that can handle or fulfill a client request, the CoR pattern recommends giving each of these objects a chance to process the request in some sequential order. Applying the CoR pattern in such a case, each of these potential handler objects can be arranged in the form of a chain, with each object having a pointer to the next object in the chain.
The first object in the chain receives the request and decides either to handle the request or to pass it on to the next object in the chain.
The request flows through all objects in the chain one after the other until the request is handled by one of the handlers in the chain or the request reaches the end of the chain without getting processed.
The following are some of the important characteristics of the CoR pattern:
- The set of potential request handler objects and the order in which these objects form the chain can be decided dynamically at runtime by the client depending on the current state of the application.
- A client can have different sets of handler objects for different types of requests depending on its current state. Also, a given handler object may need to pass on an incoming request to different other handler objects depending on the request type and the state of the client application. In Java this can be accomplished by having different handlers implement a common interface or be subclasses of a common abstract parent class.
- The client object that initiates the request or any of the potential handler objects that forward the request do not have to know about the capabilities of the object receiving the request. This means that neither the client object nor any of the handler objects in the chain need to know which object will actually fulfill the request.
- Request handling is not guaranteed. This means that the request may reach the end of the chain without being fulfilled.
Example
Let us consider an application to simulate the purchase request (PR) authorization process in a typical organization. Let us consider an organization with four levels of management personnel
listed in the Table who can authorize a PR with an amount less than their authorization limit.
Management Level | Authorization Limit |
---|---|
Branch Manager | $25,000 |
Regional Director | $100,000 |
Vice President | $200,000 |
President and COO | $400,000 |
Applying the CoR pattern, let us define an abstract PRHandler class that declares the common interface to be offered by all of the potential PR handlers.
public abstract class PRHandler {
private PRHandler nextHandler;
private String handlerName;
public PRHandler(String name) {
handlerName = name;
}
public String getName() {
return handlerName;
}
public abstract boolean authorize(PurchaseRequest request);
public PRHandler getNextHandler() {
return nextHandler;
}
public void setNextHandler(PRHandler handler) {
nextHandler = handler;
};
}
class BranchManager extends PRHandler {
static double LIMIT = 25000;
public BranchManager(String name) {
super(name);
}
public boolean authorize(PurchaseRequest request) {
double amount = request.getAmount();
if (amount <= LIMIT) {
System.out.println(" Branch Manager " + getName() +
" has authorized the PR - " + request);
return true;
} else {
//forward the request to the next handler
return getNextHandler().authorize(request);
}
}
}
class RegionalDirector extends PRHandler {
static double LIMIT = 100000;
public RegionalDirector(String name) {
super(name);
}
public boolean authorize(PurchaseRequest request) {
double amount = request.getAmount();
if (amount <= LIMIT) {
System.out.println(" Regional Director " + getName() +
" has authorized the PR - " +
request);
return true;
} else {
//forward the request to the next handler
return getNextHandler().authorize(request);
}
}
}
class VicePresident extends PRHandler {
static double LIMIT = 200000;
public VicePresident(String name) {
super(name);
}
public boolean authorize(PurchaseRequest request) {
double amount = request.getAmount();
if (amount <= LIMIT) {
System.out.println(" V.P. " + getName() +
" has authorized the PR - " + request);
return true;
} else {
//forward the request to the next handler
return getNextHandler().authorize(request);
}
}
}
class PresidentCOO extends PRHandler {
static double LIMIT = 400000;
public PresidentCOO(String name) {
super(name);
}
public boolean authorize(PurchaseRequest request) {
double amount = request.getAmount();
if (amount <= LIMIT) {
System.out.println(" President & COO " + getName() +
" has authorized the PR - " + request);
return true;
} else {
System.out.println("PR - " + request +
" couldn't be authorized.\n " +
"Executive Board needs to be " +
"consulted for approval \n" +
"reason: Amount too large");
return false;
}
}
}
public class PRManager {
private BranchManager branchManager;
private RegionalDirector regionalDirector;
private VicePresident vicePresident;
private PresidentCOO coo;
public static void main(String[] args) {
PRManager manager = new PRManager();
manager.createAuthorizationFlow();
PurchaseRequest request =
new PurchaseRequest(1, "Office Supplies",10000);
manager.branchManager.authorize(request);
request = new PurchaseRequest(2, "HardWare Procurement",
175000);
manager.branchManager.authorize(request);
request = new PurchaseRequest(3, "AD Campaign",800000);
manager.branchManager.authorize(request);
}
public void createAuthorizationFlow() {
branchManager = new BranchManager("Robin");
regionalDirector = new RegionalDirector("Oscar");
vicePresident = new VicePresident("Kate");
coo = new PresidentCOO("Drew");
branchManager.setNextHandler(regionalDirector);
regionalDirector.setNextHandler(vicePresident);
vicePresident.setNextHandler(coo);
}
}
class PurchaseRequest {
private int ID;
private String description;
private double amount;
public PurchaseRequest(int id, String desc, double amt) {
ID = id;
description = desc;
amount = amt;
}
public double getAmount() {
return amount;
}
public String toString() {
return ID + ":" + description;
}
}
|
Friday, September 4, 2009
Patterns - 024: Structural patterns ( adapter )
In general, clients of a class access the services offered by the class through its interface. Sometimes, an existing class may provide the functionality required by a client, but its interface may not be what the client expects.
In such cases, the existing interface needs to be converted into another interface, which the client expects.
This can be accomplished by using the Adapter pattern. The Adapter pattern suggests defining a wrapper class around the object with the incompatible interface. This wrapper object is referred as an adapter and the object it wraps is referred to as an adaptee. The adapter provides the required interface expected by the client.
Class Adapter
A class adapter is designed by subclassing the adaptee class. In addition, a class adapter implements the interface expected by the client object. When a client object invokes a class adapter method, the adapter internally calls an adaptee method that it inherited.
Object Adapter
An object adapter contains a reference to an adaptee object. Similar to a class adapter, an object adapter also implements the interface, which the client expects. When a client object calls an object adapter method, the object adapter invokes an appropriate method on the adaptee instance whose reference it contains.
Class Adapters | Object Adapters |
---|---|
Based on the concept of inheritance. | Uses object composition. |
Can be used to adapt the interface ofthe adaptee only. Cannot adapt theinterfaces of its subclasses, as theadapter is statically linked with theadaptee when it is created. | Can be used to adapt the interface of theadaptee and all of its subclasses. |
Because the adapter is designed as asubclass of the adaptee, it is possibleto override some of the adaptee’sbehavior.Note: In Java, a subclass cannot override amethod that is declared as final in itsparent class. | Cannot override adaptee methods.Note: Literally, cannot “override” simplybecause there is no inheritance. Butwrapper functions provided by theadapter can change the behavior as required. |
The client will have some knowledge of the adatee’s interface as the full public interface of the adaptee is visible to the client. | The client and the adaptee are completely decoupled. Only the adapter is aware of the adaptee’s interface. |
In Java applications: Suitable when the expected interface is available in the form of a Java interface and not as an abstract or concrete class. This is because the Java programming language allows only single inheritance. Since a class adapter is designed as a subclass of the adaptee class, it will not be able to subclass the interface class (representing the expected interface) also, if the expected interface is available in the form of an abstract or concrete class. | In Java applications: Suitable even when the interface that a client object expects is available in the form of an abstract class. Can also be used if the expected interface is available in the form of a Java interface. Or When there is a need to adapt the interface of the adaptee and also all of its subclasses. |
In Java applications: Can adapt methods with protected access specifier. | In Java applications: Cannot adapt methods with protected access specifier, unless the adapter and the adaptee are designed to be part of the same package. |
Example
Let us build an application to validate a given customer address. This application can be part of a larger customer data management application.
The application already has a Customer object which validate the USAddress that implements the AddressValidator interface by calling the isValidAddress() method.
public interface AddressValidator {
public boolean isValidAddress(String inp_address,
String inp_zip, String inp_state);
}
|
Let us say that the application needs to be enhanced to deal with customers from Canada as well.
Let us assume that a utility class CAAddress, with the required functionality to validate a given Canadian address, already exists.
But The CAAddress class offers an isValidCanadianAddr method, but the Customer expects an isValidAddress method as declared in the AddressValidator interface. This incompatibility in the interface makes it difficult for a Customer object to use the existing CAAddress class.
Changing the CAAddress class interface can affect all of those current clients of the CAAddress class.
Class Adaptor
Applying the Adapter pattern, a class adapter CAAddressAdapter can be designed as a subclass of the CAAddress class implementing the AddressValidator interface.
Because the adapter CAAddressAdapter implements the AddressValidator interface, client objects can access the adapter CAAddressAdapter objects without any problems. When a client object invokes the isValidAddress method on the adapter instance, the adapter internally translates it into a call to the inherited isValidCanadianAddr method.
public class CAAddressAdapter extends CAAddress
implements AddressValidator {
public boolean isValidAddress(String inp_address,
String inp_zip, String inp_state) {
return isValidCanadianAddr(inp_address, inp_zip,
inp_state);
}
}
|
Object Adaptor
Now let us assume that the client expects the AddressValidator interface to be available as an abstract class instead of a Java interface. Because the adapter CAAdapter has to provide the interface declared by the AddressValidator abstract class, the adapter needs to be designed to subclass the AddressValidator abstract class and implement its abstract methods. Because multiple inheritance is not supported in Java, now the adapter CAAddressAdapter cannot subclass the existing CAAddress class as it has already used its only chance to subclass from another class.
Applying the object Adapter pattern, the CAAddressAdapter can be designed to contain an instance of the adaptee CAAddress . This adaptee instance is passed to the adapter by its clients, when the adapter is first created. In general, the adaptee instance contained by an object adapter may be provided in the following two ways:
- Clients of the object adapter may pass the adaptee instance to the adapter. This approach is more flexible in choosing the class to adapt from, but then the client may become aware of the adaptee or the fact of adaptation. It is more suitable when the adapter needs any specific state from the adaptee object besides its behavior.
- The adapter may create the adaptee instance on its own. This approach is relatively less flexible and suitable when the adapter does not need any specific state from the adaptee, but needs only its behavior.
public abstract class AddressValidator {
public abstract boolean isValidAddress(String inp_address,
String inp_zip, String inp_state);
}
class CAAddressAdapter extends AddressValidator {
private CAAddress objCAAddress;
public CAAddressAdapter(CAAddress address) {
objCAAddress = address;
}
public boolean isValidAddress(String inp_address,
String inp_zip, String inp_state) {
return objCAAddress.isValidCanadianAddr(inp_address,
inp_zip, inp_state);
}
}
|
Subscribe to:
Posts (Atom)