Java_J2EE_Job_Interview_Companion
.pdfEmerging Technologies/Frameworks… |
321 |
code (e.g. Spring) assumes the responsibility of locating and instantiating these servicing components and supplying the relevant references when needed to the client code whereby acting as the factory objects. This external piece of code is often referred to as IoC (specifically known as dependency injection) container or framework.
SpringConfig.xml
<beans>
<bean id="car" class="CarBO" singleton="false" > <constructor-arg>
<ref bean="carDao" /> </constructor-arg>
</bean>
<bean id="carDao” class="CarDAOImpl" singleton="false" />
</beans>
Now your CarBO code changes to: class CarBO {
private CarDAO dao = null;
public CarBO(CarDAO dao) { this.dao = dao;
}
public void getCars(String color) {
//if you need to use a different implementation class say FastCarDAOImpl then need to //make one change only to the SpringConfig.xml file to use a different implementation //class(i.e. class=”FastCarDAOImpl”) rather than having to change all the callers.
List listCars = dao.findCarsByColor(color);
}
}
Your calling code would be (e.g. from a Web client or EJB client ):
ApplicationContext ctx = new FileSystemXmlApplicationContext("SpringConfig.xml");
//lookup “car” in your caller where “carDao” is dependency injected using the constructor. CarBO bo = (CarBO)ctx.getBean("car"); //Spring creates an instance of the CarBO object with
//an instance of CarDAO object as the constructor arg.
String color = red; bo.getCars(color)
You can use IoC containers like Spring framework to inject your business objects and DAOs into your calling classes. Dependencies can be wired by either using annotations or using XML as shown above. Tapestry 4.0 makes use of the Hivemind IoC container for injecting application state objects, pages etc.
IoC or dependency injection containers generally control creation of objects (by calling “new”) and resolve dependencies between objects it manages. Spring framework, Pico containers, Hivemind etc are IoC containers to name a few. IoC containers support eager instantiation, which is quite useful if you want self-starting services that “come up” on their own when the server starts. They also support lazy loading, which is useful when you have many services which may only be sparsely used.
Q 10: What are the different types of dependency injections? FAQ
A 10: There are three types of dependency injections.
Constructor Injection (e.g. Pico container, Spring etc): Injection is done through constructors.
Setter Injection (e.g. Spring): Injection is done through setter methods.
Interface Injection (e.g. Avalon): Injection is done through an interface.
Spring supports both constructor-based injection and setter-based injection. The above example on Q9 is based on the constructor-based injection. Here is the same example using the Spring’s setter-based injection.
SpringConfig.xml
<beans>
<bean id="car" class="CarBO" singleton="false" >
322 |
Emerging Technologies/Frameworks… |
<property |
name=”dao”> |
ref bean="carDao" /> </property>
</bean>
<bean id="carDao” class="CarDAOImpl" singleton="false" /> </beans>
Now your CarBO code changes to: class CarBO {
private CarDAO dao = null;
public CarBO() {} ….
public void setDao(CarDAO carDao){ this.dao = carDao;
}
public void getCars(String color) {
//if you need to use a different implementation class say FastCarDAOImpl then need to //make one change only to the SpringConfig.xml file to use a different implementation //class(i.e. class=”FastCarDAOImpl”) rather than having to change all the callers.
List listCars = dao.findCarsByColor(color);
}
}
The above SpringConfig.xml code creates an instance of CarBO object and CarDAO object and calls the setDao(CarDAO carDao) method, passing in the reference to the CarDAO object.
Your caller code would be (e.g. from a Web client or EJB client ) same as above:
ApplicationContext ctx = new FileSystemXmlApplicationContext("SpringConfig.xml");
//lookup “car” in your caller where “carDao” is dependency injected using the setter method. CarBO bo = (CarBO)ctx.getBean("car"); //Spring creates an instance of the CarBO object with
//an instance of CarDAO object and then invokes the //setter method setDao(CarDAO carDao) on CarBO.
String color = red; bo.getCars(color)
Q. Which one to use?
The choice between constructor-based injection and setter-based injection goes back to OO programming question – Should you fill fields in a constructor or setter methods?. There is no clear cut answer for this question. It is a good practice to start with constructor-based injection since it permits immutability (i.e. if your classes are meant to be immutable) and also constructors with parameters give you a clear statement of what is required to create a valid object. If there is more than one way to create a valid object then provide multiple constructors. But if you have a lot of constructor parameters then your constructors can look messy and also if you have many string based parameters then setter-based injection will be more descriptive because each setter name will indicate what the string is supposed to do (e.g. setFirstName(…), setLastName(…) etc)
Q 11: What are the benefits of IoC (aka Dependency Injection)? FAQ
A 11:
Minimizes the amount of code in your application. With IoC containers you do not care about how services are created and how you get references to the ones you need. You can also easily add additional services by adding a new constructor or a setter method with little or no extra configuration.
Makes your application more testable by not requiring any singletons or JNDI lookup mechanisms in your unit test cases. IoC containers make unit testing and switching implementations very easy by manually allowing you to inject your own objects into the object under test.
Loose coupling is promoted with minimal effort and least intrusive mechanism. The factory design pattern is more intrusive because components or services need to be requested explicitly whereas in IoC the dependency is injected into the requesting code. Also some containers promote the design to interfaces not to implementations design concept by encouraging managed objects to implement a well-defined service interface of your own.
Emerging Technologies/Frameworks… |
323 |
IoC containers support eager instantiation and lazy loading of services. Containers also provide support for instantiation of managed objects, cyclical dependencies, life cycle management, and dependency resolution between managed objects etc.
Q 12: What is the difference between a service locator pattern and an inversion of control pattern?
A 12:
|
Service locator |
Inversion Of Control (IoC) |
|
|
The calling class which needs the dependent classes |
In IoC (aka Dependency Injection) pattern the responsibility is |
|
|
needs to tell the service locator which classes are needed. |
shifted to the IoC containers to locate and load the dependent |
|
|
Also the calling classes have the responsibility of finding |
classes based on the information provided in the descriptor files. |
|
|
these dependent classes and invoking them. This makes |
Changes can be made to the dependent classes by simply |
|
|
the classes tightly coupled with each other. |
modifying the descriptor files. This approach makes the |
|
|
|
dependent classes loosely coupled with the calling class. |
|
|
|
|
|
|
Difficult to unit test the classes separately due to tight |
Easy to unit test the classes separately due to loose coupling. |
|
|
coupling. |
|
|
|
|
|
|
|
|
|
|
Q 13: Why dependency injection is more elegant than a JNDI lookup to decouple client and the service? A 13: Here are a few reasons why a JNDI look up is not elegant:
The client and the service being looked up must agree on a string based name, which is a contract not enforced by the compiler or any deployment-time checks. You will have to wait until runtime to discover any discrepancies in the string based name between the lookup code and the JNDI registry.
The JNDI lookup code is verbose with its own try-catch block, which is repeated across the application.
The retrieved service objects are not type checked at compile-time and could result in a casting error at runtime.
Dependency injection is more elegant because it promotes loose coupling with minimal effort and is the least intrusive mechanism. Dependency is injected into requesting piece of code by the IoC containers like Spring etc. With IoC containers you do not care about how services are created and how you get references to the ones you need. You can also easily add additional services by adding a new constructor or a setter method with little or extra configuration.
Q 14: Explain Object-to-Relational (O/R) mapping?
A 14: There are several ways to persist data and the persistence layer is one of the most important layers in any application development. O/R mapping is a technique of mapping data representation from an object model to a SQL based relational model.
O/R mapping is well suited for read Æ modify Æ write centric applications and not suited for write centric applications (i.e. batch processes with large data sets like 5000 rows or more) where data is seldom read. Although this was generally true of many earlier O/R mapping frameworks, most today (including latest Hibernate) allow for efficient ways of performing large batch style write operations. O/R mapping tools/frameworks allow you to model inheritance (Refer Q101 in Enterprise section), association and composition class relationships. O/R mapping tools work well in 80-90% of cases. Use basic database features like stored procedures, triggers etc, when O/R mapping is not appropriate. Keep in mind that no one size fits all solution. Always validate your architectural design with a vertical slice and test for performance. Some times you have to handcraft your SQL and a good O/R mapping (aka ORM) tool/framework should allow that. O/R mapping tools/frameworks allow your application to be:
•Less verbose (e.g. transparent persistence , Object Oriented query language , transitive persistence etc)
•More portable (i.e. vendor independence due to multi dialect support )
•More maintainable (i.e. transparent persistence, inheritance mapping strategies, automatic dirty checking etc).
Takes care of much of the plumbing like connection establishment, exception handling, configuration etc. You can often leverage the framework’s strategies and capabilities to get efficiencies. Also provides support for eager fetching, lazy loading (i.e. using proxy objects), caching strategies and detached objects (no DTOs required). Hibernate is a popular O/R mapping (aka ORM) framework, which provides above mentioned benefits and features.
Emerging Technologies/Frameworks… |
327 |
Q. What are the benefits of detached objects?
•Detached objects can be passed across layers all the way up to the presentation layer without having to use any DTOs (Data Transfer Objects). You can later on re-attach the detached objects to another session.
Session session1 = sessionFactory.openSession();
Car myCar = session1.get(Car.class, carId); //”myCar” is a persistent object at |
this stage. |
|
session1.close(); |
//once the session is closed “myCar” becomes a detached |
object |
you can now pass the “myCar” object all the way upto the presentation tier. It can be modified without any effect to your database table.
myCar.setColor(“Red”); |
//no effect on the database |
When you are ready to persist this change to the database, it can be reattached to another session as shown below:
Session session2 |
= sessionFactory.openSession(); |
|
Transaction tx = |
session2.beginTransaction(); |
|
session2.update(myCar); |
//detached object ”myCar” gets re-attached |
|
tx.commit(); |
|
//change is synchronized with the database. |
session2.close() |
|
|
•When long transactions are required due to user think-time, it is the best practice to break the long transaction up into two or more transactions. You can use detached objects from the first transaction to carry data all the way up to the presentation layer. These detached objects get modified outside a transaction and later on reattached to a new transaction via another session.
Q. How does Hibernate distinguish between transient (i.e. newly instantiated) and detached objects?
• Hibernate uses the “version” property, if there is one.
• If not uses the identifier value. No identifier value means a new object. This does work only for Hibernate managed surrogate keys. Does not work for natural keys and assigned (i.e. not managed by Hibernate) surrogate keys.
• Write your own strategy with Interceptor.isUnsaved().
Q. What is a Hibernate transaction object?
Transaction is a single threaded, short lived object used by the application to specify atomicity. Transaction abstracts your application code from underlying JDBC, JTA or CORBA transactions. At times a session can span several transactions. When long transactions are required due to user think-time, it is the best practice to break the long transaction up into two or more transactions. You can use detached objects from the first transaction to carry data all the way up to the presentation layer. These detached objects get modified outside a transaction and later on re-attached to a new transaction via another session.
Transaction tx = session.beginTransaction(); Employee emp = new Employee(); emp.setName(“Brian”); emp.setSalary(1000.00);
session.save(emp);
tx.commit(); //close session
Q. How do you query the database with Hibernate?
Hibernate provides a very robust querying API that supports query strings, named queries and queries built as aggregate expressions. The most flexible way is using the Hibernate Query Language syntax (HQL), which is easy to understand and is an Object Oriented extension to SQL, which supports inheritance and polymorphism.
Query query = session.createQuery(“Select car from Car as car where car.color = :color”); query.setString(“color”,”black”);
List list = query.list();
HQL |
SQL |
HQL uses classes and properties instead of tables and columns. |
SQL uses tables and columns and is more verbose. |
HQL is less verbose than SQL and supports automatic association |
|
328 |
|
|
|
Emerging Technologies/Frameworks… |
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
joining. |
|
|
|
|
|
|
|
Select car.* from Car |
as |
car join |
Part |
|
|
|
|
|
|
|
|
|
|
|
part on car.part_id |
= |
part.id |
where |
|
|
|
|
|
|
|
|
|
|
|
car.color = ‘black’ |
and part.cost > |
|
||
|
|
Select car |
from Car |
as |
car join |
car.parts |
as |
|
||||||
|
|
part where |
car.color |
= |
‘black’ and |
part.cost |
> |
|
|
100”); |
|
|
|
|
|
|
100”); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Type-safe queries can be handled by the object oriented query by criteria approach.
String color = “black”;
Criteria criteria = session.createCriteria(Car.class); criteria.add(Expression.eq(“color”, color)); Collection col = criteria.list();
You can also use Hibernate’s direct SQL query feature. If none of the above meets your requirements then you can get a plain JDBC connection from a Hibernate session.
Q. How does hibernate support legacy applications?
You can use user defined data types and composite primary keys to get additional flexibility to support legacy applications. It is best practice to use wrapper classes like Boolean, Integer, Long etc instead of primitive types in your persistent classes. For example If you have a legacy application, which has the value of null for a Boolean property in its legacy table, then hibernate will throw a PropertyAccessException if you use the primitive type boolean since it cannot take the null value.
Q. Explain some of the following attributes used in *.hbm.xml mapping file?
Attribute |
|
Description and possible values |
|
|
Example |
|
cascade |
|
Lets you control your graph of objects as to how |
|
<hibernate-mapping> |
|
|
|
|
automatically any associated objects gets saved, |
|
<class name=”Car” table=”car”> |
|
|
|
|
updated or deleted. It is also known as transitive |
|
…. |
|
|
|
|
persistence. |
|
<set name=”parts” cascade=”all” lazy=”true”> |
|
|
|
|
none (default): no automatic action. |
|
<key column=”part_id” /> |
|
|
|
|
|
<one-to-many class=”com.Part” /> |
|
||
|
|
save-update: save or update actions are automatically |
|
</set> |
|
|
|
|
|
…. |
|
||
|
|
passed to the child entities. |
|
</class> |
|
|
|
|
delete: Delete actions are automatically passed to child |
|
</hibernate-mapping> |
|
|
|
|
|
|
|
||
|
|
entities. |
|
|
|
|
|
|
delete-orphan: When a child is removed from the |
|
|
|
|
|
|
parent, then the child is automatically deleted. |
|
|
|
|
|
|
all: save, update and delete actions are passed to child |
|
|
|
|
|
|
entities but not delete-orphan. |
|
|
|
|
|
|
all-delete-orphan: save, update, delete and delete- |
|
|
|
|
|
|
orphan actions are passed to child entities. |
|
|
|
|
|
|
There are other cascade values such as merge, |
|
|
|
|
|
|
replicate, persist, lock etc. |
|
|
|
|
|
|
If you have a true composition relationship, where if the |
|
|
|
|
|
|
parent gets deleted then the children should also be |
|
|
|
|
|
|
deleted, then you should set the cascade attribute to all- |
|
|
|
|
|
|
delete-orphan. For example if an Order object is deleted |
|
|
|
|
|
|
then all its LineItem objects (i.e. children) should also be |
|
|
|
|
|
|
deleted as well. |
|
|
|
|
|
|
|
|
|
|
|
inverse |
|
This attribute is used when you use the one-to-many and |
|
//one-to-many side |
||
|
|
many-to-one bidirectional association to indicate that |
|
<hibernate-mapping> |
|
|
|
|
many-to-one side controls the association as opposed to |
|
<class name=”Car” table=”car”> |
|
|
|
|
one-to-many side. |
|
…. |
|
|
|
|
If you do not have the inverse flag or if it is set to false |
|
<set name=”parts” cascade=”all” inverse=”true”> |
|
|
|
|
|
<key column=”part_id” /> |
|
||
|
|
then the one-to-many side will control the association, |
|
<one-to-many class=”com.Part” /> |
|
|
|
|
which means if you have the following scenario: |
|
</set> |
|
|
|
|
|
|
|
…. |
|
|
|
Car car1 = new Car(“blue”); |
|
|
</class> |
|
|
|
|
|
Emerging Technologies/Frameworks… |
329 |
|||||||
|
|
|
|
|
|
|
|
|||||
|
|
car1.getParts().add(new Part(“Steering”)); |
|
|
</hibernate-mapping> |
|
|
|||||
|
|
car1.getParts().add(new Part(“Brake”)); |
|
|
|
|
|
|
|
|||
|
|
session.save(car1); |
|
|
|
|
|
//many-to-one side |
|
|||
|
|
This will result in 3 INSERT SQL calls (1 for the parent |
|
|
|
|||||||
|
|
|
|
<hibernate-mapping> |
|
|
||||||
|
|
Car object |
and 2 times for the Part objects). Since the |
|
|
<class name=”Part” table=”part”> |
|
|
||||
|
|
association is controlled by the Car object (i.e. one-to- |
|
|
…. |
|
|
|
||||
|
|
many side), inserting the part objects will not set the |
|
|
<many-to-one name=”car” column=”car_id” / > |
|
|
|||||
|
|
foreign key value (i.e. car_id) into the Part objects. There |
|
|
…. |
|
|
|
||||
|
|
will be two additional UPDATE SQL calls to add the Car |
|
|
</class> |
|
|
|
||||
|
|
object’s foreign key value into the Part records. So this is |
|
|
</hibernate-mapping> |
|
|
|||||
|
|
not only inefficient but also will cause errors during |
|
|
|
|
|
|
||||
|
|
INSERT SQL calls to Part objects if every part should |
|
|
|
|
|
|
||||
|
|
have a car (i.e. foreign-key column car_id in Part is a |
|
|
|
|
|
|
||||
|
|
not-null column). |
|
|
|
|
|
|
|
|
|
|
|
|
The solution to overcome the above issue is to set the |
|
|
|
|
|
|
||||
|
|
attribute inverse=”true” on the Car object (i.e. one-to- |
|
|
|
|
|
|
||||
|
|
many side) to indicate that the ownership of the |
|
|
|
|
|
|
||||
|
|
association should be given to the Part objects (i.e., |
|
|
|
|
|
|
||||
|
|
many-to-one side). Since the association belongs to the |
|
|
|
|
|
|
||||
|
|
Part objects there will never be an INSERT SQL call to |
|
|
|
|
|
|
||||
|
|
the Part record with a null car_id. |
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
||||
lazy |
|
This property is used to determine if all the associated |
|
|
|
|
|
|
||||
|
|
graph of objects should be “eagerly” fetched or “lazily” |
|
|
<hibernate-mapping> |
|
|
|||||
|
|
loaded |
when |
methods |
like |
session.get(…), |
|
|
<class name=”Car” table=”car”> |
|
|
|
|
|
session.load(…), session.find(…), etc are executed. The |
|
|
…. |
|
|
|
||||
|
|
lazy loading uses proxy objects. |
|
|
|
|
<set name=”parts” cascade=”all” lazy=”true”> |
|
|
|||
|
|
lazy= true (default on hibernate 3.0 onwards) means |
|
|
<key column=”part_id” /> |
|
|
|||||
|
|
|
|
<one-to-many class=”com.Part” /> |
|
|
||||||
|
|
load associated objects lazily. |
|
|
|
|
</set> |
|
|
|
||
|
|
lazy=false means load associated objects eagerly. |
|
|
…. |
|
|
|
||||
|
|
|
|
</class> |
|
|
|
|||||
|
|
It is the best practice to set the lazy attribute to true in |
|
|
</hibernate-mapping> |
|
|
|||||
|
|
|
|
|
|
|
|
|||||
|
|
the mapping file and make it a conscious choice to |
|
|
//session should be open to access a proxy object |
|
||||||
|
|
eagerly join in your HQL or eagerly fetch in your criteria |
|
|
|
|||||||
|
|
query for specific use cases. For e.g. |
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
Session session= sessionFactory.openSession(); |
|
|
|
|
|
String hqlQuery = “ FROM Car c OUTER JOIN FETCH |
|
|
Car car = session.load(Car.class, 12);// id =12 |
|
|
|||||
|
|
|
|
c.parts WHERE c.color=?”; |
|
|
Set parts = car.getParts(); |
|
|
|||
|
|
If you want to access a lazily initialized collection, you |
|
|
session.close(); |
//session is closed. |
|
|
||||
|
|
|
|
Part part1 = (Part)parts.get(0); //exception is thrown |
|
|
||||||
|
|
must make sure that the session is open, otherwise an |
|
|
|
//because the session is closed |
|
|
||||
|
|
exception will be thrown. |
|
|
|
|
|
|
|
|
||
|
|
You could also optimize your lazy loading strategy by |
|
|
|
|
|
|
||||
|
|
specifying the batch-size attribute as discussed next. |
|
|
|
|
|
|
||||
batch-size |
|
This is used as an optimization strategy for loading |
|
|
<hibernate-mapping> |
|
|
|||||
|
|
objects lazily. Hibernate can load several uninitialized |
|
|
<class name=”Car” table=”car”> |
|
|
|||||
|
|
proxy objects if one proxy object or collection is |
|
|
…. |
|
|
|
||||
|
|
accessed. |
|
|
|
|
|
|
<set name=”parts” batch-size=”20”> |
|
|
|
|
|
For example, say you have 50 Car objects loaded into a |
|
|
<key column=”part_id” /> |
|
|
|||||
|
|
|
|
<one-to-many class=”com.Part” /> |
|
|
||||||
|
|
session with a session.find(….) query operation. Say |
|
|
</set> |
|
|
|
||||
|
|
each car object has an association with a collection of 10 |
|
|
…. |
|
|
|
||||
|
|
Part objects. So if you iterate through all your Car |
|
|
</class> |
|
|
|
||||
|
|
objects, there will be 50 SQL |
SELECT calls to the |
|
|
</hibernate-mapping> |
|
|
||||
|
|
database for every invocation of car.getParts() method. |
|
|
|
|
|
|
||||
|
|
If you set your batch-size attribute to 20, then there will |
|
|
|
|
|
|
||||
|
|
be only 3 SQL SELECTs to the database. Hibernate will |
|
|
|
|
|
|
||||
|
|
load 20,20,10 collections in just 3 SELECT calls. |
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|||||
unsaved- |
|
unsaved-value attribute comes into play when you use |
|
|
<hibernate-mapping> |
|
|
|||||
value |
|
the saveOrUpdate(…) method. |
|
|
|
|
<class name=”Car” table=”car”> |
|
|
|||
|
|
|
|
|
|
|
|
|
<id name=”id” column=”car_id” type=”long” |
|
|
|
|
|
null is the default value. Other values supported are |
|
|
|
unsaved-value=”null”> |
|
|
||||
|
|
any, none, and id-value. |
|
|
|
|
<generator class=”native” /> |
|
|
|||
|
|
|
|
|
|
|
|
|
</id> |
|
|
|
|
|
If the unsaved-value is set to null or not set at all (default |
|
|
<set name=”parts” cascade=”all” lazy=”true”> |
|
|
|||||
|
|
value is null) and if the primary-key property value is null |
|
|
<key column=”part_id” /> |
|
|
|||||
|
|
then hibernate assumes that the object is transient and |
|
|
<one-to-many class=”com.Part” /> |
|
|