home personal workZone travel about
code.pst » tech musings and code posts

Archive for the ‘Spring’ Category

Spring DM OSGi demo app

Monday, September 28th, 2009

As you will see Spring DM makes life much simpler! It manages all “OSGi aware” pieces of the application for you and you can rid of the Activators.

The bundles we need now are similar as before. I will prefix “spring” to the artifactId just so its easier.

The shared service: We don’t need to change anything in shared so just use the older one as-is.

Creating a service implementation: The ComplexService we defined now needs to be implemented and made available as an OSGi service. Lets create a simple ComplexServiceImpl:

public class ComplexServiceImpl implements ComplexService {
	public String doSomething() {
		return "Hello from Version 1!";
	}
}

To register the service we now use the OSGi extender provided by Spring DM. All we need to do is create some XML configs.

<?xml version="1.0" encoding="UTF-8"?>
<beans ..... >
 
  <!-- Create bean -->
  <bean id="complexService" class="com.irahul.spring.complexapp.ComplexServiceImpl"/>
 
  <!-- register service -->
  <osgi:service ref="complexService" interface="com.irahul.shared.ComplexService" />
 
</beans>

Creating the servlet: In Spring world we just create the handler and then wire it up using XML.

public class MyHandler implements Servlet {
	private HttpService httpService;
	private List<ComplexService> complexServices;
 
	public void setHttpService(HttpService httpService){
		this.httpService = httpService;		
	}
 
	public void setComplexServices(List<ComplexService> complexServices) {
		this.complexServices = complexServices;
	}
 
	//ideally this should be externalized. Have a manager listen for servlets but keeping it simple
	public void init() throws Exception{
		httpService.registerServlet("/", this, null, null);	
	}
 
	public void service(ServletRequest request, ServletResponse response)
		throws ServletException, IOException {
 
		//we may have discovered more than 1 service
		if(complexServices==null|| complexServices.size()==0){
			response.getOutputStream().print("No Service found!");
		}
		else{
			//there are 1...n services, pick one
			//using a random pick
			response.getOutputStream().print(complexServices.get(
					new Random().nextInt(complexServices.size())).doSomething());
		}
	}
	....
}

Configuring it:

<?xml version="1.0" encoding="UTF-8"?>
<beans ..... >
 
  <!-- Reference list of services in OSGi -->
  <osgi:list id="complexServiceList" interface="com.irahul.shared.ComplexService" cardinality="0..N"/>
 
  <!-- Reference to Http Service -->
  <osgi:reference id="httpService" interface="org.osgi.service.http.HttpService"/>
 
  <!-- Create handler -->
  <bean id="myHandler" class="com.irahul.spring.http.handler.MyHandler" init-method="init">
  	<property name="complexServices" ref="complexServiceList"/>
  	<property name="httpService" ref="httpService"/>
  </bean>
 
</beans>

Download full source.

Running in Eclipse Equinox: Use the following config.ini


osgi.bundles=log4j.osgi-1.2.15-SNAPSHOT.jar@start, com.springsource.org.aopalliance-1.0.0.jar@start, com.springsource.slf4j.log4j-1.5.0.jar@start, com.springsource.slf4j.api-1.5.0.jar@start, com.springsource.slf4j.org.apache.commons.logging-1.5.0.jar@start, com.springsource.javax.servlet-2.4.0.jar@start, services-3.1.2.jar@start, org.eclipse.equinox.http.jar@start, org.springframework.aop-2.5.6.A.jar@start, org.springframework.beans-2.5.6.A.jar@start, org.springframework.context-2.5.6.A.jar@start, org.springframework.core-2.5.6.A.jar@start, spring-osgi-core-1.2.0.jar@start, spring-osgi-io-1.2.0.jar@start, spring-osgi-extender-1.2.0.jar@start, spring-osgi-annotation-1.2.0.jar@start, shared-1.0-SNAPSHOT.jar@start, spring.complexapp-1.0-SNAPSHOT.jar@start, spring.complexapp-2.0-SNAPSHOT.jar@start, spring.http.handler-1.0-SNAPSHOT.jar@start
eclipse.ignoreApp=true

That is it, see you at code-camp!

Injecting beans into Quartz job

Thursday, May 28th, 2009

Finally as promised the revised and more efficient way to inject beans directly into your quartz jobs. Simply use the jobDataAsMap property.

<bean name="jobBean" class="org.springframework.scheduling.quartz.JobDetailBean">
		<property name="jobClass" value="com.irahul.example.SpringQuartzJob" />	  
	  	<property name="name" value="jobName" />
	  	<property name="jobDataAsMap">
			<map>
				<entry key="setterName" value-ref="beanRef" />				
                                .....
			</map>
		</property>
	</bean>

Accessing Spring beans from Quartz jobs

Saturday, November 3rd, 2007

I had referred to Mark’s blog in my earlier post and actually now have a improvement over his solution. Define your context as usual (courtesy to Mark for his example)

<beans>
  <!-- Define the Job Bean that will be executed. 
  Our bean is named in the jobClass property. -->
  <bean name="myJob" class="org.springframework.scheduling.quartz.JobDetailBean">
    <property name="jobClass" value="com.gsoftware.common.util.MyJob"/>
  </bean>
  <!-- Associate the Job Bean with a Trigger. 
  Triggers define when a job is executed. -->
  <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
    <!-- see the example of method invoking job above -->
    <property name="jobDetail" ref="myJob"/>
    <property name="startDelay" value="2000"/>
    <property name="repeatInterval" value="10000"/>
  </bean>
  <!-- A list of Triggers to be scheduled and executed by Quartz -->
  <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
      <list><ref bean="simpleTrigger"/></list>
    </property>
    <property name="applicationContextSchedulerContextKey" value="applicationContext"/>
  </bean>
</beans>

Note that in the factory I have added the property for the application context.
Now all you need to do in your job is extend the spring base class QuartzJobBean for a job and create a setter as follows:

public class MyJob extends QuartzJobBean {
  private ApplicationContext applicationContext;
 
  public void setApplicationContext(ApplicationContext appContext) {
    applicationContext = appContext;
  }
 
  @Override
  protected void executeInternal(JobExecutionContext executionContext) {
    //your code...
 
  }
}

Now you have the application context available in your job. Nothing else required!

OSGi – Spring Quartz job

Tuesday, October 30th, 2007

Mark’s blog provides a good example of how to provide the Spring application context to a Job. Here I will show how to ’inject’ OSGi services into your Spring OSGi application. This will become much cleaner once Spring Dynamic Modules executor bundle is released but at the moment using Spring 2.0.7 I need to provide some OSGi services to my Quartz job.

I have say a bundle ‘MyServiceBundle’ that registers a service with the following interface:

package com.irahul.example.myservicebundle; 
public interface TransactionService{ 
    void updateTransaction(Long id, String status); 
}

The activator looks something like:

package com.irahul.example.myservicebundle; 
public class Activator implements BundleActivator { 
    public void start(BundleContext bundleContext){ 
       TransactionService txnSvc = new ....//an implementation of it 
       Map<String,String> metaProperties = new... 
       //define whatever meta data you want to register for service discovery 
       bundleContext.registerService("com.irahul.example.TransactionService", 
          txnSvc,metaProperties); 
    } 
}

Now over in the bundle ‘MyQuartzJob’ define a JobContext which can be injected with all the beans it requires to perform the Job.

package com.irahul.example.myquartzjob; 
public interface JobContext{ 
    void setTransactionService(TransactionService txnSvc); 
    TransactionService getTransactionService(); 
}

Implement the QuartzJobBean to get the application context like in Mark’s blog. Now in your application context create an empty bean with your JobContext implementation.

<!-- Job Context --> 
<bean id="jobContext" class="com.irahul.example.myquartzjob.JobContextImpl"></bean>

After that all that remains is the activator, which looks like:

package com.irahul.example.myquartzjob
public class Activator implements BundleActivator { 
    public void start(BundleContext bundleContext){ 
    // Initialize the Spring application context 
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext( 
         new String[]{"context.xml"}); 
    //get the service 
    ServiceReference txnRef = bundleContext. 
               getServiceReference("com.irahul.example.TransactionService"); 
               //you can search on additonal meta data filter as well 
    TransactionService txnService = (TransactionService)bundleContext.getService(txnRef); 
    //now get the spring bean as setup 
    JobContext jobContext = (JobContext)applicationContext.getBean("jobContext"); 
    jobContext.setTransactionService(txnService); 
}

Your Job now has the application context all setup and ready to go!