I have an application calling a remote method on a stateless session bean. This mehtod performs a whole heap of JPA transactions and thus can take quite some time to execute. The exact time is dependent on parameters passed in but mostly the call times out before the method can complete execution.
Something strange I noticed was that the JBoss TM doesn't actually stop the remote method, which continues execution (usually until completion) but only times out and aborts the method call. I would have thought the manager would want to interrupt any active thread that is running within a transaction that has timed out. But it seems you can control the two timeouts separately.
To control the EJB method timeout set the transaction timeout to a higher value. This can be done on a per method basis by annotating the method with
@org.jboss.annotation.ejb.TransactionTimeout(600) // eg: a 10 minute timeout.
Or to apply the timeout setting to the entire bean:
@ActivationConfigProperty(propertyName="transactionTimeout", propertyValue="600")
For bean managed transactions you can set the timeput pn the UserTransaction as follows:
UserTransaction ut = (UserTransaction)ctx.lookup ("java:someApp/someBean/SomeTransaction");
ut.setTransactionTimeout(600);
ut.begin();
...
ut.commit();
To set the read timeout for remote method invocations in JBoss (6), update the following line in <JBoss home>/server/default/deploy/ejb3-connectors-jboss-beans.xml with:
</parameter>
<parameter>socket://${hostforurl}:${port}?timeout=600000</parameter>
<parameter>
Wednesday, June 15, 2011
Monday, June 6, 2011
JPA-style positional param was not an integral ordinal
My JPA named native query: @NamedNativeQuery( name = "getFailure", query = "SELECT * " + "FROM INTERFACE_FAILURES " + "WHERE server_id = ?1" + "AND interface_name = ?2" + "AND date_time = TO_DATE(?3, 'dd/MM/yyyy hh:mi:ss PM') ", resultClass = InterfaceFailure.class ) called as follows: Query query = entityManager.createNamedQuery("getFailure") .setParameter(1, serverId) .setParameter(2, interfaceId) .setParameter(3, dateTime); if(query.getResultList().size() > 0) { failure = (InterfaceFailure)query.getSingleResult(); } results in the following: 15:54:33,438 ERROR [org.hibernate.impl.SessionFactoryImpl] Error in named query: getFailure: org.hibernate.QueryException: JPA-style positional param was not an integral ordinal at org.hibernate.engine.query.ParameterParser.parse(ParameterParser.java:111) [:3.6.0.Final] at org.hibernate.loader.custom.sql.SQLQueryParser.substituteParams(SQLQueryParser.java:290) [:3.6.0.Final] ... The solution, which google did not help with at all, hence my post: @NamedNativeQuery( name = "getFailure", query = "SELECT * " + "FROM INTERFACE_FAILURES " + "WHERE server_id = (?1)" + "AND interface_name = (?2)" + "AND date_time = TO_DATE(?3, 'dd/MM/yyyy hh:mi:ss PM') ", resultClass = InterfaceFailure.class ) Add brackets around the integral positional parameters.
Issues with JPA Queries with Date constraints
Lately I have been trying to update an Oracle table with a primary key made up of a start date and end date using JPA merge. The merge step was throwing ConstraintViolationExceptions saying that the primary key already existed, which was strange because as far as I thought merge was only supposed to try and insert rows if an existing match didn't exist, in which case we should not ever see constraint violations of this sort. Due to my still sketchy understanding of JPA I figured creating a new entity object could somehow be causing an automatic database synchronisation step, which results in the Constraint violation exception. I decided to try searching for the existing record before creating it if the search result came back with null. I added the following query: @NamedNativeQuery( name = "getUserLogEntry", query = "SELECT * " + "FROM USER_LOG_ENTRY " + "WHERE start_date_time = ?1 " + "AND end_date_time = ?2 ", resultClass = UserLogEntry.class ) Which is called passing in Date objects as parameters: Query query = entityManager.createNamedQuery("getUserLogEntry") .setParameter(1, startDate, TemporalType.DATETIME) .setParameter(2, endDate, TemporalType.DATETIME); if(query.getResultList().size() > 0) { entry = (UserLogEntry)query.getSingleResult(); } This however, was not finding any entry in the database, even though there definitely was such an entry there! After much wasted time I did find a way aroung this (although not a full understanding of why the previous attempts were not working). It seems passing java Date objects to the SQL query somehow scrambles somewhere in the Date translation, resulting in no matches. Therefore I casted my java dates to Strings and then used SQL's TO_DATE to format the dates exactly as I wanted: @NamedNativeQuery( name = "getUserLogEntry", query = "SELECT * " + "FROM HC_DYN_USER_LOG_ENTRY " + "WHERE start_date_time = TO_DATE(?1, 'dd/MM/yyyy hh:mi:ss PM') " + "AND end_date_time = TO_DATE(?2, 'dd/MM/yyyy hh:mi:ss PM') ", resultClass = UserLogEntry.class ) private static SimpleDateFormat reportDateFormat = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss a"); ... String startDateStr = reportDateFormat.format(startDateTime); String endDateStr = reportDateFormat.format(endDateTime); Query query = entityManager.createNamedQuery("getUserLogEntry") .setParameter(1, startDateStr) .setParameter(2, endDateStr); if(query.getResultList().size() > 0) { entry = (UserLogEntry)query.getSingleResult(); }
JPA Queries
Recently started having to use JPA (at the whim of some senior) without having had any proper training on it. As expected I have run into a myraid of issues, one of them being referring to attributes of an embedded primary key class (ie: an entity generated from a table named <tableName>PK). Trying to refer to attributes of the embedded class using standard JPQL would result in errors such as “No data type for node org.hibernate.hql.ast.tree.AggregateNode”. My temporary solution is to use named native queries instead, allowing me to write straight SQL. For example, in the entity class itself, you would have something like:@Entity @Table(name="LOG_ENTRY") @NamedNativeQueries ({ @NamedNativeQuery( name = "getLatestLogEntryDate", query = "SELECT * " + "FROM LOG_ENTRY e " + "WHERE e.start_date_time = (SELECT MAX(start_date_time) FROM LOG_ENTRY) ", resultClass = LogEntry.class ) })public class LogEntry implements Serializable { private static final long serialVersionUID = 1L; @EmbeddedId private LogEntryPK id; @Column(name="AVG_TIME") private BigDecimal avgTime; ... }@Embeddable public class LogEntryPK implements Serializable { //default serial version id, required for serializable classes. private static final long serialVersionUID = 1L; @Column(name="SERVER_ID") private String serverId; @Temporal( TemporalType.TIMESTAMP) @Column(name="START_DATE_TIME") private java.util.Date startDateTime; @Temporal( TemporalType.TIMESTAMP) @Column(name="END_DATE_TIME") private java.util.Date endDateTime; ... }This allows reference to startDateTime within the ServiceLogEntryPK class. Another issue was developing queries that needed to return composite data, which is not itself an entity. For example, returning server_id, start_date_time, and the average of avg_time, grouped by month. This can be done by adding a named native query to the LogEntry class as follows:@NamedNativeQueries ({ @NamedNativeQuery( name = "getLogEntriesAggregateMonthly", query = "SELECT 'All Servers' as server_id, TO_CHAR(start_date_time, 'YYYY-MM') DATE_FIELD, AVG(e.AVG_TIME) as AVG_TIME " + "FROM LOG_ENTRY e " + "WHERE start_date_time >= TO_DATE(?1, 'yy.MM.dd') " + "AND end_date_time <= TO_DATE(?2, 'yy.MM.dd') " + "AND server_id like (?3) " + "GROUP BY TO_CHAR(start_date_time, 'YYYY-MM')", resultSetMapping = "LogSummary" ) }) @SqlResultSetMappings({ @SqlResultSetMapping(name="LogSummary") })The SqlResultSetMapping name is just a String token, and can be pretty much any randomly chosen string. (Don't ask me what the purpose of this is) A good discussion on the weaknesses of JPA queroes can be found here: http://heapspace.blogspot.com/2009/03/jpa-strengths-and-weaknesses.html
Sunday, March 20, 2011
Viewing tables in Hypersonic
To view tables in the Hypersonic database that comes with JBoss, ensure JBoss is started and go to the JMX Management Console at http://localhost:<port>/jmx-console. <port> is usually 8080. In the Management Console under the JBoss heading click on the link called service=Hypersonic to go to the MBean view. Here you will see a list of MBean operations. Click on the invoke button for startDatabaseManager() to start up the HSQL Database manager. You should then see your database table in the tree to the left and an area where you can execute SQL statements.
Friday, February 11, 2011
Overview of popular software design patterns
Singleton
Ensure that only one instance of a class is created. To implement this, make the constructor protected (unit tests may need to access it), have a private static member which is an instance of itself, and have a get method that instantiates the class only if one does not already exist.
Use of singletons can be abused. They are a little like global variables. Systems relying on global state hide their dependencies. Some arguments against using it:
- It promotes tight coupling between classes
- It violates the single responsibility principle - a class should not case whether it is a singleton.
They can be fairly safely used when they don't contain any mutable state. An example of an appropriate use of a singleton may be a global resource manager.
Factory
Creates objects without exposing the instantiation logic to the client and refers to the newly created object through a common interface. A simple implementation would be to have an interface and some implementing classes. The factory will return an instance of the superclass. Which subclass it is will depend on parameters passed in to the creation/get method.
Factory Method
Defines an interface for creating objects, but lets subclasses decide which class to instantiate and refers to the newly created object through a common interface.
MVC
Separates the model, view, and controller, or presentation, logic, and data.
DAO
Abstracts and encapsulates all access to the data source. The DAO manages the connection with the data source to obtain and store data.
Facade
Provides a unified, convenient interface to a set of existing interfaces, potentially hiding some components/interfaces. It provides flexibility to change/replace "hidden" subsystems including interfaces.
Prototype
Specifies the kinds of objects to create using a prototypical instance, and creates new objects by copying this prototype.
Strategy
Defines a family of algorithms, encapsulating each one and making them interchangeable. The strategy pattern lets the algorithm vary independently from clients that use it.
Observer
Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
Command
Encapsulates a request in an object allowing the parameterisation of clients with different requests and allows saving the requests in a queue.
Visitor
Represents an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
Decorator
Adds additional responsibilities dynamically to an object.
Flyweight
Uses sharing to support a large number of objects that have part of their internal state in common where the other part of their state can vary.
Proxy
Provides a placeholder for an object to control references to it.
Bridge
Increases flexibility by letting abstraction and implementation evolve independently. This is achieved by having separate layers for abstraction and implementation, with a fixed implementation interface.
Visitor
Represents an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
Decorator
Adds additional responsibilities dynamically to an object.
Flyweight
Uses sharing to support a large number of objects that have part of their internal state in common where the other part of their state can vary.
Proxy
Provides a placeholder for an object to control references to it.
Bridge
Increases flexibility by letting abstraction and implementation evolve independently. This is achieved by having separate layers for abstraction and implementation, with a fixed implementation interface.
Thursday, February 10, 2011
J2EE Overview
Yes, there are so many other sites out there that provide J2EE Overviews but this is probably the most breif but yet complete one you'll find.
J2EE defines standards for developing multitier enterprise applications. It simplifies enterprise applications by basing them on standardised, modular components, and providing a set of services to those components. It handles many details of application behaviour automatically, without requiring complex programming.
J2EE defines standards for developing multitier enterprise applications. It simplifies enterprise applications by basing them on standardised, modular components, and providing a set of services to those components. It handles many details of application behaviour automatically, without requiring complex programming.
Enterprise JavaBeans
EJB is a standard distributed object framework and component model. It defines several types of components: session beans, entity beans, message driven beans, which simplify application development by concealing application complexity and enabling the component designer to focus on business logic.
Servlets and JSPs
Servlets and Java Server Pages are complementary APIs, both providing a means for generating dynamic web content. Servlets are Java programs implementing the javax.servlet.Servlet interface and running in a Web/App server's servlet engine. JSPs contain a mixture of HTML and java scripts, JSP elements, and directives, and are compiled into Servlets by the JSP engine.
JDBC
JDBC is a set of interfaces allowing Java applications to access any database.
RMI
RMI is an API which allows Java objects to communicate remotely with other objects. Its equivalent from OMG is CORBA.
IDL
IDL is a standard platform-independent language used to define interfaces that object implemnetation provide and client objects call. It allows java objects to communicate with other objects in any language.
JMS
JMS API is a messaging standard that allows J2EE components to create, send, receive, and read messages. It enables distributed communication between components. The addition of the JMS API enhances the J2EE platform by simplifying enterprise development, allowing loosely coupled, reliable, asynchronous interactions among J2EE components and legacy systems capable of messaging.
JTA
JTA allows J2EE components to perform distributed transactions.
JavaMail
JavaMail API allows Java components to send and receive emails.
JAXP (includes JAXB which is sometimes mentioned separately?)
Java API for XML Processing allows java applications to parse and transform XML documents.
JNDI
Java Naming and Directory Interface is a protocol which provides a standard API to access naming and directory services. It allows Java applications to find any necessary resource in a standard way.
Why use J2EE?
- It is a standardised and reliable software architecture
- that gives a lot of flexibility
- is well documented,
- with low level services already implemented.
Should foreign keys always be indexed?
In my opinion, mostly yes. The query optimizer will make a decision on whether it will be faster to use it or not. Indexes may not be of much use for low cardinality reference columns and will not be used by the optimiser.
On a Star Schema there may be some benefit from indexing low cardinality columns. This will give the query optimiser the option of using index intersection.
Foreign key indexing may not be desirable for purely data warehousing tables that are frequently batch loaded. The index write traffic will be large if there are many indexed columns and it may be necessary to disable foreign keys and indexes for these kinds of operations.
A more obscure reason for ensuring foreign keys are always indexed is the following - A delete from the parent table may lock the child table, which may result in a deadlock.
On a Star Schema there may be some benefit from indexing low cardinality columns. This will give the query optimiser the option of using index intersection.
Foreign key indexing may not be desirable for purely data warehousing tables that are frequently batch loaded. The index write traffic will be large if there are many indexed columns and it may be necessary to disable foreign keys and indexes for these kinds of operations.
A more obscure reason for ensuring foreign keys are always indexed is the following - A delete from the parent table may lock the child table, which may result in a deadlock.
Unexpected behaviour with JUnit ExpectedException
The JUnit ExpectedException allows specification of expected exception types and messages. One would think that code throwing the exception would carry on executing any lines following it as the exception is expected. This is not the case.
The solution is to make sure that the code throwing the exception is the last line of the method.
The solution is to make sure that the code throwing the exception is the last line of the method.
Friday, November 19, 2010
Google Maps API issue with popup window sizing
Several times as part of my work with the Google maps API now, I have seen cases where the content of an info window popup falls below the bottom end of the window.
This occurs when the API has trouble calculating the size of the content before it has loaded. For example it occurs frequently with images where the image size is not specified, inherited styles (as font size is calculated using a default font, which may not be the one specified in the CSS), and tables where the width is not specified exactly.
For example something like this does not work when cell data flows over multiple rows:
Whereas this does:
This occurs when the API has trouble calculating the size of the content before it has loaded. For example it occurs frequently with images where the image size is not specified, inherited styles (as font size is calculated using a default font, which may not be the one specified in the CSS), and tables where the width is not specified exactly.
For example something like this does not work when cell data flows over multiple rows:
<table border="1" cellspacing="1" cellpadding="3" width="100%" bgcolor="#EAF0F8">
...
</table>Whereas this does:
<table border="1" cellspacing="1" cellpadding="3" width="600px" bgcolor="#EAF0F8">
...
</table>Friday, October 8, 2010
setting Extjs Menu maximum height
I was recently trying to set the maximum height of an Extjs.menu.Menu and wasted way too much time on it, including posting on the Sencha forums and waiting in vain for a reply. But I now have a solution, and here it is, for the greater good of humanity...
What I tried that failed was something like:
menu = new Ext.menu.Menu({
id: 'menu',
style: '',
items: items,
renderTo: 'center_region',
showSeparator: false,
maxHeight: 100,
autoScroll: true,
enableScrolling: true
});
menu.showAt([x, y]);I tried various settings of autoHeight, style, etc. as well and nothing seemed to work. Adding the height attribute (height: 100) actually made a difference, but it now set the height permanently to 100px rather that a maximum of 100px, which resulted in a number of unsightly gaps at the bottom of the menu when the number of items was small.
The solution that finally worked for me was the following:
reportsMenu = new Ext.menu.Menu({
id: 'reportsMenu',
showSeparator: false,
boxMaxHeight: 150,
autoScroll: true,
enableScrolling: true,
items: selectedReports
});
reportsMenu.showAt([x, y]);
reportsMenu.syncSize();How one is supposed to figure that out from the Ext documentation beats me (unless hours of trial and error is intended). FYI I was using Extjs 3.1.1, in case it is ever updated to be more intuitive and the meaning of properties changes in future.
Tuesday, October 5, 2010
Extjs Store not loading
I recently came across the problem of my Extjs Store not loading anything, with no apparent errors. My Ext.data.Store loads data from a remote server and uses a Ext.data.ArrayReader with a converter for one of the fields, like:
The converter looks like this:
var convertRecords = function(v, record) {
for (var i = 0; i < v.length; i++) {
v[i] = new Record(
v[i].title,
v[i].description,
v[i].serviceType,
v[i].serviceURLs,
v[i].keywords);
}
return v;
};
The problem I had was that the convertRecords() seemed to begin execution but not complete, although the application was not stuck but appeared as if convertRecords() had returned.
The solution, which should help for any generic Store loading (or not loading) problem:
genericFeaturesStore.on({
'load': {
fn: function(store, records, options) {
alert("load");
},
scope: this
},
'loadexception': {
fn: function(obj, options, response, e) {
alert("error: "+e);
},
scope: this
}
});
This allowed me to see that it was throwing an error because it couldn't find the serviceType for one of the many records.
var genericFeaturesStore = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({url: 'getRecords.do'}),
reader: new Ext.data.ArrayReader({}, [
{ name: 'title' },
{ name: 'records', convert : convertRecords}
]),
...
});
proxy: new Ext.data.HttpProxy({url: 'getRecords.do'}),
reader: new Ext.data.ArrayReader({}, [
{ name: 'title' },
{ name: 'records', convert : convertRecords}
]),
...
});
The converter looks like this:
var convertRecords = function(v, record) {
for (var i = 0; i < v.length; i++) {
v[i] = new Record(
v[i].title,
v[i].description,
v[i].serviceType,
v[i].serviceURLs,
v[i].keywords);
}
return v;
};
The problem I had was that the convertRecords() seemed to begin execution but not complete, although the application was not stuck but appeared as if convertRecords() had returned.
The solution, which should help for any generic Store loading (or not loading) problem:
genericFeaturesStore.on({
'load': {
fn: function(store, records, options) {
alert("load");
},
scope: this
},
'loadexception': {
fn: function(obj, options, response, e) {
alert("error: "+e);
},
scope: this
}
});
This allowed me to see that it was throwing an error because it couldn't find the serviceType for one of the many records.
Thursday, September 9, 2010
Setting the scope of callbacks with Extjs
I recently ran into a problem where I was attempting to access a record in a collection being iterated over from inside a GDownloadUrl (Google Maps API) callback whose request would be executed as part of that loop. It took me a while to figure out the reason the last record was always getting passed to the callback no matter which callback was executing - GDownloadUrl is asynchronous and by the time any of the callbacks are executed the iteration was usually over!
Extjs provides an easy alternative to GDownloadUrl that allows access to the iteraiton record (or any other object) used when executing the callback - Ext.Ajax. All that needs to be done to retain the object required in the callback is to call createDelegate on the callback and then access the object in the callback using "this". An example is provided below:
for (var i = 0; i < activeLayersStore.getCount(); i++) {
var record = activeLayersPanel.getStore().getAt(i);
Ext.Ajax.request({
url: url,
timeout : 180000,
success: function(response, options) {
alert("The record for this iteration is: "+ this.get('TypeName'));
}.createDelegate(record),
failure: function(response, options) {
alert("Error requesting data" + response.statusText);
}
});
}
The documentation for Extjs Function.createDelegate can be found here: http://dev.sencha.com/deploy/dev/docs/?class=Function&member=createDelegate
Additionally, if multiple objects are required for use in the callback, the createDelegate may be used as follows:
Additionally, if multiple objects are required for use in the callback, the createDelegate may be used as follows:
yourFunction.createDelegate({ o1: obj1, o2: obj2 });
or alternatively, if the signature of your handler is flexible you can pass parameters as follows:
yourFunction.createDelegate(scope, [scope2], 2);
Friday, September 3, 2010
Image Zoom in Javascript
I recently spent some time investigating how to achieve image zoom using Javascript (as Extjs doesn't support it as of v3). There may be simpler jquery or other ways to achieve this but I wanted some simple Javascript. Suppose we have a couple of synced Extjs images and panels defined as follows:
Zoom can be achieved as follows:
The above zoom function is as far as I got with it before having to put it aside. As you may notice from the comments, it doesn't work that nicely in IE and setting of the scrollbars is quite jerky when setting both scrollLeft and scrollTop to somthing other than position 0. This is something I will need to investigate further and update here in future.
/**
* The first image (BoxComponent)
*/
var imgBox1 = new Ext.ux.Image({
id: 'img_box1',
src:'http://earthobservatory.nasa.gov/Features/BlueMarble/Images/land_shallow_topo_2048.jpg'
});
/**
* Panel for the first image
*/
var imgPanel1 = new Ext.Panel({
id: 'img_panel1',
title: "Migrated",
height: 280,
autoScroll: true,
items:[imgBox1],
listeners: {
render: function(p){
//sync scrolling between image panel 1 and 2
p.body.on('scroll', function(e){
var panel2 = Ext.getCmp('img_panel2').body.dom;
panel2.scrollLeft = e.target.scrollLeft;
panel2.scrollTop = e.target.scrollTop;
}, p);
}
}
});
/**
* The second image (BoxComponent)
*/
var imgBox2 = new Ext.ux.Image({
id: 'img_box2',
src:'http://earthobservatory.nasa.gov/Features/BlueMarble/Images/land_shallow_topo_2048.jpg'
});
/**
* Panel for the second image
*/
var imgPanel2 = new Ext.Panel({
id: 'img_panel2',
title: "Stacked",
height: 280,
autoScroll: true,
items:[imgBox2],
listeners: {
render: function(p){
//sync scrolling between image panel 1 and 2
p.body.on('scroll', function(e){
var panel1 = Ext.getCmp('img_panel1').body.dom;
panel1.scrollLeft = e.target.scrollLeft;
panel1.scrollTop = e.target.scrollTop;
}, p);
}
}
});
* The first image (BoxComponent)
*/
var imgBox1 = new Ext.ux.Image({
id: 'img_box1',
src:'http://earthobservatory.nasa.gov/Features/BlueMarble/Images/land_shallow_topo_2048.jpg'
});
/**
* Panel for the first image
*/
var imgPanel1 = new Ext.Panel({
id: 'img_panel1',
title: "Migrated",
height: 280,
autoScroll: true,
items:[imgBox1],
listeners: {
render: function(p){
//sync scrolling between image panel 1 and 2
p.body.on('scroll', function(e){
var panel2 = Ext.getCmp('img_panel2').body.dom;
panel2.scrollLeft = e.target.scrollLeft;
panel2.scrollTop = e.target.scrollTop;
}, p);
}
}
});
/**
* The second image (BoxComponent)
*/
var imgBox2 = new Ext.ux.Image({
id: 'img_box2',
src:'http://earthobservatory.nasa.gov/Features/BlueMarble/Images/land_shallow_topo_2048.jpg'
});
/**
* Panel for the second image
*/
var imgPanel2 = new Ext.Panel({
id: 'img_panel2',
title: "Stacked",
height: 280,
autoScroll: true,
items:[imgBox2],
listeners: {
render: function(p){
//sync scrolling between image panel 1 and 2
p.body.on('scroll', function(e){
var panel1 = Ext.getCmp('img_panel1').body.dom;
panel1.scrollLeft = e.target.scrollLeft;
panel1.scrollTop = e.target.scrollTop;
}, p);
}
}
});
Zoom can be achieved as follows:
/**
* Add zoom functionality to image panels
*/
'addZoom': function() {
var zooming=function(e){
e=window.event ||e;
var o=this,data=e.wheelDelta || -e.detail*40,zoom,size;
//TODO: Zooming in IE doesn't zoom to the correct point?
if(!+'\v1'){//IE
var oldWidth=o.offsetWidth;
var oldHeight=o.offsetHeight;
zoom = parseInt(o.style.zoom) || 100;
zoom += data / 12;
if(zoom > zooming.min)
o.style.zoom = zoom + '%';
e.returnValue=false;
var newWidth=o.offsetWidth*zoom/100;
var newHeight=o.offsetHeight*zoom/100;
var scrollLeft = (o.parentNode.scrollLeft/oldWidth)*newWidth;
var scrollTop = (o.parentNode.scrollTop/oldHeight)*newHeight;
o.parentNode.scrollLeft = scrollLeft;
o.parentNode.scrollTop = scrollTop;
}else {
size=o.getAttribute("_zoomsize").split(",");
zoom=parseInt(o.getAttribute("_zoom")) ||100;
zoom+=data/12;
var oldWidth=o.offsetWidth;
var oldHeight=o.offsetHeight;
var newWidth=size[0]*zoom/100;
var newHeight=size[1]*zoom/100;
var scrollLeft = (o.parentNode.scrollLeft/oldWidth)*newWidth;
var scrollTop = (o.parentNode.scrollTop/oldHeight)*newHeight;
if(zoom>zooming.min){
o.setAttribute("_zoom",zoom);
o.style.width=newWidth+"px";
o.style.height=newHeight+"px";
//TODO: Zoom is very jerky when setting scrollbars this way, when
// either scrollbar is not at position 0. Need to fix it.
o.parentNode.scrollLeft = scrollLeft;
o.parentNode.scrollTop = scrollTop;
}
e.preventDefault();
e.stopPropagation();//for firefox3.6
}
};
zooming.add=function(obj,min){// obj = image box, min defines the minimum image zoom size ,defaults to 50
zooming.min=min || 50;
obj.onmousewheel=zooming;
if(/Firefox/.test(navigator.userAgent))//if Firefox
obj.addEventListener("DOMMouseScroll",zooming,false);
if(-[1,]){//if not IE
obj.setAttribute("_zoomsize",obj.naturalWidth+","+obj.naturalHeight);
}
};
zooming.add(document.getElementById("img_box1"));
zooming.add(document.getElementById("img_box2"));
}
* Add zoom functionality to image panels
*/
'addZoom': function() {
var zooming=function(e){
e=window.event ||e;
var o=this,data=e.wheelDelta || -e.detail*40,zoom,size;
//TODO: Zooming in IE doesn't zoom to the correct point?
if(!+'\v1'){//IE
var oldWidth=o.offsetWidth;
var oldHeight=o.offsetHeight;
zoom = parseInt(o.style.zoom) || 100;
zoom += data / 12;
if(zoom > zooming.min)
o.style.zoom = zoom + '%';
e.returnValue=false;
var newWidth=o.offsetWidth*zoom/100;
var newHeight=o.offsetHeight*zoom/100;
var scrollLeft = (o.parentNode.scrollLeft/oldWidth)*newWidth;
var scrollTop = (o.parentNode.scrollTop/oldHeight)*newHeight;
o.parentNode.scrollLeft = scrollLeft;
o.parentNode.scrollTop = scrollTop;
}else {
size=o.getAttribute("_zoomsize").split(",");
zoom=parseInt(o.getAttribute("_zoom")) ||100;
zoom+=data/12;
var oldWidth=o.offsetWidth;
var oldHeight=o.offsetHeight;
var newWidth=size[0]*zoom/100;
var newHeight=size[1]*zoom/100;
var scrollLeft = (o.parentNode.scrollLeft/oldWidth)*newWidth;
var scrollTop = (o.parentNode.scrollTop/oldHeight)*newHeight;
if(zoom>zooming.min){
o.setAttribute("_zoom",zoom);
o.style.width=newWidth+"px";
o.style.height=newHeight+"px";
//TODO: Zoom is very jerky when setting scrollbars this way, when
// either scrollbar is not at position 0. Need to fix it.
o.parentNode.scrollLeft = scrollLeft;
o.parentNode.scrollTop = scrollTop;
}
e.preventDefault();
e.stopPropagation();//for firefox3.6
}
};
zooming.add=function(obj,min){// obj = image box, min defines the minimum image zoom size ,defaults to 50
zooming.min=min || 50;
obj.onmousewheel=zooming;
if(/Firefox/.test(navigator.userAgent))//if Firefox
obj.addEventListener("DOMMouseScroll",zooming,false);
if(-[1,]){//if not IE
obj.setAttribute("_zoomsize",obj.naturalWidth+","+obj.naturalHeight);
}
};
zooming.add(document.getElementById("img_box1"));
zooming.add(document.getElementById("img_box2"));
}
The above zoom function is as far as I got with it before having to put it aside. As you may notice from the comments, it doesn't work that nicely in IE and setting of the scrollbars is quite jerky when setting both scrollLeft and scrollTop to somthing other than position 0. This is something I will need to investigate further and update here in future.
Sunday, August 8, 2010
Learning Ext JS
Ext JS is a javascript library for building web applications, originally an extension of YUI.
The API documentation can be found at http://dev.sencha.com/deploy/dev/docs/
An excellent source for learning Ext JS are the YouTube tutorials by Jay Garcia from TDG-innovations (http://tdg-i.com/ has the screencasts with a better quality than those on YouTube). Some topics they have covered include:
The API documentation can be found at http://dev.sencha.com/deploy/dev/docs/
An excellent source for learning Ext JS are the YouTube tutorials by Jay Garcia from TDG-innovations (http://tdg-i.com/ has the screencasts with a better quality than those on YouTube). Some topics they have covered include:
- Ext.extend - subclassing with Ext JS
- Ext.apply - a utility that allows one to easily copy properties over from one object to anothe
- Ext.each - an alternative to a for loop, used to iteratie over an array (this one gets a little hairy in the screencast, I'm not sure how useful it really is)
- Containers (Ext.Panel, Ext.Window - add, remove, doLayout, Ext.Element, Ext.Fx - slideOut, fadeOut)
-
Tuesday, July 13, 2010
Inversion of Control
A common issue faced by enterprise application builders is how to fit together different elements, such as web controller architectures with DB interfaces, when they were built by different teams with little knowledge of eachother. IoC literally inverts control so that instead of application code calling libraries, libraries call the application code based on events occurring.
A good example of early IoC is the change in UIs, from being controlled by the application workflow, to GUIs which are controlled by events.
Another term for IoC is dependency injection, introduced by Martin Fowler, which is explained as follows: "The basic idea of Dependency Injection is to have a separate object, an assembler, that populates a field in X class with an implementation for Y interface."
A good example of early IoC is the change in UIs, from being controlled by the application workflow, to GUIs which are controlled by events.
Another term for IoC is dependency injection, introduced by Martin Fowler, which is explained as follows: "The basic idea of Dependency Injection is to have a separate object, an assembler, that populates a field in X class with an implementation for Y interface."
JBoss Application Server Overview
JBoss is a J2EE compatible application server that has full support for J2EE web services and the SOA. It supports the AOP model for developing middleware solutions and integrates well with Hibernate (object persistence framework).
The JBoss architecture consists of the microcontainer, bootstrap beans loaded into the microcontainer, a collection of deployers for loading various deployment types, and various mbean (managed beans - Java objects that represent resources to be managed) and legacy mbean deployments.
The JBoss Microcontainer is a lightweight container for managing POJOs, their deployment, configuration, and lifecycle.
You don't have to run a monolithic server all the time, but may remove components that are not required and integrate additional services as required, into JBoss by writing your own mbeans.
The JBoss AS ships with a number of different server configurations:
<JBoss_Home>\server\
<JBoss_Home>\server\<instance-name>\deployers or deploy.
JBoss provides an embedded Hypersonic database along with a default datasource to connect applications to.
When the JBoss server is running, you can get a live view of the server by going to the JMX console application. This is a raw view of JMX beans which make up the server.
In JBoss, log4j is used for logging, controlled by conf/jboss-log4j.xml. The default output file is the server.log.
The JBoss AS comes with clustering support out of the box. Ina JBoss cluster, a node is a JBoss server instance. A cluster (partition) contains a set of nodes that work toward some goal. The JBoss AS supports two types of clustering architectures - client side interceptors (proxies/stubs), and load balancers.
The JBoss architecture consists of the microcontainer, bootstrap beans loaded into the microcontainer, a collection of deployers for loading various deployment types, and various mbean (managed beans - Java objects that represent resources to be managed) and legacy mbean deployments.
The JBoss Microcontainer is a lightweight container for managing POJOs, their deployment, configuration, and lifecycle.
You don't have to run a monolithic server all the time, but may remove components that are not required and integrate additional services as required, into JBoss by writing your own mbeans.
The JBoss AS ships with a number of different server configurations:
<JBoss_Home>\server\
- minimal - bare-bones server, no web container, EJB, or JMS support
- default - a default set of services
- standard - the Java EE5 certified configuration of services
- all - all available services
- web - lightweight web container-oriented configuration of services
<JBoss_Home>\server\<instance-name>\deployers or deploy.
JBoss provides an embedded Hypersonic database along with a default datasource to connect applications to.
When the JBoss server is running, you can get a live view of the server by going to the JMX console application. This is a raw view of JMX beans which make up the server.
In JBoss, log4j is used for logging, controlled by conf/jboss-log4j.xml. The default output file is the server.log.
The JBoss AS comes with clustering support out of the box. Ina JBoss cluster, a node is a JBoss server instance. A cluster (partition) contains a set of nodes that work toward some goal. The JBoss AS supports two types of clustering architectures - client side interceptors (proxies/stubs), and load balancers.
Monday, July 12, 2010
JSP Overview
JSP is a popular Java technology for web application development and is based on servlet technology. A JSP page is a text document that contains two types of text - static data which can be expressed in any text-based format (HTML, SVG, XML, etc) and JSP elements (standard JSP or XML) which construct dynamic content.
A JSP page services requests as a servlet. In an application server, the source for the servlet created from a JSP named myPage is myPage_jsp.java. Once the JSP has been translated and compiled, the page's servlet follows the standard servlet lifecycle.
Expressions that are evaluated immediately use the ${ } syntax. Expressions that are differed use the #{ } syntax. Immediate evaluation expressions are always read-only value expressions.
Implicit objects include:
To declare that a JSP page will use tags defined in a tag library, include the taglib directive.
An Applet or JavaBeans component can be included in a JSP by using the jsp:plugin element.
A JSP page services requests as a servlet. In an application server, the source for the servlet created from a JSP named myPage is myPage_jsp.java. Once the JSP has been translated and compiled, the page's servlet follows the standard servlet lifecycle.
Expressions that are evaluated immediately use the ${ } syntax. Expressions that are differed use the #{ } syntax. Immediate evaluation expressions are always read-only value expressions.
Implicit objects include:
- PageContext
- Servlet Context
- Session
- Request
- Response
- etc.
- The JSP:useBean element declares that the page will use a bean that is stored within and is accessible from the specified scope (application, session, request, or page)
- jsp:setProperty
- jsp:getProperty
To declare that a JSP page will use tags defined in a tag library, include the taglib directive.
An Applet or JavaBeans component can be included in a JSP by using the jsp:plugin element.
Friday, July 9, 2010
The REST architectural style
REST, Representational State Transfer, is an architural style that captures (post-hoc) the characteristics of the Web that made it so successful. It is a simpler alternative to SOAP and WSDL-based Web Services, where a representation of the requested resource is returned.
A concrete implementation of a REST web service follows four basic design principles:
The JAX-RS provides full support for building and deploying RESTful web services. It offers a number of utility classes and interfaces, and declarative annotations that allow you to:
A concrete implementation of a REST web service follows four basic design principles:
- Uses HTTP methods explicitly (POST, GET, PUT, DELETE)
- Stateless
- Exposes directure structure
- Transfer XML, Javascript Object Notation, or both
The JAX-RS provides full support for building and deploying RESTful web services. It offers a number of utility classes and interfaces, and declarative annotations that allow you to:
- Identify components of the application
- route requests to particular methods/classes
- extract data from requests into arguments of methods
- provide metadata used in responses
Hibernate
Hibernate is a Java framework that provides OR mapping functionality to define how Java objects are stored, modified, deleted, and retrieved.
The Hibernate architecture has 3 main components:
The Hibernate Session is the main runtime interface between a Java application and Hibernate. SessionFactory allows the application to create a Hibernate Session by reading the configuration from hibernate.cfg.xml.
Important elements of the Hibernate mapping file include the following:
Hibernate also supports native SQL statements.
The Hibernate architecture has 3 main components:
- connection management
- transaction management
- object-relational mapping
The Hibernate Session is the main runtime interface between a Java application and Hibernate. SessionFactory allows the application to create a Hibernate Session by reading the configuration from hibernate.cfg.xml.
Important elements of the Hibernate mapping file include the following:
- <hibernate-mapping> root element
- <class> maps classes to DB entities
- <id> maps to the primary key of a table
- <generator> is used to generate the primary key for a new record. Values include increment, sequence, and assigned
- <property> maps attributes to columns
Hibernate also supports native SQL statements.