Saturday, October 30, 2010

Quartz

I’ve been setting up a Quartz scheduler recently. We wanted it to store the jobs in a Database. Quartz helpfully comes with a set of sql scripts for virtually all DB’s to create and manage all jobs, triggers, schedules etc via a transaction and cluster aware scheduler, so there is no need to think about that aspect of it. The scripts are all stored in the Quartz distribution under docs/dbTables folder.

Once the tables are all set up you can use the example application provided with Quartz to test out the DB persistence (Example 13). Configure it to point to your database by updating the instance1.properties file

We then wanted to Spring-ify it. This was straightforward

e.g.

public class RunSchedule {

static Logger _log = LoggerFactory.getLogger(RunSchedule.class);

public static void main(String[] args) throws Exception {

BeanFactory springContext = new ClassPathXmlApplicationContext("Spring-Quartz.xml");

cleanUp((Scheduler)springContext.getBean("plannedDowntimeScheduler"));

}

public static void cleanUp(Scheduler inScheduler) throws Exception {

_log.warn("***** Deleting existing jobs/triggers *****");

// unschedule jobs

String[] groups = inScheduler.getTriggerGroupNames();

for (int i = 0; i <>

String[] names = inScheduler.getTriggerNames(groups[i]);

for (int j = 0; j <>

inScheduler.unscheduleJob(names[j], groups[i]);

}

}

// delete jobs

groups = inScheduler.getJobGroupNames();

for (int i = 0; i <>

String[] names = inScheduler.getJobNames(groups[i]);

for (int j = 0; j <>

inScheduler.deleteJob(names[j], groups[i]);

}

}

}

}

And

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:jee="http://www.springframework.org/schema/jee"

xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:jms="http://www.springframework.org/schema/jms"xmlns:util="http://www.springframework.org/schema/util"

xsi:schemaLocation="

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd

http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-2.5.xsd

http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">

<bean id="runMeTask" class="ie.bge.middleware.RunMeTask" />

<bean name="runMeJob"

class="org.springframework.scheduling.quartz.JobDetailBean">

<property name="jobClass" value="ie.bge.middleware.RunMeJob" />

<property name="jobDataAsMap">

<map>

<entry key="runMeTask" value-ref="runMeTask" />

<map>

<property>

<bean>

<bean id="simpleTrigger"

class="org.springframework.scheduling.quartz.SimpleTriggerBean">

<property name="jobDetail" ref="runMeJob" />

<property name="repeatInterval" value="5000" />

<property name="startDelay" value="1000" />

<bean>

<bean id="cronTrigger"

class="org.springframework.scheduling.quartz.CronTriggerBean">

<property name="jobDetail" ref="runMeJob" />

<property name="cronExpression" value="0/5 * * * * ?" />

<bean>

<bean name="plannedDowntimeScheduler"

class="org.springframework.scheduling.quartz.SchedulerFactoryBean" init-method=”start”>

<property name="quartzProperties">

<util:properties location="/quartz.properties" />

property>

<property name="applicationContextSchedulerContextKey"

value="applicationContext" />

<property name="waitForJobsToCompleteOnShutdown" value="true" />

<bean>

<beans>

All works as expected.

N.B. Note the init-method attribute for SchedulerFactoryBean. This is to automate the starting of the scheduler after it is instantiated. It is better than having a code based startup, (which would implement the Spring InitializingBean)

When we integrated it into our main application however we started having issues.

Code:

Caused by: org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: ORA-00942: table or view does not exist

[See nested exception: java.sql.SQLException: ORA-00942: table or view does not exist

]]

The problem was due to autowiring. We had a datasource defined for a different purpose that was getting autowired into our SchedulerFactoryBean. (We were defining the datasource via the quartz.properties, and not injecting the datasource).


Manually wiring the correct dataSource fixed the problem. (or turninng off autowiring should also work as suggested by jrsisson)

http://forum.springsource.org/showthread.php?p=326612&posted=1#post326612

Spring

BeanFactory or ApplicationContext?


Taken from Spring website

Users are sometimes unsure whether a BeanFactory or an ApplicationContext is best suited for use in a particular situation. A BeanFactory pretty much just instantiates and configures beans. AnApplicationContext also does that, and it provides the supporting infrastructure to enable lots of enterprise-specific features such as transactions and AOP.

In short, favor the use of an ApplicationContext.

(For the specific details behind this recommendation, see this section.)

CSS Javascript quickie

Center (Centre) a div

Its easy, but its not necessarily obvious. To centre a div you need to set the width, and the margin-left and right to auto,

e.g.

#div{

width: 500px; margin-left: auto ; margin-right: auto ;

}

To center text within a div use.

text-align: center ;

http://www.thesitewizard.com/css/center-div-block.shtml

Javascript

Useful links explaining with nice and simple explanations of objects in javascript (I wonder how I never “got it” before considering how simply its described here)

http://javascriptkit.com/javatutors/object3.shtml

Also the prototype modifier. Basically it allows properties, and methods to be added to objects. Effectively making javascript OO, instead of purely functional.

http://www.javascriptkit.com/javatutors/proto4.shtml

Saturday, October 16, 2010

Recording a desktop demo video/ viewlet


Just a quick note about recording a desktop demo (viewlet). These are very handy for demo’s on using software etc. They allow you to record the screen activity, while adding voice over commentary, and popup overlays.

One of the best freeware recorders is Wink

http://www.debugmode.com/wink/

Also some image compression stuff on here.

Svn identity/ login

If subversion in eclipse is pestering you for login credentials every few seconds, then your credentials may have got corrupted.

You can reset the stored credentials by deleting the auth directory.

This is usually located at

Unix (linux/ Osx)
~/.subversion/auth

Windows:

USER_HOME/Application Data/Subversion/auth

Taken from http://osdir.com/ml/version-control.subversion.subclipse.user/2006-08/msg00029.html


.keyring file only used when JavaSVN adapter is selected.

Also, your repository may allow anonymous read access, so browsing and
update operation doesn't require you to log in. Supclipse only prompts for
credentials when credentials are requested by Subversion server.

Weblogic JMS

Link for looking up all jms queues using jmx

http://weblogic-zone.blogspot.com/2010/01/jms-resources-using-jmx.html

You can use a JMX program, WLST, JConsole, or the console.

See the documentation on using WLST

http://download.oracle.com/docs/cd/E15523_01/web.1111/e13715/toc.htm

See the documentation on writing JMX clients

http://download.oracle.com/docs/cd/E15523_01/web.1111/e13729/toc.htm

See the MBean reference documentation

http://download.oracle.com/docs/cd/E15523_01/apirefs.1111/e13951/core/index.html

The JMX distributed queue mbeans have type = weblogic.j2ee.descriptor.wl.DistributedQueueBean

You can either walk down the hierarchy starting at the Domain MBean and into the JMSSystemResource MBean or you can query for specific MBean types.


JMS and OSB

One issue that I’ve seen on a client site.

An OSB proxy is set up to consume from a JMS queue. Data is injected into the queue but the Proxy does not consume it.

(Only seen when custom dispatch policies were used)

This is a weblogic bug. The workaround is to go through the configuration of the proxy, and assign it a different Dispatch Policy. This would enable consuming of the queue. Then you can simply rollback the change in OSB, and consuming will continue.


JMS Unit of Order

http://download.oracle.com/docs/cd/E12840_01/wls/docs103/jms/uoo.html

Message Unit-of-Order is a WebLogic Server value-added feature that enables a stand-alone message producer, or a group of producers acting as one, to group messages into a single unit with respect to the processing order.
Note that it appears to cause problems with the JMS Api's for viewing message payloads.

Editied Note.. We found an MBean API for discovering these. It involves using the MBean operation getMessages (specifying a flag). I will blog about it later

Weblogic Roles

Just a quick reminder for myself. This is easy but on initial inspection it seems like there is something missing. In fact it is easy, but appearance can be confusing.

The high level is. You are using weblogic server to host your apps. You want some security policies for your apps. It therefore makes sence to use the weblogic security realm, and its roles, groups, users and policies to manage the entity.

-. Create new Role(s).

From weblogic console, goto Security Realm, Select realm, select Roles and Policies.

Now expand the global Roles, and click on the Roles link. This will allow you to create custom roles.

-. Create/ edit Groups to include new Roles

Assign users to groups

JSTL snippets

Simple when you know how. Frustrating and time consuming when you don’t
If/ else
Because of the xml format we can’t have a
<c:if test=”${actionBean.test}”>
</c:if>
<c:else>
</c:else>
Instead we have to use choose, when and otherwise.
e.g.
<c:choose>
<c:when test="${actionBean.test}”>
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose>

Looping through lists
Realated to above, I was trying to test if a list was populated.
First attempt was
<c:choose>
<c:when test="${actionBean.result.size>0}">
javax.el.PropertyNotFoundException: The class 'java.util.Collections$Synchronize
dCollection' does not have the property 'size'.
at javax.el.BeanELResolver.getBeanProperty(BeanELResolver.java:547)
at javax.el.BeanELResolver.getValue(BeanELResolver.java:249)
at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:143)
at com.sun.el.parser.AstValue.getValue(AstValue.java:118)
at com.sun.el.parser.AstGreaterThan.getValue(AstGreaterThan.java:41)
Truncated. see log file for complete stacktrace
Solution is to use Not Empty
<c:when test="${not empty actionBean.result}">

Monday, October 11, 2010