EJB3 and JPA Basics



EJB3 and JPA Basics

Mapped Superclasses
A mapped superclass provides a convenient class on which to store shared state and behavior that entities can inherit from, but it is itself not a persistent class and cannot act in the capacity of an entity. It cannot be queried over and cannot be the target of a relationship. Annotations such as @Table are not permitted on mapped superclasses because the state defined in them applies only to its entity subclasses.
It is good practice to make mapped superclass as abstract Java classes.mapped superclasses do not get mapped to tables.
Entity Inheritance
The Java Persistence specification provides three different ways to map an inheritance hierarchy to a relational database:
A single table per class hierarchy
One table will have all properties of every class in the hierarchy.
A table per concrete class
Each class will have a table dedicated to it, with all of its properties and the properties of its superclass mapped to this table.
A table per subclass
Each class will have its own table. Each table will have only the properties that are defined in that particular class. These tables will not have properties of any superclass or subclass.
The root entity class defines the inheritance strategy with the @Inheritance annotation. Inheritance has only one property: InheritanceType strategy InheritanceType is an enum, which has value: SINGLE_TABLE, TABLE_PER_CLASS, JOINED. The default one is SINGLE_TABLE
Single-Table Strategy(A single table per class hierarchy)
This strategy maps all classes in the hierarchy to one table, which contains a superset of all the possible state in any of the entity classes.
@Entity
@Table(name="Employee")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="Employee_Type")
public abstract class Employee
@Entity
@DiscriminatorValue("Contract_Employee")
public class ContractEmployee
Discriminator Column and Discriminator Value
The table has to have one extra column to indicate the type.
Advantages

It offers peak performance for both polymorphic queries and write operations. The SQL that is needed to issue these operations is simple, optimized, and does not require joining.
Single table inheritance mapping is the fastest of all inheritance models, since it never requires a join to retrieve a persistent instance from the database. Similarly, persisting or updating a persistent instance requires only a single INSERT or UPDATE statement. Finally, relations to any class within a single table inheritance hierarchy are just as efficient as relations to a base class.
Disadvantages
Single-table approach tends to be more wasteful of database tablespace, as for every field in the entire inheritance hierarchy, a column must exist in the mapped table, as many columns may be empty.
Joined Strategy(A table per subclass)
The InheritanceType.JOINED strategy uses a different table for each class in the hierarchy. Each table only includes state declared in its class.
@Entity
@Table(name="Employee")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="Employee_Type")
public abstract class Employee
PrimaryKeyJoinColumn annotations tell the JPA implementation how to join each subclass table record to the corresponding record in its direct superclass table.
Advantages
The joined strategy has the following advantages:
Using joined subclass tables results in the most normalized database schema, meaning the schema with the least spurious or redundant data.
As more subclasses are added to the data model over time, the only schema modification that needs to be made is the addition of corresponding subclass tables in the database (rather than having to change the structure of existing tables).
Relations to a base class using this strategy can be loaded through standard joins and can use standard foreign keys, as opposed to the machinations required to load polymorphic relations to table-per-class base types, described below.
Disadvantages
Aside from certain uses of the table-per-class strategy described below, the joined strategy is often the slowest of the inheritance models. Retrieving any subclass requires one or more database joins, and storing subclasses requires multiple INSERT or UPDATE statements.
Table-per-Concrete-Class Strategy(A table per concrete class)
Like the JOINED strategy, the InheritanceType.TABLE_PER_CLASS strategy uses a different table for each concrete class in the hierarchy. Unlike the JOINED strategy, however, each table includes all state for an instance of the corresponding class. Thus to load a subclass instance, the JPA implementation must only read from the subclass table; it does not need to join to superclass tables.
Advantages
The table-per-class strategy is very efficient when operating on instances of a single concrete class. As in this case, the strategy never requires joining to superclass or subclass tables. Reads, joins, inserts, updates, and deletes are all efficient in the absence of polymorphic behavior. Also, as in the joined strategy, adding additional classes to the hierarchy does not require modifying existing class tables.
Disadvantages
The negative side is that it makes polymorphic querying across a class hierarchy more expensive than the other strategies. The problem is that it must either issue multiple separate queries across each of the subclass tables, or query across all of them using a UNION operation. This is always expensive.
Fetch Type
FetchType.EAGER or FetchType.LAZY
Cascade Type
public enum CascadeType {ALL,PERSIST,MERGE,REMOVE,REFRESH,DETACH}
Directionality
Unidirectional or bidirectional
Entitys Relationships
Many-to-one, One-to-one, One-to-many, Many-to-many
Persistence Context
A persistent context manages a set of managed entity object instances.
The entity manager tracks all entity objects within a persistence context for changes and updates made, and flushes these changes to the database.
As soon as an EntityManager object is created, it is implicitly associated with a persistence context for managing a set of entities.
Persistent Context comes in two flavors, one is the transaction-scoped persistent context and the other one is extended persistent context.
Transaction-Scoped Persistence Context
Life-time of transaction-scoped persistence context is dependent on the life-time of the transaction.
When the transaction completes, the transaction-scoped persistence context will be destroyed and all man-aged entity object instances will become detached.
Only persistence contexts managed by an application server may be transaction-scoped.
Extended Persistence Context
@PersistenceContext(type=PersistenceContextType.EXTENDED)
private EntityManager em;
Extended persistence context lives even after a transaction completes.
Entity object instances that are attached to an extended context remain managed even after a transaction is complete.
An EntityManager using an extended persistence context maintains the same persistence context for its entire lifecycle.
It is often used in stateful session beans.
Detached entities
Entity instances become unmanaged and detached when a transaction scope or extended persistence context ends. An interesting side effect is that detached entities can be serialized and sent across the network to a remote client. The client can make changes remotely to these serialized object instances and send them back to the server to be merged back and synchronized with the database.
merge()
The Java Persistence specification allows you to merge state changes made to a detached entity back into persistence storage using the entity manager’s merge() method.
If the entity manager isn’t already managing an instance, a full copy of the parameter is made and returned from the merge() method. This copy is managed by the entity manager, but the instance you pass in will not be managed.
Any additional setter methods called on this copy will be synchronized with the database when the EntityManager decides to flush.
The original parameter remains detached and unmanaged.
Either way will add an entity to a PersistenceContext, the difference is in what you do with the entity afterwards.
Persist takes an entity instance, adds it to the context and makes that instance managed (ie future updates to the entity will be tracked)
Merge creates a new instance of your entity, copies the state from the supplied entity, and makes the new copy managed. The instance you pass in will not be managed (any changes you make will not be part of the transaction - unless you call merge again).
The Stateful Session Bean
Stateful session beans maintain conversational state,
The Singleton Session Bean
@javax.ejb.Singleton
@javax.ejb.Startup
public class MySingletonBean implements MySingletonLocalBusiness{..}
Container Managed Transactions (CMT)
In a CMT the container starts, commits and rolls back a transaction on our behalf, we however must tell the container how to manage the transaction by using either deployment descriptors or annotations and ask it to rollback the transaction when needed.
@TransactionManagement(TransactionManagementType.CONTAINER|BEAN)
@TransactionAttribute
TransactionAttributes
REQUIRED  means the method must always be invoked in a transaction, either creating a new one or joining an existing one, this creates a single umbrella transaction.
REQUIRES_NEW    means that the method will always create a new transaction, if the client already has a transaction; it is temporary suspended until our method returns. The success of the newly created transaction has no affect on an existing transaction.
SUPPORTS  will inherit whatever transactional environment of the caller is, if it does not have one then no transaction is used, if it joins an already existing transaction it will not cause it to suspend
MANDATORY    means that a transaction must already exist if one does not then an EJBTransactionRequiredException error is thrown.
NOT_SUPPORTED   means that the method will not run in an transaction, if one already exists then this is suspended until the method completes then resumes. this is useful for an MDB supporting a JMS provider in a non-transactional, autoknowledge mode.
NEVER means that it cannot be invoked by a transactional client, otherwise a EJBException is thrown.
Transaction Attribute   
Type               Caller Transaction Exists    Effect
REQUIRED          No    Container creates a new transaction
                     Yes   Method joins the callers transaction
REQUIRES_NEW    No    Container creates a new transaction
                     Yes   Container creates a new transaction and the callers transaction is suspended
SUPPORTS          No    No transaction is used
                     Yes    Method joins the callers transaction
MANDATORY        No   javax.ejb.EJBTransactionRequiredException is thrown
                     Yes  Method joins the callers transaction
NOT_SUPPORTED   No   No transaction is used
                     Yes  The callers transaction is suspended and the method is called without a transaction
NEVER             No   No transaction is used
                     Yes   javax.ejb.EJBException is thrown
Bean-Managed Transactions
BMT allows you to specify exactly where the transaction starts, ends, commits and rolls back, using the javax.transaction.UserTransaction interface.
@TransactionManagement(TransactionManagementType.BEAN)
@Resource private UserTransaction userTransaction;
userTransaction.begin;
userTransaction.commit();
userTransaction.setRollbackOnly();
@ApplicationException(rollback=false|true)[TODO]
Applied to an exception to denote that it is an application exception and should be reported to the client directly (i.e., unwrapped).
@ApplicationException(rollback=false)
public class DatabaseException extends RuntimeException
Isolation and Database Locking
Dirty, Repeatable, and Phantom Reads
Dirty reads
A dirty read occurs when a transaction reads uncommitted changes made by a previous transaction. If the first transaction is rolled back, the data read by the second transaction becomes invalid because the rollback undoes the changes. The second transaction will not be aware that the data it has read has become invalid.
Repeatable reads
A repeatable read occurs when the data read is guaranteed to look the same if read again during the same transaction. Repeatable reads are guaranteed in one of two ways: either the data read is locked against changes, or it is a snapshot that doesn’t reflect changes.
If the data is locked, it cannot be changed by any other transaction until the current transaction ends. If the data is a snapshot, other transactions can change the data, but these changes will not be seen by this transaction if the read is repeated.
A nonrepeatable read occurs when the data retrieved in a subsequent read within the same transaction can return different results.
When a transaction queries for the same data twice in the same transaction, the second query returns a different version of the data than was returned the first time because another transaction modified it in the intervening time.
In other words, the subsequent read can see the changes made by other transactions.
Phantom reads
A phantom read occurs when new records added to the database are detectable by transactions that started prior to the insert. Queries will include records added by other transactions after their transaction has started.
Database Locks
The most common locks are read locks, write locks, and exclusive write locks.
Read locks
Read locks prevent other transactions from changing data read during a transaction until the transaction ends, thus preventing non-repeatable reads. Other transactions can read the data but not write to it. The current transaction is also prohibited from making changes.
Write locks
Write locks are used for updates. A write lock prevents other transactions from changing the data until the current transaction is complete but allows dirty reads by other transactions and by the current transaction itself. In other words, the transaction can read its own uncommitted changes.
Exclusive write locks
Exclusive write locks are used for updates. An exclusive write lock prevents other transactions from reading or changing the data until the current transaction is complete. It also prevents dirty reads by other transactions. Some databases do not allow transactions to read their own data while it is exclusively locked.
Snapshots
A snapshot is a frozen view of the data that is taken when a transaction begins.
Some databases get around locking by providing every transaction with its own snapshot. Snapshots can prevent dirty reads, nonrepeatable reads, and phantom reads. They can be problematic because the data is not real-time data; it is old the instant the snapshot is taken.
Transaction Isolation Levels
Read Uncommitted
The transaction can read uncommitted data (i.e., data changed by a different transaction that is still in progress). Dirty reads, nonrepeatable reads, and phantom reads can occur
Read Committed
The transaction cannot read uncommitted data; data that is being changed by a different transaction cannot be read. Dirty reads are prevented; nonrepeatable reads and phantom reads can occur.
Repeatable Read
The transaction cannot change data that is being read by a different transaction.
Dirty reads and non-repeatable reads are prevented; phantom reads can occur.
Serializable
The transaction has exclusive read and update privileges; different transactions can neither read nor write to the same data. Dirty reads, nonrepeatable reads, and phantom reads are prevented.
Optimistic Locking
Using optimistic locking, we assume there is a good chance that current transaction will be the only one that actually changes the entity during that interval.
So we don't acquire a lock on the entity until the change is actually made to the database, usually at the end of the transaction.
At transaction commit time, we let the database resolve whether the data has been altered by another transaction. If it has, we throw an exception and roll back our transaction. In other words, we are being optimistic that the data hasn’t been touched until we need to commit.
Versioning
To determine whether others have changed same data in the intervening time since the committing transaction read the entity, the provider maintains a versioning system for the entity, defines a version column to track the version of a row.
@Version private Long version;
A @Version property is a column that will hold a version ID of a particular row.
Whenever the entity class is updated, the version column is incremented automatically by JPA. When a transaction beginning the commit process and business logic has updated the entity, the entity manager first checks to see whether the version property of the in-memory entity instance matches the version column currently stored in the database. If the versions match, then the version property is incremented. If they don’t match, then the entity manager throws an exception(OptimisticLockException) and rolls back the whole transaction.
Advanced Optimistic Locking Modes
Optimistic Read Locking(LockModeType.OPTIMISTIC)
An optimistic read lock in JPA provides Repeatable Read.
The resulting lock will guarantee that both the transaction that obtains the entity read lock and any other that tries to change that entity instance will not both succeed.
Optimistic Write Locking(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
The write lock guarantees all that the optimistic read lock does, but also pledges to increment the version field in the transaction regardless of whether a user updated the entity or not. This provides a promise of an optimistic lock failure if another transaction also tries to modify the same entity before this one commits.
When not use optimistic lock?
The optimistic locking design pattern does not work all the time.
If you have a row in your database that has a high concurrent write contention, then it is probably less efficient to use the optimistic locking pattern because it will create a lot of rollbacks, which create a lot of overhead in your system.
Pessimistic Locking
Pessimistic locking implies obtaining a lock on one or more objects immediately.
It guarantees locked object will not be modified by another transaction until after the current transaction completes and releases its lock.
Disadvantages
This limits the scalability and concurrency of applications because needless locking serializes many operations that could easily occur in parallel.
Pessimistic Locking Modes
By far the most common is pessimistic write locking.
Pessimistic Write Locking(LockModeType.PESSIMISTIC_WRITE)
This mode will be translated by most providers into a SQL "SELECT FOR UPDATE" statement in the database, obtaining a write lock on the entity so no other applications can modify it.
Pessimistic Read Locking(LockModeType.PESSIMISTIC_READ)
A PESSIMISTIC_READ mode can be used to pessimistically achieve repeatable read semantics when no writes to the entity are expected.
Pessimistic Forced Increment Locking
(LockModeType.PESSIMISTIC_FORCE_INCREMENT)
This mode will also increment the version field of the locked entity regardless of whether changes were made to it.

@Basic
The @Basic annotation is the simplest form of mapping for a persistent property. This is the default mapping type for properties that are primitives, primitive wrapper types.
Lazy Loading
We declare fetch attribute to lazy on mapping relationship, such as @Basic, @OneToMany, @ManyToOne, @OneToOne, and @ManyToMany.
If the fetch() attribute is LAZY, that particular property will not be initialized
until you actually access this field.
Open Session in View
The problem
If your view (jsp) need access object's property that is lazy loaded, you will get exception:
LazyInitializationException: Session has been closed.
This is because the session has already been closed.
Using an interceptor|Filter to implement
sf.getCurrentSession().beginTransaction();
chain.doFilter(request, response);
sf.getCurrentSession().getTransaction().commit();
Solution for Hibernate
Spring provides OpenSessionInViewFilter.
Solution for JPA
In JPA, we can use extended entityManager(extended persistence context), or Spring's OpenEntityManagerInviewFilter.

Resources

SQL Code Example


SQL Code Example

CRUD statement

INSERT INTO person (person_id, fname, lname, gender, birth_date)

VALUES (null, 'William','Turner', 'M', '1972-05-27');

UPDATE person SET street = '1225 Tremont St.',

city = 'Boston', state = 'MA', country = 'USA', postal_code = '02138'

WHERE person_id = 1;

DELETE FROM person WHERE person_id = 2;

DROP TABLE favorite_food;

The group by and having Clauses[key point]

Count all the employees in each department and returns the names of those departments having more than two employees:

SELECT d.name, count(e.emp_id) num_employees

FROM department d INNER JOIN employee e

ON d.dept_id = e.dept_id

GROUP BY d.name

HAVING count(e.emp_id) > 2;

The order by Clause

Ascending Versus Descending Sort Order[Asc, Desc]

Filtering


Using Parentheses

Using the not Operator

Condition Types: =, <>, <, >

DELETE FROM account WHERE status = 'CLOSED' AND YEAR(close_date) = 2002;

The between operator(Number, String, Date)

Membership Conditions(in, not in)

Using wildcards(LIKE)

_ Exactly one character

% Any number of characters (including 0)

Using regular expressions

SELECT emp_id, fname, lname FROM employee WHERE lname REGEXP '^[FG]';

Null(IS [not] NULL)

Querying Multiple Tables[Join]

Self-Joins

List every employee’s name along with the name of his or her manager:

SELECT e.fname, e.lname, e_mgr.fname mgr_fname, e_mgr.lname mgr_lname

FROM employee e INNER JOIN employee e_mgr ON e.superior_emp_id = e_mgr.emp_id;

Using the Same Table Twice

SELECT a.account_id, e.emp_id, b_a.name open_branch, b_e.name emp_branch

FROM account a INNER JOIN branch b_a ON a.open_branch_id = b_a.branch_id

INNER JOIN employee e ON a.open_emp_id = e.emp_id

INNER JOIN branch b_e ON e.assigned_branch_id = b_e.branch_id

WHERE a.product_cd = 'CHK';

Using Subqueries As Tables

Non-Equi-Joins

List all possible chess matches:

SELECT e1.fname, e1.lname, 'VS' vs, e2.fname, e2.lname

FROM employee e1 INNER JOIN employee e2 ON e1.emp_id < e2.emp_id

WHERE e1.title = 'Teller' AND e2.title = 'Teller';

Grouping and Aggregates[key point]

SELECT open_emp_id, COUNT(*) how_many FROM account

GROUP BY open_emp_id HAVING COUNT(*) > 4;

Aggregate Functions

Max(), Min(),Avg(), Sum(), Count()

SELECT product_cd, MAX(avail_balance) max_balance,

MIN(avail_balance) min_balance, AVG(avail_balance) avg_balance,

SUM(avail_balance) tot_balance, COUNT(*) num_accts

FROM account GROUP BY product_cd;

Counting Distinct Values

SELECT COUNT(DISTINCT open_emp_id) FROM account;

SELECT product_cd, open_branch_id, SUM(avail_balance) tot_balance

FROM account GROUP BY product_cd, open_branch_id;

Grouping via Expressions

SELECT EXTRACT(YEAR FROM start_date) year, COUNT(*) how_many

FROM employee GROUP BY EXTRACT(YEAR FROM start_date);

Group Filter Conditions[having]

Subqueries

SELECT account_id, product_cd, cust_id, avail_balance

FROM account WHERE account_id = (SELECT MAX(account_id) FROM account);

Subquery Types

Noncorrelated Subqueries

Single-Row, Single-Column Subqueries

This type of subquery is known as a scalar subquery and can appear on either side of a condition using the usual operators (=, <>, <,>, <=, >=).

Multiple-Row, Single-Column Subqueries[in and not in, all, any]

List which employees supervise other employees:

SELECT emp_id, fname, lname, title FROM employee

WHERE emp_id IN (SELECT superior_emp_id FROM employee);

SELECT emp_id, fname, lname, title FROM employee

WHERE emp_id NOT IN (SELECT superior_emp_id

FROM employee WHERE superior_emp_id IS NOT NULL);

Find all employees whose employee IDs are not equal to any of the supervisor employee IDs:

SELECT emp_id, fname, lname, title FROM employee

WHERE emp_id <> ALL (SELECT superior_emp_id

FROM employee WHERE superior_emp_id IS NOT NULL);

Multicolumn Subqueries

Find all accounts whose balances don’t match the sum of the transaction amounts for that account.

Correlated Subqueries

List customers having exactly two accounts

SELECT c.cust_id, c.cust_type_cd, c.city FROM customer c

WHERE 2 = (SELECT COUNT(*) FROM account a WHERE a.cust_id = c.cust_id);

The exists Operator

Find all the accounts for which a transaction was posted on a particular day

SELECT a.account_id, a.product_cd, a.cust_id, a.avail_balance FROM account a

WHERE EXISTS (SELECT 1 FROM transaction t WHERE t.account_id = a.account_id AND t.txn_date = '2008-09-22');

UPDATE account a SET a.last_activity_date =

(SELECT MAX(t.txn_date) FROM transaction t WHERE t.account_id = a.account_id);

WHERE EXISTS (SELECT 1 FROM transaction t WHERE t.account_id = a.account_id);

Remove data from the department table that has no child rows in the employee table:

DELETE FROM department WHERE NOT EXISTS

(SELECT 1 FROM employee WHERE employee.dept_id = department.dept_id);

Subqueries in Filter Conditions

Find the employee responsible for opening the most accounts:

SELECT open_emp_id, COUNT(*) how_many FROM account GROUP BY open_emp_id

HAVING COUNT(*) = (SELECT MAX(emp_cnt.how_many) FROM (SELECT COUNT(*) how_many

FROM account GROUP BY open_emp_id) emp_cnt);

Working with Sets

Set Operators[union, union all, intersect, except, ]

union all operator doesn’t remove duplicates.

SELECT 'IND' type_cd, cust_id, lname name FROM individual

UNION ALL

SELECT 'BUS' type_cd, cust_id, name FROM business;

Conditional Logic

CASE

WHEN C1 THEN E1

WHEN CN THEN EN

[ELSE ED]

END

CASE V0

WHEN V1 THEN E1

WHEN VN THEN EN

[ELSE ED]

END

SELECT

SUM(CASE WHEN EXTRACT(YEAR FROM open_date) = 2010 THEN 1 ELSE 0 END) year_2010,

SUM(CASE WHEN EXTRACT(YEAR FROM open_date) = 2011 THEN 1 ELSE 0 END) year_2011,

FROM account WHERE open_date > '1999-12-31' AND open_date < '2006-01-01';

Find accounts whose account balances don’t agree with the raw data in the transaction table.

SELECT CONCAT('ALERT! : Account #', a.account_id,

' Has Incorrect Balance!')

FROM account a

WHERE (a.avail_balance, a.pending_balance) <>

(SELECT

SUM(CASE

WHEN t.funds_avail_date > CURRENT_TIMESTAMP() THEN 0

WHEN t.txn_type_cd = 'DBT' THEN t.amount * −1

ELSE t.amount

END),

SUM(CASE WHEN t.txn_type_cd = 'DBT' THEN t.amount * −1 ELSE t.amount END)

FROM transaction t

WHERE t.account_id = a.account_id);

Show whether the customer has any checking accounts and whether the customer has any savings accounts:

SELECT c.cust_id, c.fed_id, c.cust_type_cd,

CASE

WHEN EXISTS (SELECT 1 FROM account a

WHERE a.cust_id = c.cust_id

AND a.product_cd = 'CHK') THEN 'Y'

ELSE 'N'

END has_checking,

CASE

WHEN EXISTS (SELECT 1 FROM account a

WHERE a.cust_id = c.cust_id

AND a.product_cd = 'SAV') THEN 'Y'

ELSE 'N'

END has_savings

FROM customer c;

Count the number of accounts for each customer, and then returns either 'None', '1', '2', or '3+':

SELECT c.cust_id, c.fed_id, c.cust_type_cd,

CASE (SELECT COUNT(*) FROM account a

WHERE a.cust_id = c.cust_id)

WHEN 0 THEN 'None'

WHEN 1 THEN '1'

WHEN 2 THEN '2'

ELSE '3+'

END num_accounts

FROM customer c;

Division-by-Zero Errors

SELECT a.cust_id, a.product_cd, a.avail_balance /

CASE

WHEN prod_tots.tot_balance = 0 THEN 1

ELSE prod_tots.tot_balance

END percent_of_total

FROM account a INNER JOIN

(SELECT a.product_cd, SUM(a.avail_balance) tot_balance

FROM account a

GROUP BY a.product_cd) prod_tots

ON a.product_cd = prod_tots.product_cd;

Transactions

Lock Granularities:Table locks, Page locks, Row locks

SHOW TABLE STATUS LIKE 'transaction' \G

START TRANSACTION;

UPDATE product

SET date_retired = CURRENT_TIMESTAMP() WHERE product_cd = 'XYZ';

SAVEPOINT before_close_accounts;

UPDATE account

SET status = 'CLOSED', close_date = CURRENT_TIMESTAMP(),

last_activity_date = CURRENT_TIMESTAMP()

WHERE product_cd = 'XYZ';

ROLLBACK TO SAVEPOINT before_close_accounts;

COMMIT;

Resource

Learning SQL

GWT Basics


GWT Basics

GWT Advantages

1. You're write client side code in Java instead of javascript.

- We can use the reliable, strongly-typed language for development

- Reuse your skills of Java, no need skills in javascript and CSS.

2. We can use complex Java on the client

- We can use java class such as String, array, Math class, ArrayList, HashMap, custom classes, etc.

3. We can send complex Java types to and from the server.

4. GWT provides a number of widget.

-- Such as DatePicker, Tree, SuggestBox, RichTextArea, Grid, TabBar and etc.

5. Full IDE-based Java support for development/debugging.

-- Client side is java code, so we can use all Java IDE development/debugging features, Google also provides GWT designer, we can drag and drop control and widget to desgin the web UI.

6. Debugging

- We can debug client side code just like any other Java application, using our IDE's debugger. This approach is much better than JavaScript debugger.

Testabilty

- We can use java to write code to test client side code just like other java code.

GWT Disadvantages


1. Big learning curve, especailly for non-java developer.

2. Cumbersome deployment.

-- We have to translate client java code to javascript, then deploy to server.

Unusual approach

-- Fundamentally different strategy than all other Ajax environments makes evaluation and management buyoff harder.

Approaches to Communicate with the server

Making Remote Procedure Calls (GWT RPC)

If serve side can be implemented using java, we can use GWT RPC. Using it we can pass Java objects to and from a server and transparently make calls to Java servlets and let GWT take care of low-level details like object serialization.

Retrieving JSON Data via HTTP

RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);

try {

Request request = builder.sendRequest(null, new RequestCallback() {

public void onError(Request request, Throwable exception) {displayError("Couldn't retrieve JSON");}

public void onResponseReceived(Request request, Response response) {

if (200 == response.getStatusCode()) {

updateTable(asArrayOfStockData(response.getText()));

} else {

displayError("Couldn't retrieve JSON (" + response.getStatusText()

+ ")");

}

}

});

} catch (RequestException e) {displayError("Couldn't retrieve JSON");}

Making Cross-Site Requests for JSONP

Writing Asynchronous Callbacks

All the calls you make from the HTML page to the server are asychronous, in client side, we need to implemente a function that would be called when request succeeds or fails(Using AsyncCallback).

@RemoteServiceRelativePath("greet")

public interface GreetingService extends RemoteService {

String greetServer(String name) throws IllegalArgumentException;

}

public interface GreetingServiceAsync {

void greetServer(String input, AsyncCallback callback)

throws IllegalArgumentException;

}

private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);

greetingService.greetServer(textToServer, new AsyncCallback() {

public void onFailure(Throwable caught) {

// Show the RPC error message to the user

dialogBox.setText("Remote Procedure Call - Failure");

serverResponseLabel.addStyleName("serverResponseLabelError");

serverResponseLabel.setHTML(SERVER_ERROR);

dialogBox.center();

closeButton.setFocus(true);

}

public void onSuccess(String result) {

dialogBox.setText("Remote Procedure Call");

serverResponseLabel.removeStyleName("serverResponseLabelError");

serverResponseLabel.setHTML(result);

dialogBox.center();

closeButton.setFocus(true);

}

});

}

public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {..} // at server side

Manage Events on the Client

GWT is event-based. Code executes in response to some event occurring.

This is just like Swing, we write handler to handle event.

HTML logout_link = new HTML("Sign Out");

logout_link.addClickListener(new ClickListener() {

public void onClick(Widget sender) {

if (Window.confirm("Do you really want to leave ?")) {

login_user = "";Window.Location.reload();

}

}

});

logout_link.addStyleName("hover-cursor");

Declarative Layout in XML with GWT UiBinder

API

GWT.log("")

Basic steps

Create application

webAppCreator -out MyWebApp -junit "C:\Documents and Settings\Administrator\.m2\repository\junit\junit\4.8.2\junit-4.8.2.jar" com.mycompany.mywebapp.MyWebApp

Run locally in development mode

ant devmode

Compile and run in production mode

ant build

ant war

Running unit tests

ant test.dev|test.prod|test

Code Example

Creating custom widgets

public class ImageButton extends Composite{

private HorizontalPanel hPanel;

private Image button_img;

private HTML button_text;

public ImageButton(String text, Image image) {

}

}

DateTimeSelection to set data and time.

Creating Composite

CreateAccount, ChangePasswd, Login

How to access image

public interface ImagePack extends ImageBundle, DisclosurePanelImages {

AbstractImagePrototype Logo();

AbstractImagePrototype delete();

}

public class ImageAccessor {

private static final ImagePack images = (ImagePack) GWT.create(ImagePack.class);

public static ImagePack getImages() {return images;}

}

titlePanel.add(ImageAccessor.getImages().Logo().createImage());

Resources:

http://code.google.com/webtoolkit

Google Web Toolkit: The new frontier of Rich Internet Applications

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)