간단하게 정리된 HashTable의 사용예.
쉽게 HashTable은 key, data의 조합으로 사용되며
key를 사용하여 data를 조회할 수 있다.

from:http://www.java2s.com/Code/Java/Collections-Data-Structure/DemonstratetheHashtableclassandanEnumeration.htm
/*
 * Copyright (c) Ian F. Darwin, http://www.darwinsys.com/, 1996-2002.
 * All rights reserved. Software written by Ian F. Darwin and others.
 * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Java, the Duke mascot, and all variants of Sun's Java "steaming coffee
 * cup" logo are trademarks of Sun Microsystems. Sun's, and James Gosling's,
 * pioneering role in inventing and promulgating (and standardizing) the Java
 * language and environment is gratefully acknowledged.
 *
 * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
 * inventing predecessor languages C and C++ is also gratefully acknowledged.
 */

import java.util.Enumeration;
import java.util.Hashtable;

/**
 * Demonstrate the Hashtable class, and an Enumeration.
 *
 * @see HashMapDemo, for the newer HashMap class.
 */
public class HashtableDemo {

  public static void main(String[] argv) {

    // Construct and load the hash. This simulates loading a
    // database or reading from a file, or wherever the data is.

    Hashtable h = new Hashtable();

    // The hash maps from company name to address.
    // In real life this might map to an Address object...
    h.put("Adobe", "Mountain View, CA");
    h.put("IBM", "White Plains, NY");
    h.put("Learning Tree", "Los Angeles, CA");
    h.put("Microsoft", "Redmond, WA");
    h.put("Netscape", "Mountain View, CA");
    h.put("O'Reilly", "Sebastopol, CA");
    h.put("Sun", "Mountain View, CA");

    // Two versions of the "retrieval" phase.
    // Version 1: get one pair's value given its key
    // (presumably the key would really come from user input):
    String queryString = "O'Reilly";
    System.out.println("You asked about " + queryString + ".");
    String resultString = (String) h.get(queryString);
    System.out.println("They are located in: " + resultString);
    System.out.println();

    // Version 2: get ALL the keys and pairs
    // (maybe to print a report, or to save to disk)
    Enumeration k = h.keys();
    while (k.hasMoreElements()) {
      String key = (String) k.nextElement();
      System.out.println("Key " + key + "; Value " + (String) h.get(key));
    }
  }
}
Posted by twintail twintail

신경안쓰고 사용하던 와중에 책에서 읽은 내용

checked exception과 unchecked exception으로 분류된다.

checked exception은 java.lang.Exception을 상속하는 예외들로 try~catch로 구문 처리해줘야만 한다. 그렇지 않은 경우 컴파일 타임에 예외를 발생한다.

unchecked exception은 java.lang.RuntimeException을 상속하는 예외들로 try~catch로 구문처리 하지 않아도 컴파일 타임에 에러를 유발하지 않는다.
프로그램 실행시 발생하는 exception이다.

처리의 방식은 간단히 설명하면 꼭 필요하지 않은 경우에는 unchecked exception으로 처리해야 한다고 한다.
예로서 business 로직(의미는 누가 정한 것인지..)의 exception은 business exception의 경우만 checked로 처리하고 그렇지 않은 부분은 unchecked exception으로 처리한다.

이런 방법이 확실히 혼란을 막기엔 충분한 조치라고 생각한다.

이전의 내 방식은 모든 예외는 던져서 최종적으로 확인된 코드에서 부터 거꾸로 올라거 확인하는 방식이었지만 이제는 방법을 바꿔야 할 것 같다.

이러한 Exception은 jsp에서 catch하거나 에러페이지를 따로 두어서 처리하는 것이 효율적인 방법이다. 일일이 로그를 뒤져갈 필요가 없기 때문이기도 하다.

특정에러 페이지를 두어 관리자/사용자가 같은 메시지를 보지 않도록 하는 것도 필요할 것이다.

Posted by twintail twintail

autoReconnect는 비추천되고 있다. 결과를 가져올때까지 반복하는 것이 해결책으로 제시되고 있다.

참고.


Question:

I have a servlet/application that works fine for a day, and then stops working overnight

Answer:

MySQL closes connections after 8 hours of inactivity. You either need to use a connection pool that handles stale connections or use the "autoReconnect" parameter (see Section 23.3.4.1, “Driver/Datasource Class Names, URL Syntax and Configuration Properties for Connector/J”).

Also, you should be catching SQLExceptions in your application and dealing with them, rather than propagating them all the way until your application exits, this is just good programming practice. MySQL Connector/J will set the SQLState (see java.sql.SQLException.getSQLState() in your APIDOCS) to "08S01" when it encounters network-connectivity issues during the processing of a query. Your application code should then attempt to re-connect to MySQL at this point.

The following (simplistic) example shows what code that can handle these exceptions might look like:

Example 23.12. Example of transaction with retry logic

[CODE type=java]public void doBusinessOp() throws SQLException {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;

//
// How many times do you want to retry the transaction
// (or at least _getting_ a connection)?
//
int retryCount = 5;

boolean transactionCompleted = false;

do {
try {
conn = getConnection(); // assume getting this from a
// javax.sql.DataSource, or the
// java.sql.DriverManager

conn.setAutoCommit(false);

//
// Okay, at this point, the 'retry-ability' of the
// transaction really depends on your application logic,
// whether or not you're using autocommit (in this case
// not), and whether you're using transacational storage
// engines
//
// For this example, we'll assume that it's _not_ safe
// to retry the entire transaction, so we set retry count
// to 0 at this point
//
// If you were using exclusively transaction-safe tables,
// or your application could recover from a connection going
// bad in the middle of an operation, then you would not
// touch 'retryCount' here, and just let the loop repeat
// until retryCount == 0.
//
retryCount = 0;

stmt = conn.createStatement();

String query = "SELECT foo FROM bar ORDER BY baz";

rs = stmt.executeQuery(query);

while (rs.next()) {
}

rs.close();
rs = null;

stmt.close();
stmt = null;

conn.commit();
conn.close();
conn = null;

transactionCompleted = true;
} catch (SQLException sqlEx) {

//
// The two SQL states that are 'retry-able' are 08S01
// for a communications error, and 40001 for deadlock.
//
// Only retry if the error was due to a stale connection,
// communications problem or deadlock
//

String sqlState = sqlEx.getSQLState();

if ("08S01".equals(sqlState) || "40001".equals(sqlState)) {
retryCount--;
} else {
retryCount = 0;
}
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
// You'd probably want to log this . . .
}
}

if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
// You'd probably want to log this as well . . .
}
}

if (conn != null) {
try {
//
// If we got here, and conn is not null, the
// transaction should be rolled back, as not
// all work has been done

try {
conn.rollback();
} finally {
conn.close();
}
} catch (SQLException sqlEx) {
//
// If we got an exception here, something
// pretty serious is going on, so we better
// pass it up the stack, rather than just
// logging it. . .

throw sqlEx;
}
}
}
} while (!transactionCompleted && (retryCount > 0));
}[/CODE]

Note. Use of the autoReconnect option is not recommended because there is no safe method of reconnecting to the MySQL server without risking some corruption of the connection state or database state information. Instead, you should use a connection pool which will enable your application to connect to the MySQL server using an available connection from the pool. The autoReconnect facility is deprecated, and may be removed in a future release.

Posted by twintail twintail

Jboss의 DB Source의 설정은 3개의 파일에 의해서 이루어진다.

우선 deploy 폴더에 test-ds.xml로 작성된 파일을 보면

<?xml version="1.0" encoding="UTF-8"?>

<datasources>
  <local-tx-datasource>
     <jndi-name>jdbc/test</jndi-name>-->
     <connection-url>jdbc:mysql://127.0.0.1:3306/test?zeroDateTimeBehavior=round</connection-url>
     <driver-class>com.mysql.jdbc.Driver</driver-class>
     <user-name>test</user-name>
     <password>test</password>
     <min-pool-size>5</min-pool-size>
     <max-pool-size>20</max-pool-size>
     <idle-timeout-minutes>1</idle-timeout-minutes>
     <track-statements>true</track-statements>
  </local-tx-datasource>
</datasources>

위와 같이 설정을 할 수가 있다. jboss deploy 폴더에 XXXX-ds.xml로 저장되어야만 Data Source 로 인식된다.

두번째로 확인해야 할 것은

war file의 WEB-INF에 포함되는 jboss-web.xml이다.

<?xml version="1.0" encoding="UTF-8"?>

<jboss-web>

   <resource-ref>
       <res-ref-name>test-ds</res-ref-name>
       <res-type>javax.sql.DataSource</res-type>
       <jndi-name>java:/jdbc/test</jndi-name>
   </resource-ref>

</jboss-web>

위에서 표시된 test-ds는 참조 Data source를 나타낸다. 따라서 data source 설정을 하고 있은 test-ds.xml을 나타낸다.

마지막 설정으로 web.xml에 resource-ref를 설정한다.

   <resource-ref>
       <description>DB Connection</description>
       <res-ref-name>test-ds</res-ref-name>
       <res-type>javax.sql.DataSource</res-type>
       <res-auth>Container</res-auth>
   </resource-ref>

jboss-web.xml이 없어도 될거라고 생각했지만 실제로 jboss-web.xml이 없으면 에러를 유발한다.
web.xml내에 설정이 없다면 web applicaion에서 동작하지 않는 것으로 확인 되었다.

자세한 내용은 jboss 관리자 메뉴얼을 보시면 자세한 설명이 있습니다.



Posted by twintail twintail
TAG Java, Jboss, JNDI


Introducing a simple generalisation of the Java language's Timer class

Level: Intermediate

Tom White
Lead Java Developer, Kizoom
4 November 2003

All manner of Java applications commonly need to schedule tasks for repeated execution. Enterprise applications need to schedule daily logging or overnight batch processes. A J2SE or J2ME calendar application needs to schedule alarms for a user's appointments. However, the standard scheduling classes, Timer and TimerTask, are not flexible enough to support the range of scheduling tasks typically required. In this article, Java developer Tom White shows you how to build a simple, general scheduling framework for task execution conforming to an arbitrarily complex schedule.

The java.util.Timer and java.util.TimerTask classes, which I'll refer to collectively as the Java timer framework, make it easy for programmers to schedule simple tasks. (Note that these classes are also available in J2ME.) Before this framework was introduced in the Java 2 SDK, Standard Edition, Version 1.3, developers had to write their own scheduler, which involved grappling with threads and the intricacies of the Object.wait() method. However, the Java timer framework is not rich enough to meet the scheduling requirements of many applications. Even a task that needs repeating every day at the same time cannot be directly scheduled using Timer, due to the time jumps that occur as daylight saving time comes and goes.

This article presents a scheduling framework that is a generalisation of Timer and TimerTask to allow more flexible scheduling. The framework is very simple -- it consists of two classes and an interface -- and it's easy to learn. If you're used to working with the Java timer framework, you should be able to pick up the scheduling framework very quickly. (For more information about the Java timer framework, see Resources.)

Scheduling a one-shot task
The scheduling framework is built on top of the Java timer framework classes. Therefore, we'll first look at scheduling using these classes before I explain how the scheduling framework is used and how it is implemented.

Imagine an egg timer that tells you when a number of minutes have elapsed (and therefore that your egg is cooked) by playing a sound. The code in Listing 1 forms the basis for a simple egg timer written in the Java language:

Listing 1. EggTimer class

package org.tiling.scheduling.examples;

import java.util.Timer;
import java.util.TimerTask;

public class EggTimer {
private final Timer timer = new Timer();
private final int minutes;

public EggTimer(int minutes) {
this.minutes = minutes;
}

public void start() {
timer.schedule(new TimerTask() {
public void run() {
playSound();
timer.cancel();
}
private void playSound() {
System.out.println("Your egg is ready!");
// Start a new thread to play a sound...
}
}, minutes * 60 * 1000);
}

public static void main(String[] args) {
EggTimer eggTimer = new EggTimer(2);
eggTimer.start();
}

}

An EggTimer instance owns a Timer instance to provide the necessary scheduling. When the egg timer is started using the start() method, it schedules a TimerTask to execute after the specified number of minutes. When the time is up, the run() method on the TimerTask is called behind the scenes by Timer, which causes it to play a sound. The application then terminates after the timer is cancelled.

Scheduling a recurring task
Timer allows tasks to be scheduled for repeated execution by specifying a fixed rate of execution or a fixed delay between executions. However, there are many applications that have more complex scheduling requirements. For example, an alarm clock that sounds a wake-up call every morning at the same time cannot simply use a fixed rate schedule of 86400000 milliseconds (24 hours), because the alarm would be too late or early on the days the clocks go forward or backward (if your time zone uses daylight saving time). The solution is to use calendar arithmetic to calculate the next scheduled occurrence of a daily event. This is precisely what the scheduling framework supports. Consider the AlarmClock implementation in Listing 2 (see Resources to download the source code for the scheduling framework, as well as a JAR file containing the framework and examples):

Listing 2. AlarmClock class

package org.tiling.scheduling.examples;

import java.text.SimpleDateFormat;

import java.util.Date;

import org.tiling.scheduling.Scheduler;
import org.tiling.scheduling.SchedulerTask;
import org.tiling.scheduling.examples.iterators.DailyIterator;

public class AlarmClock {

private final Scheduler scheduler = new Scheduler();
private final SimpleDateFormat dateFormat =
new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS");
private final int hourOfDay, minute, second;

public AlarmClock(int hourOfDay, int minute, int second) {
this.hourOfDay = hourOfDay;
this.minute = minute;
this.second = second;
}

public void start() {
scheduler.schedule(new SchedulerTask() {
public void run() {
soundAlarm();
}
private void soundAlarm() {
System.out.println("Wake up! " +
"It's " + dateFormat.format(new Date()));
// Start a new thread to sound an alarm...
}
}, new DailyIterator(hourOfDay, minute, second));
}

public static void main(String[] args) {
AlarmClock alarmClock = new AlarmClock(7, 0, 0);
alarmClock.start();
}
}

Notice how similar the code is to the egg timer application. The AlarmClock instance owns a Scheduler instance (rather than a Timer) to provide the necessary scheduling. When started, the alarm clock schedules a SchedulerTask (rather than a TimerTask) to play the alarm. And instead of scheduling the task for execution after a fixed delay, the alarm clock uses a DailyIterator class to describe its schedule. In this case, it simply schedules the task at 7:00 AM every day. Here is the output from a typical run:


Wake up! It's 24 Aug 2003 07:00:00.023
Wake up! It's 25 Aug 2003 07:00:00.001
Wake up! It's 26 Aug 2003 07:00:00.058
Wake up! It's 27 Aug 2003 07:00:00.015
Wake up! It's 28 Aug 2003 07:00:00.002
...

DailyIterator implements ScheduleIterator, an interface that specifies the scheduled execution times of a SchedulerTask as a series of java.util.Date objects. The next() method then iterates over the Date objects in chronological order. A return value of null causes the task to be cancelled (that is, it will never be run again) -- indeed, an attempt to reschedule will cause an exception to be thrown. Listing 3 contains the ScheduleIterator interface:

Listing 3. ScheduleIterator interface

package org.tiling.scheduling;

import java.util.Date;

public interface ScheduleIterator {
public Date next();
}

DailyIterator's next() method returns Date objects that represent the same time each day (7:00 AM), as shown in Listing 4. So if you call next() on a newly constructed DailyIterator class, you will get 7:00 AM of the day on or after the date passed into the constructor. Subsequent calls to next() will return 7:00 AM on subsequent days, repeating forever. To achieve this behavior DailyIterator uses a java.util.Calendar instance. The constructor sets up the calendar so that the first invocation of next() returns the correct Date simply by adding a day onto the calendar. Note that the code contains no explicit reference to daylight saving time corrections; it doesn't need to because the Calendar implementation (in this case GregorianCalendar) takes care of this.

Listing 4. DailyIterator class

package org.tiling.scheduling.examples.iterators;

import org.tiling.scheduling.ScheduleIterator;

import java.util.Calendar;
import java.util.Date;

/**
* A DailyIterator class returns a sequence of dates on subsequent days
* representing the same time each day.
*/
public class DailyIterator implements ScheduleIterator {
private final int hourOfDay, minute, second;
private final Calendar calendar = Calendar.getInstance();

public DailyIterator(int hourOfDay, int minute, int second) {
this(hourOfDay, minute, second, new Date());
}

public DailyIterator(int hourOfDay, int minute, int second, Date date) {
this.hourOfDay = hourOfDay;
this.minute = minute;
this.second = second;
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
calendar.set(Calendar.MILLISECOND, 0);
if (!calendar.getTime().before(date)) {
calendar.add(Calendar.DATE, -1);
}
}

public Date next() {
calendar.add(Calendar.DATE, 1);
return calendar.getTime();
}

}

Implementing the scheduling framework
In the previous section, we learned how to use the scheduling framework and compared it with the Java timer framework. Next, I'll show you how the framework is implemented. In addition to the ScheduleIterator interface shown in Listing 3, there are two other classes -- Scheduler and SchedulerTask -- that make up the framework. These classes actually use Timer and TimerTask under the covers, since a schedule is really no more than a series of one-shot timers. Listings 5 and 6 show the source code for the two classes:

Listing 5. Scheduler

package org.tiling.scheduling;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class Scheduler {

class SchedulerTimerTask extends TimerTask {
private SchedulerTask schedulerTask;
private ScheduleIterator iterator;
public SchedulerTimerTask(SchedulerTask schedulerTask,
ScheduleIterator iterator) {
this.schedulerTask = schedulerTask;
this.iterator = iterator;
}
public void run() {
schedulerTask.run();
reschedule(schedulerTask, iterator);
}
}

private final Timer timer = new Timer();

public Scheduler() {
}

public void cancel() {
timer.cancel();
}

public void schedule(SchedulerTask schedulerTask,
ScheduleIterator iterator) {

Date time = iterator.next();
if (time == null) {
schedulerTask.cancel();
} else {
synchronized(schedulerTask.lock) {
if (schedulerTask.state != SchedulerTask.VIRGIN) {
throw new IllegalStateException("Task already
scheduled " + "or cancelled");
}
schedulerTask.state = SchedulerTask.SCHEDULED;
schedulerTask.timerTask =
new SchedulerTimerTask(schedulerTask, iterator);
timer.schedule(schedulerTask.timerTask, time);
}
}
}

private void reschedule(SchedulerTask schedulerTask,
ScheduleIterator iterator) {

Date time = iterator.next();
if (time == null) {
schedulerTask.cancel();
} else {
synchronized(schedulerTask.lock) {
if (schedulerTask.state != SchedulerTask.CANCELLED) {
schedulerTask.timerTask =
new SchedulerTimerTask(schedulerTask, iterator);
timer.schedule(schedulerTask.timerTask, time);
}
}
}
}

}

Listing 6 shows the source code for the SchedulerTask class:

Listing 6. SchedulerTask

package org.tiling.scheduling;

import java.util.TimerTask;

public abstract class SchedulerTask implements Runnable {

final Object lock = new Object();

int state = VIRGIN;
static final int VIRGIN = 0;
static final int SCHEDULED = 1;
static final int CANCELLED = 2;

TimerTask timerTask;

protected SchedulerTask() {
}

public abstract void run();

public boolean cancel() {
synchronized(lock) {
if (timerTask != null) {
timerTask.cancel();
}
boolean result = (state == SCHEDULED);
state = CANCELLED;
return result;
}
}

public long scheduledExecutionTime() {
synchronized(lock) {
return timerTask == null ? 0 : timerTask.scheduledExecutionTime();
}
}

}

Like the egg timer, every instance of Scheduler owns an instance of Timer to provide the underlying scheduling. Instead of the single one-shot timer used to implement the egg timer, Scheduler strings together a chain of one-shot timers to execute a SchedulerTask class at the times specified by a ScheduleIterator.

Consider the public schedule() method on Scheduler -- this is the entry point for scheduling because it is the method a client calls. (The only other public method, cancel(), is described in Canceling tasks.) The time of the first execution of the SchedulerTask is discovered by calling next() on the ScheduleIterator interface. The scheduling is then kicked off by calling the one-shot schedule() method on the underlying Timer class for execution at this time. The TimerTask object supplied for one-shot execution is an instance of the nested SchedulerTimerTask class, which packages up the task and the iterator. At the allotted time, the run() method is called on the nested class, which uses the packaged task and iterator references to reschedule the next execution of the task. The reschedule() method is very similar to the schedule() method, except that it is private and performs a slightly different set of state checks on SchedulerTask. The rescheduling process repeats indefinitely, constructing a new nested class instance for each scheduled execution, until the task or the scheduler is cancelled (or the JVM shuts down).

Like its counterpart TimerTask, SchedulerTask goes through a series of states during its lifetime. When created, it is in a VIRGIN state, which simply means it has never been scheduled. Once scheduled, it shifts to a SCHEDULED state, then later to a CANCELLED state if the task is cancelled by one of the methods described below. Managing the correct state transitions, such as ensuring that a non-VIRGIN task is not scheduled twice, adds extra complexity to the Scheduler and SchedulerTask classes. Whenever an operation is performed that might change the state of the task, the code must synchronize on the task's lock object.

Canceling tasks
There are three ways to cancel a scheduled task. The first is to call the cancel() method on the SchedulerTask. This is like calling cancel() on a TimerTask: the task will never run again, although it will run to completion if already running. The return value of the cancel() method is a boolean that indicates whether further scheduled tasks might have run had cancel() not been called. More precisely, it returns true if the task was in a SCHEDULED state immediately prior to calling cancel(). If you try to reschedule a cancelled (or even scheduled) task, Scheduler throws an IllegalStateException.

The second way to cancel a scheduled task is for ScheduleIterator to return null. This is simply a shortcut for the first way, as the Scheduler class calls cancel() on the SchedulerTask class. Canceling a task this way is useful if you want the iterator -- rather than the task -- to control when the scheduling stops.

The third way is to cancel the whole Scheduler by calling its cancel() method. This cancels all the scheduler's tasks and leaves it in a state where no more tasks may be scheduled on it.

Extending the cron facility
The scheduling framework could be likened to the UNIX cron facility, except that the specification of scheduling times is controlled imperatively rather than declaratively. For example, the DailyIterator class used in the implementation of AlarmClock has the same scheduling as a cron job, specified by a crontab entry beginning 0 7 * * *. (The fields specify minute, hour, day of month, month, and day of week, respectively.)

However, the scheduling framework has more flexibility than cron. Imagine a HeatingController application that switches the hot water on in the mornings. I would like to instruct it to "turn the hot water on at 8:00 AM on weekdays and 9:00 AM on weekends." Using cron, I would need two crontab entries (0 8 * * 1,2,3,4,5 and 0 9 * * 6,7). By using a ScheduleIterator, the solution is more elegant because I can define a single iterator using composition. Listing 7 shows one way to do this:

Listing 7. Using composition to define a single iterator

int[] weekdays = new int[] {
Calendar.MONDAY,
Calendar.TUESDAY,
Calendar.WEDNESDAY,
Calendar.THURSDAY,
Calendar.FRIDAY
};
int[] weekend = new int[] {
Calendar.SATURDAY,
Calendar.SUNDAY
};
ScheduleIterator i = new CompositeIterator(
new ScheduleIterator[] {
new RestrictedDailyIterator(8, 0, 0, weekdays),
new RestrictedDailyIterator(9, 0, 0, weekend)
}
);

A RestrictedDailyIterator class is like DailyIterator, except it is restricted to run on particular days of the week; and a CompositeIterator class takes a set of ScheduleIterators and correctly orders the dates into a single schedule. See Resources for the source code to these classes.

There are many other schedules that cron cannot produce, but an implementation of ScheduleIterator can. For instance, the schedule described by "the last day of every month" can be implemented using standard Java calendar arithmetic (using the Calendar class), whereas it is impossible to express this using cron. Applications don't even have to use the Calendar class. In the source code for this article (see Resources), I have included an example of a security light controller that runs to the schedule "turn the lights on 15 minutes before sunset." The implementation uses the Calendrical Calculations Software Package (see Resources) to compute the time of the sunset locally (given the latitude and longitude).

Real-time guarantees
When writing applications that use scheduling, it is important to understand what the framework promises in terms of timeliness. Will my tasks be executed early or late? If so, what's the maximum margin of error? Unfortunately, there are no simple answers to these questions. However, in practice the behavior is good enough for a large class of applications. The discussion below assumes that the system clock is correct (see Resources for information on the Network Time Protocol).

Because Scheduler delegates its scheduling to the Timer class, the real-time guarantees that Scheduler can make are identical to those of Timer. Timer schedules tasks using the Object.wait(long) method. The current thread is made to wait until it is woken up, which can happen for one of these reasons:

  1. The notify() or notifyAll() method is called on the object by another thread.
  2. The thread is interrupted by another thread.
  3. The thread is woken up in the absence of a notify (known as a spurious wakeup, described in Item 50 of Joshua Bloch's Effective Java Programming Language Guide -- see Resources).
  4. The specified amount of time has elapsed.

The first possibility cannot occur for the Timer class because the object that wait() is called on is private. Even so, the implementation of Timer safeguards against the first three causes of early wakeup, thus ensuring that the thread wakes up after the time has elapsed. Now, the documentation comment for Object.wait(long) states it may wake up after the time has elapsed "more or less", so it is possible that the thread wakes up early. In this case, Timer issues another wait() for (scheduledExecutionTime - System.currentTimeMillis()) milliseconds, thereby guaranteeing that tasks can never be executed early.

Can tasks be executed late? Yes. There are two main causes of late execution: thread scheduling and garbage collection.

The Java language specification is purposefully vague on thread scheduling. This is because the Java platform is general purpose and targets a wide range of hardware and associated operating systems. While most JVM implementations have a thread scheduler that is fair, it is by no means guaranteed -- certainly implementations have different strategies for allocating processor time to threads. Therefore, when a Timer thread wakes up after its allotted time, the time at which it actually executes its task depends on the JVM's thread scheduling policy, as well as how many other threads are contending for processor time. Therefore, to mitigate late task execution, you should minimize the number of runnable threads in your application. It is worth considering running schedulers in a separate JVM to achieve this.

The time that the JVM spends performing garbage collection (GC) can be significant for large applications that create lots of objects. By default, when GC occurs the whole application must wait for it to finish, which may take several seconds or more. (The command line option -verbose:gc for the java application launcher will cause each GC event to be reported to the console.) To minimize pauses due to GC, which may hinder prompt task execution, you should minimize the number of objects your application creates. Again, this is helped by running your scheduling code in a separate JVM. Also, there are a number of tuning options that you can try to minimize GC pauses. For instance, incremental GC attempts to spread the cost of the major collections over several minor collections. The trade-off is that this reduces the efficiency of GC, but this might be an acceptable price for timelier scheduling. (See Resources for more GC tuning hints.)

When was I scheduled?
To determine whether tasks are being run in a timely manner, it helps if the tasks themselves monitor and record any instances of late execution. SchedulerTask, like TimerTask, has a scheduledExecutionTime() method that returns the time that the most recent execution of this task was scheduled to occur. Evaluating the expression System.currentTimeMillis() - scheduledExecutionTime() at the beginning of the task's run() method lets you determine how late the task was executed, in milliseconds. This value could be logged to produce statistics on the distribution of late execution. The value might also be used to decide what action the task should take -- for example, if the task is too late, it might do nothing. If, after following the guidelines above, your application requires stricter guarantees of timeliness, consider looking at the Real-time Specification for Java (see Resources for more information).

Conclusion
In this article, I have introduced a simple enhancement to the Java timer framework that permits very flexible scheduling strategies. The new framework is essentially a generalisation of cron -- in fact, it would be valuable to implement cron as a ScheduleIterator interface to provide a pure Java cron replacement. While not offering strict real-time guarantees, the framework is applicable to a host of general purpose Java applications that need to schedule tasks on a regular basis.

Resources

About the author
Tom White is Lead Java Developer at Kizoom, a leading UK software company in the delivery of personalised travel information to mobile devices. Clients include the UK's national train operator, the London public transport system, and UK national bus companies. Since its founding in 1999, Kizoom has used all the disciplines from Extreme Programming. Tom has been writing Java programs full time since 1996, using most of the standard and enterprise Java APIs, from client Swing GUIs and graphics to back-end messaging systems. He has a first class honours degree in mathematics from Cambridge University. When not programming, Tom enjoys making his young daughter laugh and watching 1930s Hollywood films. Contact Tom at tom-at-tiling.org.
Posted by twintail twintail
TAG Java, timer

스트링을 비교하면서 자주 실수를 하게 되는데.

== 또는 !=을 사용하여 String을 비교하는 경우가 많다.

if(stringValue == "string") {
   return true;
}


이와 같이 사용하게 되는데, 이렇게 사용하는 경우 간혹 체크가 안될수 있다고 한다.
전에도 종종 실수하곤 했는데 이 부분은 매번 ==을 사용해서 습관이 되버린 것인지.

String을 비교하는 올바른 표현은 다음과 같다.
if(stringValue.equals("string") {
   return true;
}


Posted by twintail twintail
TAG If, Java, string, 비교

from : http://forum.java.sun.com/thread.jspa?threadID=601573&messageID=3230332

DB Connect 와 관련된 설정.

예시

Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");
Connection conn = ds.getConnection();


참고자료.



Posted by twintail twintail
TAG Java, JNDI

assert는 jdk 1.4에서부터 지원하기 시작하셨습니다.

근래에 들어서 1.5 패키지를 사용하기 시작하면서.. 간혹 코드중에 assert가 등장하곤 합니다.
예를 들면 코드 중간에 assert depth < elName.length; 이렇게 적혀 있다던가 하는 등의 라인을 발견하게 되면
이게 뭐지 하는 생각을 하게 됩니다.

assert는 다음과 같은 방법으로 표현이 됩니다.
assert Expression1 ;
assert Expression1 : Expression2 ;

자 그러면 왜 assert를 사용하는가? 여기저기 사이트를 뒤져본 결과에 따르면
assert 다음의 표현식이 false일 경우 AssertionError를 발생하게 된다고 합니다.

간단한 사용의 예로는 각 변수에 임의의 값이 있어야 하는데 그값이 제대로 들어갔는지 확인을 하기 위해 다음과 같이 사용을 할 수가 있습니다.

이경우 keyValue 가 null이라면 AssertionError를 발생하게 될 것입니다.
public void setKeyValue(Object keyValue){
   assert (keyValue != null);
   this.keyValue = keyValue;
}


AssertionError을 검출해 내기 위해선 VM parameter로  -ea를 지정해 줘야 합니다.
제가 주로 사용하는 eclipse에서는 기본적으로 -da로 설정되어 검출을 사용하지 않는가 봅니다.
다음과 같이 사용이 가능합니다.
java -ea className

이렇게 동작하였을 경우 에러메시지는 다음과 같습니다.
Exception in thread "main" java.lang.AssertionError
   at test.assertion.Foo.main(Foo.java:16)

assert false; 라고 표현한 부분에서 에러를 도출해 내고 있습니다.

다음 예제는 java spec 3.0을 참조한 내용입니다. 무엇을 나타내려고 하는 것인지 생각해 봅시다.
package test.assertion;

public class Foo {

   static{
       System.out.println("Foo");
   }
   public static void main(String[] args) {
       System.out.println("Foo.main()");
       Baz.testAsserts();
       // Will execute after Baz is initialized.
       System.out.println("other test");
      
       int testValue = 0;
      
       assert testValue == 1;
           System.out.println("assert is false");
       assert testValue == 0;
           System.out.println("assert is true");
          
       assert false;
          
   }
}

class Bar {
   static {
       System.out.println("Bar");
       Baz.testAsserts();
       // Will execute before Baz is initialized!
   }
}

class Baz extends Bar {
   static void testAsserts() {
       System.out.println("Baz");
       boolean enabled = false;
       assert enabled = true;
       System.out.println("Asserts " + (enabled ? "enabled" : "disabled"));
   }

}

이러한 assert의 사용법은 제약이 있는 프로그래밍에서 사용이 가능합니다.
데이터의 범위가 정확한지 아니면 제한을 넘어서지 않는지를 미리 점검하고 프로그래밍하는 것이 가능합니다.
이렇게 하는 것은 체계적인 사전 조건을 이용하여 시스템의 안정성을 확보하는 것이 이후 발생되는 에러를 처리하는 것보다 시스템의 설계단계에서 보다 일관적이고 좋다는 의견이 있습니다.

assert는 TDD에도 종종 사용되는 것 같습니다. vm 단계에서 활성화/비활성화가 가능하므로 테스트 단계에서는 이를 활성화하여 테스트를 수행하고 운용 단계에서 비활성화하는 경우도 있다고 합니다.
반면에 모든 부분에 assert를 사용하는 것은 무리가 있을수도 있습니다. 굳이 확인이 필요한 부분이라고는 하지만 반드시 동작하는 부분에 대하여 assert를 사용하는 것은 불필요한 사용이 될 수 있습니다.

관련 URL : http://java.sun.com/j2se/1.4/docs/guide/lang/assert.html
Posted by twintail twintail
TAG assert, Java

Servlet을 실제로 사용하고 있는 분들은 많으실 것입니다. init()에 대해서 간략히 요약을 하려고 합니다.
init()은 Servlet의 초기화 메소드로 Servlet이 적재 될때 호출이 된다고 합니다. 그러면 그 시점은 서버를 가동할 때라고 인식하기 쉽지만.  실제로 호출이 되는 시점은 서블릿이 호출되는 시점에서 init()메서드를 호출합니다.
반면에 매번 호출하지는 않습니다. 한번만 호출을 하도록 되어 있습니다. 이때 함께사용되는 것들이 초기화 메소드이므로 ServletConfig와 관련된 메소드의 호출이있습니다. 환경변수의 로딩 등 서블릿을 처음 가동하는데 필요한 사전 동작을 처리하는 메소드가 Servlet의 init()입니다.

추가내용 : 내용은 위와 같이 설명되어 있으나. 일부 서버에서는 서블릿을 적재하는 과정에서 init()을 호출하는 듯하다. jboss에서 테스트해본 결과 서버를 구동하는 과정에서 init()이 호출되는 것을 확인하였다.

Posted by twintail twintail

Installation

To install JiBX, just download the distribution zip file and unpack it.This will create a jibx directory that contains the distribution files,including a complete copy of this documentation. The readme.html file inthe unpacked root directory gives more information and links to some includeddemonstration code, and to the local copy of this documentation.

If you're using Maven, you can use the JiBX repositoryat http://jibx.sourceforge.net/maven/to get a specific version of the distribution jar files (as jibx-bind-1.0.jar,jibx-run-1.0.jar, etc.). There's also a Maven2 plugin available for JiBX.

Binding definitions

To use JiBX, you'll need to first create a binding definition that describeshow your XML documents are connected to your Java objects. Here's a simpleexample just to give you a feeling for how this works:

Figure 1. Simple binding example

In this example I've got an XML document with a <customer> root elementthat I want to bind to a Customer class in my Java code. Thebinding definition tells JiBX the details of how this binding is to beperformed. The color coding in the diagram shows how the three parts interrelate.The mapping element within the binding definition (shown in green)creates the basic linkage between the <customer> element and theCustomer class. The child elements of the mappingelement provide the details of this linkage - for example, the first valuechild element (shown in blue) links the <first-name> child element tothe firstName field of the Customer class.

JiBX's binding capabilities go far beyond what's shown by this simple example. On theJava side, you can use fields of any access type (including private),or use JavaBean-style get/set methods if you prefer. You can easily definecustom serialization handlers for data values, and you can tell JiBX to callyour own methods at various points in the binding process to allow furthercustomizations. To learn more about using these and many other JiBX featurescheck out the Binding Tutorial section of this site.

If you're starting from existing Java code you may find the Generator Tools subproject useful. This includes a tool whichwill generate a default binding for a set of Java classes (and a separate toolto generate an XML schema definition from a binding definition and thereferenced Java classes). Similarly, if you're starting from an XML schemadefinition you may find the Xsd2Jibx subprojectuseful. This provides a tool to generate a set of Java classes and acorresponding binding definition from a schema. These subprojects can help a lotin getting started, but you should still take the time to understandhow bindings work before you go too far with JiBX.

Using JiBX

Once you've got a binding definition for your document format you're readyto begin using JiBX. To do this, you first compile your application classes asnormal, then run the JiBX Binding Compiler. The bindingcompiler converts your binding definition into actual code in the form of bindingmethods that it adds to your application class files (you can alsorun the binding compiler at runtime, to modify yourclasses before they're loaded into the JVM). The methods added by the bindingcompiler are then used by the JiBX Runtime to actuallymarshal and unmarshal your Java classes to and from XML.

Starter project

The JiBX distribution includes an example starter project, with an Antbuild.xml script for compiling, binding, and running the projectcode. This is found in the starter directory off the installation root.See the index.html page in this directory for details.

Details

That's the summary. Here are the links for the details of these steps,along with information on some useful tools included in the distribution:

Posted by twintail twintail
TAG Java, jibx, xml