My favorites | Sign in
Project Logo
                
Search
for
Updated Mar 17, 2008 by aestevezjimenez
Labels: Featured, Phase-Implementation
TransformServicesIntoSemantics  

Transform Standard Services into Semantic Services or Smart Agents

There are several ways to create a Semantic Service or transforming a standard one using jServiceRules: annotations, Spring, just java code or a combination of them. Also there are some support classes to ease the process but is not mandatory to use them.

First Case Scenario

POJO Service, support classes, annotations and Spring.

Maybe the fastest way to do it is using the support classes + annotations (jdk 1.5+). Consult the javadocs for a complete reference of annotations and support classes.

So let's say that you have a complex InvoiceService that needs to process rules or semantics and it is being created by a spring context (to create spring contexts the support class SpringContextFactory can be used).

public class InvoiceService {
}

<beans>
<bean id="invoiceService" class="org.jsemantic.servicerules.examples.energy.services.InvoiceService"/>
</beans>

First Step

Extend the AbstractSemanticService support class and annotate the service using the @SemanticService annotation.

@SemanticService(rulesFile="org/jsemantic/support/examples/energy/tariff.drl")

public class InvoiceService extends AbstractSemanticService {
}

@SemanticService is the main annotation class for the Semantic Service configuration. It's mandatory to use this annotation before any other one can be used ( SpringExternalContext,SessionVariables..). This annotation only can be used at a class level.

In order to configure a Semantic Service a rules file must be provided. The Semantic Service is stateless by default.To configure a stateful SemanticService the stateless parameter must be set to false.

In this case we provide the tariff.drl rules file.

The AbstractSemanticService class can be inherited by the services to get instances of the SemanticSession without having to inject a SemanticSessionFactory. In other words, it becomes a Semantic Service on the fly. This is not mandatory, and if you don't like using this bit of glue code you can provide the SemanticSessionFactory yourself. Also, it provides some helper methods (execute, getInstance).

Second Step

Process the annotations.

<beans>
<bean id="beanPostProcessor" 	class="org.jservicerules.support.spring.SemanticSessionBeanPostProcessor"/>

<bean id="invoiceService" class="org.jsemantic.servicerules.examples.energy.services.InvoiceService"/>
</beans>

The annotations must be processed in some way and if a Spring context is being used, the option of choice is using the SemanticSessionBeanPostProcessor support class.

Third Step

Write the semantic method.

	public Invoice createInvoice(Customer customer, MeterReading reading) {
		Collection results = session.execute(customer.getTariff());
		Tariff tariff = (Tariff) results.iterator().next(); 
		return invoice;
	}

As we are using the AbstractSemanticService support class we can take advantage of the support methods provided.

getInstance():SemanticSession returns an instance of the SemanticSession.

execute(facts:Object):Collection get an instance of the SemanticSession, evaluates the rules / semantics, dispose the session and return the results.

If the method is just evaluating some rules you can use the execute helper method and just return the results like the example. If you need to do something more complex just get an instance of the SemanticSession using getInstance().

Second Case Scenario.

POJO Service, StatelessSemanticService support class and Spring.

This time we need just a simple service that evaluates if a collection of numbers are even or odd. This could be a pure Semantic Service as it won't have more methods or more complex processing. For that matter you could use the StatelessSemanticService or StatefulSemanticService instead of writing a custom service.

First Step.

Declare the Semantic Service in the Spring context file, passing the rules files to the constructor.

<beans>
		
<bean id="evenService" class="org.jservicerules.support.semanticservice.StatelessSemanticService">	
	<constructor-arg type="java.lang.String" value="org/jsemantic/support/examples/even/even.drl"/>
</bean>
	
</beans>

Second Step.

Now that the service is available in the Spring context it can be retrieved and used:

ApplicationContext ctx = SpringContextFactory
.getClassPathApplicationContexFactory("org/jsemantic/support/examples/even/services.xml");

StatelessSemanticService service = (StatelessSemanticService) ctx.getBean("evenService");
Collection results = service.execute(getFacts());

Third Case Scenario.

POJO Service and Spring.

In this case scenario, we need again a SemanticService that evaluates a collection of numbers to discriminate if they are even or odd, but we don't want to use the support classes though. Therefore, we need to setup a SemanticSessionFactory and the dependencies that we may need (as an ExternalContext, KnowledgeDatabase or Session Variables).

First Step.

Setup the SemanticSessionFactory and the dependencies.

<beans>

<bean id="semanticSessionFactory" 	class="org.jsemantic.servicerules.drools.session.factory.SemanticSessionFactoryImpl">
	<constructor-arg type="java.lang.String" value="org/jsemantic/servicerules/support/par-impar.drl"/>
	<property name=”externalContext” ref =”context”/>
</bean>
	
<bean id="context" class="org.jservicerules.support.spring.SpringExternalContextImpl"> 
	<constructor-arg type="java.lang.String" value="org/jsemantic/servicerules/support/services.xml"/>
</bean>
</beans>

In this case the SemanticSessionFactory has a External Context associated that is also Spring based. For that matter the SpringExternalContextImpl support class is used, passing the context file in the constructor. This context is useful to access other services or classes, external to the SemanticSession.

Second Step.

Write the custom Semantic Service adding the SemanticSessionFactory as a dependency.

public class EvenService {

	private SemanticSessionFactory semanticSessionFactory = null;

	public Collection check(Collection numbers) {
		SemanticSession session = semanticSessionFactory.getInstance();

		Collection results = session.execute(numbers);

		session.dispose();
		session = null;
		return results;
	}

	public void semanticSessionFactory(SemanticSessionFactory 	semanticSessionFactory){
		this.semanticSessionFactory = semanticSessionFactory:
	} 
}

Third Step.

Inject the SemanticSessionFactory into the service bean:

<bean id="evenService class="org.jsemantic.servicerules.examples.EvenService">
	<property name="semanticSessionFactory" ref="semanticSessionFactory"/>
</bean>

And that's all, now the new Semantic Service is ready to roll!.


Sign in to add a comment
Hosted by Google Code