[Home] [Technology Journal] [Repository]  [Cooking] [Event Calendar]
Technology journal - Languages & Specifications

GWT - Google Web Toolkit | J2SE | JTA - Transactions | JMS - Messaging | JDBC | Log4J
GWT - Google Web Toolkit  

Issue and solution
Issue: java.lang.classnotfoundexception com.mysql.jdbc.driver eclipse
Solution: Since tomcat is embeded in the GWT package there is no common/lib directory to place the mysql jar (driver). You need to place this file in the start up script (shell.cmd if windows) as a classpath entry. In addition to that the mysql jar needs to be added to the project Java build path. Right click on the project in eciplse and select "Properties". From there add the mysql driver as an external jar.

Code snippet of my shell.cmd
@java -Xmx256M -cp "%~dp0\src;%~dp0\bin;C:/Applications/gwt-windows-1.5.3/gwt-user.jar;C:/Applications/gwt-windows-1.5.3/gwt-dev-windows.jar;C:/DEV/Library/mysql-connector-java-5.0.8/mysql-connector-java-5.0.8-bin.jar" com.google.gwt.dev.GWTShell -out "%~dp0\www" %* com.google.gwt.sample.stockwatcher.StockWatcher/StockWatcher.html

J2SE  

Multithreading
Main points to remember
Source: About.com (http://java.about.com/)

In multithreading programming each instruction sequence has its own unique flow of control that is independent of all others. These independently executed instruction sequences are known as threads.

Single CPU - multiple threads
Single-processing systems support logical concurrency, not physical concurrency. Logical concurrency is when multiple threads execute with separate independent theads of control.
on multi-processing systems several threads do in fact execute at the same time and physical concurrency is achieved.

Multithreading and Multiprogramming
Multithreading differs from multiprgramming. Multithreading provides concurrency within the execution of a single process. Whereas multiprogramming provides concurrency between multiple processes. Multithreading also requires less processing overhead than multiprogramming because concurrent threads are able to share common resources more easily. Multiple executing programs tend to duplicate resources and share data as the result of time consuming inter-process communication.


Two ways to create threads in Java
  1. Method 1: Create a subclass of the class Thread and override the run() method to provide an entry point into the thread's execution.
  2. Method 2: Implement the java.lang.Runnable interface. This interface contains the single method run() which must be overriden by your class.
The drawback of creating threads using the first method is that you are required to keep your objects under the Thread class in the class hierarchy.

Sample implementations:
Method 1
Download the program
Java file: TheadTest1.java
Method 2
Download the program
Java file: TheadTest2.java
The main() method of ThreadTest2 differs from that of ThreadTest1 in the way that it creates thread1 and thread2. ThreadTest1 created the threads as new instances of the MyThread class. ThreadTest2 was not able to create the threads directly, because MyClass is not a subclass of Thread. Instead, ThreadTest2 first created instances of MyClass and then passed them to the Thread() constructor, creating instances of class Thread. The Thread() constructor used by ThreadTest2 takes as its argument any class that implements the Runnable interface. This is an example of the flexibility and multiple-inheritance features provided by Java interfaces. The rest of the ThreadTest2 main() method is the same as that of ThreadTest1.

Thread states
State Description
New thread state Before a thread is started it is said to be in this state
Runnable state After a thread is started it is supposed to be in this state. When a class is in the runnable state, it may be executing or temporarily waiting to share processing resources with other threads.
Not runnable state In this state a thread is not just waiting for its share of processing resources, but it is blocked waiting for the occurrence of an event that will send it back to the runnable state. For example the sleep() method causes a thread to enter the not runnable state until the specified time has expired. A thread may also enter the not runnable state while its waiting for I/O to be completed.
Dead state A thread enters this state when the method stop() (this method is deprecated) is invoked or the threads execution is complete. When a thread enters this state it cannot be revived or returned to any other state.

Thread priority and scheduling
Generally threads share execution time with each other based on the availability of the systems CPU (or CPUs).
Scheduling: this is the approach to determine which threads should execute at a given time. Scheduling is performed by the Java runtime system and is based on priprities. The highest priority thread is in the runnable state and is the one that is run at any given instant. The highest priority thread continues to run until it enters the death state / not runnable state or has its priority lowered.
Javas approach to scheduling is known as preemptive scheduling. When a thread of higher priority becomes runnable, it preempts threads of lower priority and is immediately executed in their place.

Synchronization
There are times when you want to coordinate access to shared resources. Java enables you to coordinate the actions of multiple threads using synchronized methods and synchrnozed statements.

Log4J  

Configuration File
The configuration file may be specified at runtime using the log4j.configuration Java property
The configuration file may declare:
  1. Loggers
    • An Application can have multiple loggers each with a unique name. The Logger class defines 4 methods: debug, info, warn and error (in order of importance)
  2. Appenders
    • Log4j defines Appenders to represent destinations for logging output. Multiple Appenders may be defined for each Logger.
      • RollingFileAppender: Backs up a copy of the log file once it reaches a file size limit
      • ConsoleAppender: Sends messages to the Console
  3. Layouts
    • Layouts define the format of the logged messages
<appender name="SYSLOGFILE" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="workshop_debug.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="500000KB" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{DATE} %-5p %-15c{1} [%t][%x]: %m%n"/>
</layout>
</appender>

The element:
The function of this element is to relate the sources to the log files defined in the elements of the configuration file

e.g.
<category name="weblogic.servlet.jsp">
<priority value="warn" />
<appender-ref ref="SYSLOGFILE" />
<appender-ref ref="SYSERRORLOGFILE" />
</category> The priority value defines the lowest level a message will be sent to an appender. In this case all messages of type warn and higher will be sent.
Adding Log4J messages to your application code
To cause your code to emit messages obtain a Logger for your file.

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

private transient final Log logger = LogFactory.getLog(getClass());

logger.error("Node: " + context.getExceptionInfo().getExceptionNodeName() + ":", e);

WebLogic Workshop
For Workshop the default logging level is set to "info". To enable logging of all message levels, set the log level for the category "wlw" to debug in the configuration file (workshopLogCfg.xml)

<!-- The wlw category is used for messages logged using the Logger API from JwsContext and ControlContext -->
<category name="wlw">
<priority value="debug" />
<appender-ref ref="APPLOGFILE" />
</category>

Tracking Log Information in a Clustered Environment
In a clustered environment you may want to track log messages for individual servers in the cluster. You can modify the configuration for Appenders in workshopLogCfg.xml to include a variable that returns the name of the server which logged the message. When WebLogic Server starts, it sets an environment variable weblogic.Name with the server name. You can refer to this variable from the log file.

<appender name="APPLOGFILE" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="workshop.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="3000KB" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="server:${weblogic.Name} %d{DATE} %-5p %-15c{1}: %m%n"/>
</layout>
</appender>
If you are expecting a high volume of log messages, you can modify each Appender so that a separate log file is written for each server. In this case you modify the value of the tag named File to prepend the server name to generate a unique log file for each server, as shown in the following example:

<appender name="APPLOGFILE" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="${weblogic.Name}.workshop.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="3000KB" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{DATE} %-5p %-15c{1}: %m%n"/>
</layout>
</appender>

Log Interceptor

Log interception is a variant of log scrapping. While many logging tools allow you to introspect messages after the fact, log interceptors allow one to act on an event without incurring additional I/O costs. Log4J interceptor processes run in the same process space as the application.

JTA - Transactions  

Transactions 101
ACID properties
  1. Atomicity - all changes made to a database are done as one unit of work otherwise all changes are rolled back
  2. Consistency - a successful transaction transforms a database from a previous valid state to a new valid state
  3. Isolation - changes made by a transaction to a database are not visible to other transactions until the transaction completes its work
  4. Durability - changes made by a transaction to a database survive future system or media failures
Distributed Transactions and the Two-Phase commit protocol

definition: A distributed transaction is one that updates multiple resource managers (such as databases) in a coordinated manner
definition: The 2 phase commit protocol is a method of coordinating a single transaction across two or more resource managers.
It guarantees data integrity by ensuring that transactional updates are committed in all of the participating databases, or are fully rolled back out of all the databases, reverting to a state prior to the start of the transaction



The first phase of the two commit protocol is the "prepare" phase. The required updates are recorded in a transactional log file, and the resource must indicate, through a resource manager that it is ready to make the changes. Resources can either vote to make the commit or rollback.

JMS - Messaging  

Configuring a JMS Connection Factory to be XA compliant
A JMS Client needs to obtain a connection from a messaging system before it can send or receive messages from a JMS queue. A connection is obtained via a connection factory. A connection factory is a resource that is configured in the message server administrator. The names of a connection factory are stored in a JNDI directory.

In weblogic workshop there is a default connection factory that is configured (cgConnectionFactory). You have the option to override this factory with your own implementation.

To override the default factory with your own implementation you must do the following:
  1. Add the connection factory to the deployment description (weblogic-ejb-jar.xml)
  2. Add the connection factory to the server configuration file (config.xml)
  3. Make the connection factory XA enabled

Deployment description (weblogic-ejb-jar.xml)

 
  myMessageDrivenBean
  
  ...
  some.name.connection.factory
  ...
  

 



config.xml
JNDIName="myMessageDrivenBean"
Name="JMSConnectionFactory"
Targets="myWebLogicServer"
XAConnectionFactoryEnabled="true"/>

JMS - an overview
The Java Message Service (JMS) provides a standard Java-based interface to a MOM (Message Oriented Middleware) of some other provider.

Messaging systems are classified into the following different models:
  • Publish-Subscribe Messaging
    When multiple applications need to receive the same message. Publishers typically send messages to a Topic and all Subscribers of that Topic get a message
  • Point-To-Point Messaging
    When multiple senders send a message to only one receiver. There are two models one client sends a message to another client directly. Multiple clients send messages to a Message Queue. The receiving client receives the message from the queue.
  • Request-Reply Messaging
    Synchornous messaging where a client who sends a request expects a response. JMS does not explicitly support this model though it allows it in the context of the other methods.

Points
  • In JMS both Publish-Subscribe and Point-to-Point are implemented using interfaces hence the provider (e.g. MQ Series) does not have to support both
  • A ConnectionFactory is used to create connections for JMS implementations
  • JMS provides support for distributed transactions
  • Topics are used for Publish-Subscribe messaging (Destination: Topic, ConnectionFactory: TopicConnectionFactory, etc.)
  • Queues are used for Point-to-Point messaging (Destination: Queue, ConnectionFactory: QueueConnectionFactory, etc.)
Point to Point impelmentation

import javax.jms.*;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.InitialContext;
import java.util.Hashtable;
import java.io.File;
import java.io.FileReader;
import java.util.Date;
import java.util.Enumeration;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import weblogic.jms.extensions.WLMessageProducer;

public class PersistentTaskQueue implements TaskQueue {
private static final Log logger = LogFactory.getLog(PersistentTaskQueue.class);

// Defines the JNDI context factory.
private String initialContextFactory;

// Defines the JMS connection factory.
private String queueConnectionFactory;

// Defines the queue.
private String queueName;
private String jndiServerUrl=null;

private QueueConnectionFactory qconFactory;
private QueueConnection qcon;
private QueueSession qsession;
private QueueSender qsender;
private Queue queue;
private TextMessage msg;

InitialContext ctx = null;
// Clear the queue
public void clear() throws Exception {
open();
QueueReceiver qreceiver = qsession.createReceiver(queue);
qcon.start();

while(true) {
Message m = qreceiver.receiveNoWait();
if(m == null) {
break;
}

logger.debug("Received message sechdule at " + new Date(msg.getLongProperty("scheduleTime")));
}
}
// Browse Through the queue
public void browse() throws Exception {
open();
QueueBrowser qbrowser = qsession.createBrowser(queue, "TimeToDeliver >" + System.currentTimeMillis());
qcon.start();

Enumeration e = qbrowser.getEnumeration();
logger.debug("Received enumeration:" + e);
while(e.hasMoreElements()) {
Message m = (Message)e.nextElement();
logger.debug("Received message sechdule at " + new Date(msg.getLongProperty("scheduleTime")));
}
}
// Open the queue
public void open() throws Exception {
qconFactory = (QueueConnectionFactory) ctx.lookup(queueConnectionFactory);
qcon = qconFactory.createQueueConnection();
qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queue = (Queue) ctx.lookup(queueName);
}
// Close the queue
public void close() {
try {
qsender.close();
qsession.close();
qcon.close();
}catch(Throwable e) {
}finally{
qsender = null;
qsession = null;
qcon = null;
}
}
// Set Initial context
private InitialContext getInitialContext(String url) throws NamingException {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
env.put(Context.PROVIDER_URL, url);
return new InitialContext(env);
}
// Add message to queue
public void addMessage(Integer ID, String task, long processTime) throws CoreException {
try {
open();
qsender = qsession.createSender(queue);
qcon.start();

msg = qsession.createTextMessage();
long delay = processTime - System.currentTimeMillis();
if(delay < 0) {
delay = 0;
}

logger.debug("Setting JMS message delivery time to " + new Date(processTime));
WLMessageProducer wlp= (WLMessageProducer)qsender;
wlp.setTimeToDeliver(delay);

logger.debug("Set JMS message delivery increment is to " + delay);
msg.setJMSCorrelationID(ID.toString());

msg.setLongProperty("scheduleTime", processTime);
msg.setStringProperty("schedule", ID.toString());
msg.setText(task);

qsender.send(msg);

close();
}catch(Exception jme) {
throw new CoreException("Failed to set next schedule.", jme);
}

}

JDBC  

JDBC is a Call-Level Interface. Call-level interfaces do not require pre-compilation and thus avoid some of the problems of embedded SQL. The result is increased portability and a cleaner client-server relationship

Difference between Statement and PreparedStatement
A Statement object is associated with an open connection, and not any single SQL statement.
A Prepared Statement is associated with a channel with a connection and a compiled SQL Statement. On receipt of a SQL statement the Prepared Statement channel sends the SQL to the DBMS where it is compiled. The advantage is that if you want to use the same query multiple times, by using a Prepared Statement object the query is only compiled and optimized once. The opposite is true for a Statement object.

CallableStatement

Example:

public Account[] getAccountsByRelm(String relmIdentifier) throws CoreException
{
  Account accounts[] = null;
  Connection jcon = null;
  Statement stmt = null;
  ResultSet rs = null;
  CallableStatement callableStatement = null;
  try {
    DataSource ds = (DataSource)ctx.lookup("DS/COMPOSITE");
    jcon = ds.getConnection();
    stmt = jcon.createStatement();

    String callString = "{call SProc(?,?,?,?,?)}";
    callableStatement = jcon.prepareCall(callString);
    callableStatement.setString(2,"IDName");
    callableStatement.setString(3,Identifier);
    callableStatement.setString(4," ");
    callableStatement.setString(5," ");
    callableStatement.registerOutParameter(1,java.sql.Types.OTHER);
    System.out.println("\n Callable query is: " + callableStatement.toString());
    rs = callableStatement.executeQuery();

    System.out.println("\n rs is: " + rs.getFetchSize());

    int i = 0;
    Account account = null;
    if (rs.getFetchSize() > 0) {
    while (rs.next()) {
    account = new Account(rs.getString(1),rs.getString(2),rs.getString(3),rs.getString(4),rs.getString(5));

    }
  }

  } catch (Exception e) {
  e.printStackTrace();
  if (jcon != null) {
    try {
      jcon.rollback();
    } catch (SQLException e1) {
      e1.printStackTrace();
    }
    }
  } finally {
  if (jcon != null) {
    try {
      System.out.print(" Closing down all connections...\n\n");
      jcon.close();
    } catch (SQLException e) {
      e.printStackTrace();
    }
    }
  }
  return accounts;
}
[Home] [Technology Journal] [Repository]  [Cooking] [Event Calendar]