MuleSoft – Today’s Most used Opensource Enterprise Service Bus

Mule ESB runtime is light weight java based Enterprise Service Bus, which can be integrated between different platforms and languages that can connect fast and communicate between each other.Mule ESB can be deployed anywhere and can orchestrate real time events.

Mule ESB has got below capabilities.

Service creation and hosting — expose and host reusable services, using the ESB as a lightweight service container

Service mediation — shield services from message formats and protocols, separate
business logic from messaging, and enable location-independent service calls

Message routing — route, filter, aggregate, and re-sequence messages based on content and rules

Data transformation — exchange data across varying formats and transport protocols

Note: Image directly taken from https://www.mulesoft.com/resources/esb/what-mule-esb

Do I need an ESB?

Mule and other ESBs offer real value in scenarios where there are at least a few integration points or at least 3 applications to integrate. They are also well suited to scenarios where loose coupling, scalability and robustness are required.

Below is a quick ESB selection checklist. To read a much more comprehensive take on when to select an ESB, read this article written by MuleSoft founder and VP of Product Strategy Ross Mason: To ESB or not to ESB.

1. Are you integrating 3 or more applications/services?
2. Will you need to plug in more applications in the future?
3. Do you need to use more than one type of communication protocol?
4. Do you need message routing capabilities such as forking and aggregating message flows, or content-based routing?
5. Do you need to publish services for consumption by other applications?

Why Mule?

Mule is lightweight but highly scalable, allowing you to start small and connect more applications over time. The ESB manages all the interactions between applications and components transparently, regardless of whether they exist in the same virtual machine or over the Internet, and regardless of the underlying transport protocol used.

There are currently several commercial ESB implementations on the market. However, many of these provide limited functionality or are built on top of an existing application server or messaging server, locking you into that specific vendor. Mule is vendor-neutral, so different vendor implementations can plug in to it. You are never locked in to a specific vendor when you use Mule.

Note: the above two paras are directly taken from Mule website because i feel thats most apt content than i can describe.

In the next comming blog posts i will teach you how to start with mulesoft ESB.
Happy Mule 🙂

Advertisements

Oracle Fusion Middleware – “How to Query Oracle Coherence” ?

In my previous post “Oracle Fusion Middleware – Concepts of Oracle Coherence” i have explained how to preLoad cache which means get all the required details for the first time and put that into cache. Today i am going to explain how to query the cache once we have the details.

Querying in Oracle Coherence is obtained by set of Filters that the Coherence has provided us. Please be noted that queries apply only to currently cached data thus, the data set should be loaded entirely into cache before queries are performed(go through my preLoading concept in the previous post).

The concept of querying is based on the ValueExtractor interface. A value extractor is used to extract an attribute from a given object for querying Most developers need only the ReflectionExtractor implementation of this interface. The implementation uses reflection to extract an attribute from a value object by referring to a method name which is typically a getter method

Let me show you the example which is connected to my previous post:

/**
 * 
 */
package com.spark.coherence.cache.filters;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.spark.coherence.cache.repository.CacheRepository;
import com.spark.coherence.pof.beans.EmployeeBean;
import com.tangosol.util.Filter;
import com.tangosol.util.ValueExtractor;
import com.tangosol.util.extractor.ReflectionExtractor;
import com.tangosol.util.filter.EqualsFilter;
import com.tangosol.util.filter.GreaterEqualsFilter;
import com.tangosol.util.filter.GreaterFilter;

/**
 * @author Sony
 *
 */
public class EmployeeFilter {

	ValueExtractor valueExtractor;

	@SuppressWarnings("rawtypes")
	public EmployeeBean equalsFilter(String methodName, String methodParam) {
		valueExtractor = new ReflectionExtractor(methodName);
		Filter filter = new EqualsFilter(valueExtractor, methodParam);
		EmployeeBean person = null;
		for (Iterator iter = CacheRepository.getEmployeeCache().entrySet(filter).iterator(); iter.hasNext();) {
			Map.Entry entry = (Map.Entry) iter.next();
			Integer key = (Integer) entry.getKey();
			person = (EmployeeBean) entry.getValue();
		}
		return person;
	}
	
	@SuppressWarnings("rawtypes")
	public List<EmployeeBean> greaterThanFilter(String methodName, int methodParam) {
		valueExtractor = new ReflectionExtractor(methodName);
		Filter filter = new GreaterEqualsFilter(valueExtractor, methodParam);
		List<EmployeeBean> employeeBeans = new ArrayList<>();
		for (Iterator iter = CacheRepository.getEmployeeCache().entrySet(filter).iterator(); iter.hasNext();) {
			Map.Entry entry = (Map.Entry) iter.next();
			Integer key = (Integer) entry.getKey();
			EmployeeBean person = (EmployeeBean) entry.getValue();
			employeeBeans.add(person);
		}
		return employeeBeans;
	}

}

Happy Caching..Happy Coding 🙂

Calling REST Services using Spring’s REST Template

Hi guys, here is my 80th blog post which talks about calling Restful service using Spring’s “RestTemplate”. This codebase is executed under Spring 3.1 and 4.0 dependencies. The project structure looks as shown below.
RestTemplate_proj_struct

let me explain one scenario here, the calling REST service can return JSON Object or an XML Document back to consumer. it si up to the implementation how to convert JSON back to Java Object or convert Xml Back to Java.
We have many Marshallers and UnMarshallers available some of them are Jaxb2Marshaller,Jibx Marshaller, XStreamMarshaller,XmlBeanMarshaller..etc, i personally used Jaxb2Marshaller in this project. let us now dive into the code, there is no much explanation needed in the code, please follow the comments over the code blocks.

ConfigUtil.java

/**
 * 
 */
package com.spark.spring.rest.config;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.web.client.RestTemplate;

import com.spark.spring.rest.models.Customer;

/**
 * @author PavanKumar Mantha
 * 
 */
@Configuration
public class ConfigUtil {

	/**
	 * @return the RetTemplate Object. This method sets the marshaller object as
	 *         params to RestTemplate leveraging the marshalling capability to
	 *         the template.
	 */
	@Bean(name = "restTemplate")
	public RestTemplate getRestTemplate() {
		RestTemplate restTemplate = new RestTemplate();

		List<HttpMessageConverter<?>> converters = new ArrayList<>();
		converters.add(getMarshallingHttpMessageConverter());
		converters.add(new FormHttpMessageConverter());
		converters.add(new StringHttpMessageConverter());
		restTemplate.setMessageConverters(converters);
		return restTemplate;
	}

	/**
	 * @return MarshallingHttpMessageConverter object which is responsible for
	 *         marshalling and unMarshalling process
	 */
	@Bean(name = "marshallingHttpMessageConverter")
	public MarshallingHttpMessageConverter getMarshallingHttpMessageConverter() {

		MarshallingHttpMessageConverter marshallingHttpMessageConverter = new MarshallingHttpMessageConverter();
		marshallingHttpMessageConverter.setMarshaller(getJaxb2Marshaller());
		marshallingHttpMessageConverter.setUnmarshaller(getJaxb2Marshaller());
		return marshallingHttpMessageConverter;
	}

	/**
	 * @return Jaxb2Marshaller, this is the Jaxb2Marshaller object
	 */
	@Bean(name = "jaxb2Marshaller")
	public Jaxb2Marshaller getJaxb2Marshaller() {
		Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
		jaxb2Marshaller.setClassesToBeBound(Customer.class);
		return jaxb2Marshaller;
	}
}

RestServiceConsumer .java, RestService call

/**
 * 
 */
package com.spark.spring.rest.consume;

import org.springframework.web.client.RestTemplate;

import com.spark.spring.rest.models.Customer;

/**
 * @author PavanKumar Mantha
 *
 */
public class RestServiceConsumer {

	/**
	 * @param restTemplate, this is the exact call to the service
	 */
	public static void consumeService(RestTemplate restTemplate){
		// getting xml directly from the response as string
		String xml = restTemplate.getForObject("http://www.thomas-bayer.com/sqlrest/CUSTOMER/18/", String.class);
		System.out.println(xml);
		
		// unmarshalling xml string to java object using Jaxb
		Customer customer = restTemplate.getForObject("http://www.thomas-bayer.com/sqlrest/CUSTOMER/18/", Customer.class);
		System.out.println(customer.getFirstName());
	}

}

Customer.java, Jaxb mapping POJO

/**
 * 
 */
package com.spark.spring.rest.models;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * @author PavanKumar Mantha
 * 
 */
@XmlRootElement(name="CUSTOMER")
public class Customer {

	private String id;
	private String firstName;
	private String lastName;
	private String street;
	private String city;

	/**
	 * @return the id
	 */
	@XmlElement(name="ID")
	public String getId() {
		return id;
	}

	/**
	 * @param id
	 *            the id to set
	 */
	public void setId(String id) {
		this.id = id;
	}

	/**
	 * @return the firstName
	 */
	@XmlElement(name="FIRSTNAME")
	public String getFirstName() {
		return firstName;
	}

	/**
	 * @param firstName
	 *            the firstName to set
	 */
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	/**
	 * @return the lastName
	 */
	@XmlElement(name="LASTNAME")
	public String getLastName() {
		return lastName;
	}

	/**
	 * @param lastName
	 *            the lastName to set
	 */
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	/**
	 * @return the street
	 */
	@XmlElement(name="STREET")
	public String getStreet() {
		return street;
	}

	/**
	 * @param street
	 *            the street to set
	 */
	public void setStreet(String street) {
		this.street = street;
	}

	/**
	 * @return the city
	 */
	@XmlElement(name="CITY")
	public String getCity() {
		return city;
	}

	/**
	 * @param city
	 *            the city to set
	 */
	public void setCity(String city) {
		this.city = city;
	}

}

Main Method

/**
 * 
 */
package com.spark.spring.rest.test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.client.RestTemplate;

import com.spark.spring.rest.config.ConfigUtil;
import com.spark.spring.rest.consume.RestServiceConsumer;

/**
 * @author PavanKumar Mantha
 *
 */
public class TestRestApp {

	/**
	 * @param args
	 */
	
	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigUtil.class);
		RestServiceConsumer.consumeService((RestTemplate)applicationContext.getBean("restTemplate"));
	}

}

finally when we run the main method you should see the below output on the screen.
console

Happy RESTing…(RestTemplate) 🙂

BPM Workflow with Camunda BPM

Hi all,In my last post we have seen how to orchestrate BPEL process,but today we are going to see how we can develop a BPMN workflow using Camunda.This is also part of SOA stack,in my upcoming posts we will discuss about SOA technologies .

Briefly the below is the BPM work flow
Untitled

Please install the BPM modeling plugin and tools, also the Camunda BPM suite from the below link
download BPM modeling tools and BPM Suite

once we have all the software are in place, lets start our tutorial.
create a maven project and put all the dependencies in pom.xml as shown below.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.spark.camunda.bpm.process</groupId>
	<artifactId>TestBpmProcess</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>TestBpmProcess</name>
	<description>TestBpmProcess</description>

	<properties>
		<jdk.version>1.6</jdk.version>
	</properties>

	<dependencies>
		<!-- camunda engine dependency -->
		<dependency>
			<groupId>org.camunda.bpm</groupId>
			<artifactId>camunda-engine</artifactId>
			<version>7.1.0-Final</version>
			<scope>provided</scope>
		</dependency>

		<!-- camunda cdi beans -->
		<!-- <dependency> <groupId>org.camunda.bpm</groupId> <artifactId>camunda-engine-cdi</artifactId> 
			<version>7.1.0-Final</version> </dependency> -->

		<!-- provides a default EjbProcessApplication -->
		<!-- <dependency> <groupId>org.camunda.bpm.javaee</groupId> <artifactId>camunda-ejb-client</artifactId> 
			<version>7.1.0-Final</version> </dependency> -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.0.1</version>
			<scope>provided</scope>
		</dependency>
		
		<!-- Mysql dependency -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.6</version>
		</dependency>


		<!-- jars for email trigger -->
		<dependency>
			<groupId>javax.mail</groupId>
			<artifactId>mail</artifactId>
			<version>1.4.7</version>
		</dependency>
		<dependency>
			<groupId>org.glassfish.extras</groupId>
			<artifactId>javaee</artifactId>
			<version>3.1.1</version>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.3</version>
				<configuration>
					<failOnMissingWebXml>false</failOnMissingWebXml>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>${jdk.version}</source>
					<target>${jdk.version}</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

once we have the dependency ready, lets start coding our logic, lets start writing the logic for initial task form as follows.


<form class="form-horizontal">
	<div class="control-group">
		<label class="control-label">Customer ID</label>
		<div class="controls">
			<input form-field type="string" name="customerId" />
		</div>
	</div>
	<div class="control-group">
		<label class="control-label">Department</label>
		<div class="controls">
			<input form-field type="string" name="deptName" />
		</div>
	</div>
	<div class="control-group">
		<label class="control-label">Amount</label>
		<div class="controls">
			<input form-field type="number" name="amount" />
		</div>
	</div>
</form>

now lets map this task form to the start task of our BPM process as shown below.
request-loan

Now lets write a class to process the request and assign it to the “ProcessRequest” “ServiceTask” as shown below.

/**
 * 
 */
package com.spark.camunda.bpm.loanapproval;

import java.util.Map;

import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;

/**
 * @author Sony
 * 
 */
public class ProcessRequestDeligate implements JavaDelegate {

	@Override
	public void execute(DelegateExecution delegateExecution) throws Exception {

		Map<String, Object> variables = delegateExecution.getVariables();
		if ("dept1".equalsIgnoreCase((String) variables.get("deptName"))) {
			delegateExecution.setVariable("deptName", (String) variables.get("deptName"));
			
		} else if ("dept2".equalsIgnoreCase((String) variables.get("deptName"))) {
			delegateExecution.setVariable("deptName", (String) variables.get("deptName"));
		}
	}

}

process-req

once done we need to decide the conditional flow for the exclusive gateway. this is shown below.

cond1

cond2

once the request is forwarded to human task based on the condition. Here the condition is the loan approval for a particular department(dept1,dept2) based on this the manager will approve the request for the respective department. lets write the task form for manager to approve the request as below.


<form class="form-horizontal">
	<div class="control-group">
		<label class="control-label">Customer ID</label>
		<div class="controls">
			<input form-field type="string" name="customerId" readonly="true" />
		</div>
	</div>
	<div class="control-group">
		<label class="control-label">Amount</label>
		<div class="controls">
			<input form-field type="number" name="amount" />
		</div>
	</div>
</form>

once the manager approves the loan request the requst gets persisted into database and a event mail gets triggered to the customer. please find the below is the persistence task logic

/**
 * 
 */
package com.spark.camunda.bpm.loanapproval;

import java.sql.Connection;
import java.sql.PreparedStatement;

import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;

import com.spark.camunda.bpm.factory.SqlConnectionFactory;

/**
 * @author Sony
 * 
 */
public class PersistenceRequestDeligate implements JavaDelegate {

	@Override
	public void execute(DelegateExecution delegateExecution) throws Exception {

		SqlConnectionFactory connectionFactory = SqlConnectionFactory
				.getFactoryObject();
		Connection connection = connectionFactory.getSqlConnection();
		PreparedStatement preparedStatement = null;
		String sql = "insert into loanprocess(customer_id,amount) values (?,?)";
		preparedStatement = connection.prepareStatement(sql);
		preparedStatement.setString(1,
				delegateExecution.getVariable("customerId").toString());
		preparedStatement.setString(2, delegateExecution.getVariable("amount")
				.toString());
		preparedStatement.executeUpdate();

		preparedStatement.close();
		connection.close();
	}

}

please find the below is the event mail triggering logic

/**
 * 
 */
package com.spark.camunda.bpm.loanapproval;

import java.util.Properties;
import java.util.logging.Logger;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;

/**
 * @author Sony
 * 
 */
public class SendLoanApprovalConfirmation implements JavaDelegate {

	private final static Logger LOGGER = Logger.getLogger("SendLoanApprovalConfirmation");
	
	@Override
	public void execute(DelegateExecution delegateExecution) throws Exception {

		Properties props = new Properties();
		props.put("mail.smtp.host", "smtp.gmail.com");
		props.put("mail.smtp.socketFactory.port", "465");
		props.put("mail.smtp.socketFactory.class",
				"javax.net.ssl.SSLSocketFactory");
		props.put("mail.smtp.auth", "true");
		props.put("mail.smtp.port", "465");

		Session session = Session.getDefaultInstance(props,
				new javax.mail.Authenticator() {
					protected PasswordAuthentication getPasswordAuthentication() {
						return new PasswordAuthentication("xxx@gmail.com",
								"password");
					}
				});

		try {

			Message message = new MimeMessage(session);
			message.setFrom(new InternetAddress("xxx@gmail.com"));
			message.setRecipients(Message.RecipientType.TO,
					InternetAddress.parse("xxx@gmail.com"));
			message.setSubject("Loan Approval from John");
			message.setText("Dear Applicant your loan has got approved,"
					+ "\n\n please collect your check for the requested amount of"+delegateExecution.getVariable("amount"));

			Transport.send(message);

			LOGGER.info("processing mail sent to customer ID:"+delegateExecution.getVariable("customerId"));

		} catch (MessagingException e) {
			throw new RuntimeException(e);
		}
	}

}

please run mvn clean install package, now a war gets generated. Please deploy this war into JBoss Application server deployments folder and now start the camunda cockpit application and camunda tasklist application as shown below.

cockpit

create an instance by logging with demo/demo into camunda/tasklist application as shown below, since the entered details are for dept1 the approval goes to “john”(manager of dept1).

loanapproval

now go and see the camunda/cockpit it shows the present status of the BPM work flow as shown below.
waitingforapproval

Now john needs to login into task list to approve his assigned tasks, once he approves a automated mai is triggered to the applicant as shown below.
approvebyjohn

thats all folks now you are ready to code your own BPMN processes using Camunda BPM suit and JBoss App Server.
Happy Camunda BPMN WorkFlows 🙂 Happy SOA 🙂

IF and Else in BPEL

Hi All, its long time i wrote on SOA technologies so this week end decided to write on BPEL again. In this post i will start explaining on how to create BPEL process programmatically rather using GUI tool (Drag and Drop).

First lets create BPEl project and process as explained below.

1. Create a new BPEL project named “BpelTest” by selecting File→New→Others→BPEL 2.0→BPEL Project. Select Next. Type the project name as “BpelTest”. Click Finish.

2. Create a new BPEL process file named “BpelTestProcess” by right clicking on the BpelTest/bpelContent folder, select New→Others→BPEL 2.0→New BPEL Process File. Click Next. Fill in BPEL Process Name the string “BpelTestProcess”, and in the Namespace the string “http://spark.bpel.test.process&#8221;. Select the Template as Synchronous BPEL Process. Click Finish.

Note : Please rename the WSDL that is create as shown in the screen shot below.
image

Once the BPEL process is created let us change it as show as below. BPEL process file contain 5 major sections.
1. BPEL Process namespace.
2. Client WSDL import.
3. Specifying Partner Links.
4. Declaring Variables.
5. Orchestrating the Process Logic.

The Bpel Process name space and Client WSDL import are shown as below.

<bpel:process name="BpelTestProcess" targetNamespace="http://spark.bpel.test.process"
	suppressJoinFailure="yes" xmlns:tns="http://spark.bpel.test.process"
	xmlns:bpel="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema">

	<!-- Import the client WSDL -->
	<bpel:import location="BpelTestProcess.wsdl" namespace="http://spark.bpel.test.process"
		importType="http://schemas.xmlsoap.org/wsdl/" />

Now its time to specify the partner links and declare variables as shown below.

<bpel:partnerLinks>
		<bpel:partnerLink name="client" partnerLinkType="tns:BpelTestProcess"
			myRole="BpelTestProcessProvider" />
	</bpel:partnerLinks>


	<bpel:variables>
		<bpel:variable name="input" messageType="tns:BpelTestProcessRequestMessage" />
		<bpel:variable name="output" messageType="tns:BpelTestProcessResponseMessage" />
		<bpel:variable name="tmpInput" type="xsd:string"></bpel:variable>
	</bpel:variables>

Here we come with the exact orchestration logic.

<bpel:sequence name="main">
		<bpel:receive name="receiveInput" partnerLink="client"
			portType="tns:BpelTestProcess" operation="process" variable="input"
			createInstance="yes" />

		<bpel:assign validate="no" name="Assign">
			<bpel:copy>
				<bpel:from variable="input" part="payload"></bpel:from>
				<bpel:to variable="tmpInput"></bpel:to>
			</bpel:copy>
		</bpel:assign>
		<bpel:if>
			<bpel:condition>string($tmpInput)=string("sample passowrd")</bpel:condition>
			<bpel:assign name="working">
				<bpel:copy>
					<bpel:from>
						<bpel:literal>password matched</bpel:literal>
					</bpel:from>
					<bpel:to variable="output" part="payload"></bpel:to>
				</bpel:copy>
			</bpel:assign>
			<bpel:else>
				<bpel:assign name="failed">
					<bpel:copy>
						<bpel:from>
							<bpel:literal>Security Breach !</bpel:literal>
						</bpel:from>
						<bpel:to variable="output" part="payload"></bpel:to>
					</bpel:copy>
				</bpel:assign>
			</bpel:else>

		</bpel:if>
		<bpel:reply name="replyOutput" partnerLink="client"
			portType="tns:BpelTestProcess" operation="process" variable="output" />
	</bpel:sequence>

combining the sequence of xmls, final resultant BPEL Process code is as below.

<!-- BpelTestProcess BPEL Process [Generated by the Eclipse BPEL Designer] -->
<!-- Date: Sat May 24 19:07:43 IST 2014 -->
<bpel:process name="BpelTestProcess" targetNamespace="http://spark.bpel.test.process"
	suppressJoinFailure="yes" xmlns:tns="http://spark.bpel.test.process"
	xmlns:bpel="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema">

	<!-- Import the client WSDL -->
	<bpel:import location="BpelTestProcess.wsdl" namespace="http://spark.bpel.test.process"
		importType="http://schemas.xmlsoap.org/wsdl/" />


	<bpel:partnerLinks>
		<bpel:partnerLink name="client" partnerLinkType="tns:BpelTestProcess"
			myRole="BpelTestProcessProvider" />
	</bpel:partnerLinks>


	<bpel:variables>
		<bpel:variable name="input" messageType="tns:BpelTestProcessRequestMessage" />
		<bpel:variable name="output" messageType="tns:BpelTestProcessResponseMessage" />
		<bpel:variable name="tmpInput" type="xsd:string"></bpel:variable>
	</bpel:variables>


	<bpel:sequence name="main">
		<bpel:receive name="receiveInput" partnerLink="client"
			portType="tns:BpelTestProcess" operation="process" variable="input"
			createInstance="yes" />

		<bpel:assign validate="no" name="Assign">
			<bpel:copy>
				<bpel:from variable="input" part="payload"></bpel:from>
				<bpel:to variable="tmpInput"></bpel:to>
			</bpel:copy>
		</bpel:assign>
		<bpel:if>
			<bpel:condition>string($tmpInput)=string("06b81a04a1")</bpel:condition>
			<bpel:assign name="working">
				<bpel:copy>
					<bpel:from>
						<bpel:literal>password matched</bpel:literal>
					</bpel:from>
					<bpel:to variable="output" part="payload"></bpel:to>
				</bpel:copy>
			</bpel:assign>
			<bpel:else>
				<bpel:assign name="failed">
					<bpel:copy>
						<bpel:from>
							<bpel:literal>Security Breach !</bpel:literal>
						</bpel:from>
						<bpel:to variable="output" part="payload"></bpel:to>
					</bpel:copy>
				</bpel:assign>
			</bpel:else>

		</bpel:if>
		<bpel:reply name="replyOutput" partnerLink="client"
			portType="tns:BpelTestProcess" operation="process" variable="output" />
	</bpel:sequence>
</bpel:process>

the result of this process code in GUI looks as below
image2

Now lets code our client WSDl as follows

<?xml version="1.0"?>
<definitions name="BpelTestProcess"
        targetNamespace="http://spark.bpel.test.process"
        xmlns:tns="http://spark.bpel.test.process"
        xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype"
        xmlns="http://schemas.xmlsoap.org/wsdl/"
        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
        >

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     TYPE DEFINITION - List of types participating in this BPEL process 
     The BPEL Designer will generate default request and response types
     but you can define or import any XML Schema type and use them as part 
     of the message types.
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->    
    <types>
        <schema attributeFormDefault="unqualified" elementFormDefault="qualified" 
                targetNamespace="http://spark.bpel.test.process" 
                xmlns="http://www.w3.org/2001/XMLSchema">

            <element name="BpelTestProcessRequest">
                <complexType>
                    <sequence>
                        <element name="input" type="string"/>
                    </sequence>
                </complexType>
            </element>

            <element name="BpelTestProcessResponse">
                <complexType>
                    <sequence>
                        <element name="result" type="string"/>
                    </sequence>
                </complexType>
            </element>
        </schema>
    </types>


<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     MESSAGE TYPE DEFINITION - Definition of the message types used as 
     part of the port type defintions
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->    
    <message name="BpelTestProcessRequestMessage">
        <part name="payload" element="tns:BpelTestProcessRequest"/>
    </message>
    <message name="BpelTestProcessResponseMessage">
        <part name="payload" element="tns:BpelTestProcessResponse"/>
    </message>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     PORT TYPE DEFINITION - A port type groups a set of operations into
     a logical service unit.
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->    

    <!-- portType implemented by the BpelTestProcess BPEL process -->
    <portType name="BpelTestProcess">
        <operation name="process">
            <input  message="tns:BpelTestProcessRequestMessage" />
            <output message="tns:BpelTestProcessResponseMessage"/>
        </operation>
    </portType>   
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     PARTNER LINK TYPE DEFINITION
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->    
    <plnk:partnerLinkType name="BpelTestProcess">
        <plnk:role name="BpelTestProcessProvider" portType="tns:BpelTestProcess"/>
    </plnk:partnerLinkType>
    

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     BINDING DEFINITION - Defines the message format and protocol details
     for a web service.
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <binding name="BpelTestProcessBinding" type="tns:BpelTestProcess">
    	<soap:binding style="document"
    		transport="http://schemas.xmlsoap.org/soap/http" />
    	<operation name="process">
    		<soap:operation
    			soapAction="http://spark.bpel.test.process/process" />
    		<input>
    			<soap:body use="literal" />
    		</input>
    		<output>
    			<soap:body use="literal" />
    		</output>
    	</operation>
    </binding>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     SERVICE DEFINITION - A service groups a set of ports into
     a service unit.
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
    <service name="BpelTestProcessService">
    	<port name="BpelTestProcessPort" binding="tns:BpelTestProcessBinding">
    		<soap:address location="http://localhost:8080/BpelTestProcess" />
    	</port>
    </service>
</definitions>

also the deploy.xml looks as below.

<?xml version="1.0" encoding="UTF-8"?>
<deploy xmlns="http://www.apache.org/ode/schemas/dd/2007/03" xmlns:pns="http://ode/bpel/unit-test" xmlns:spark.bpel.test.process="http://spark.bpel.test.process" xmlns:wns="http://ode/bpel/unit-test.wsdl">
  <process name="spark.bpel.test.process:BpelTestProcess">
    <process-events generate="all"/>
    <provide partnerLink="client">
      <service name="spark.bpel.test.process:BpelTestProcessService" port="BpelTestProcessPort"/>
    </provide>
  </process>
</deploy>

Download WSO2 BPS server(BPEL Process Server) from this link : http://wso2.com/products/business-process-server/. once the server is downloaded we start it by running the wso2server.bat file located in “YourDownloadLocation\$BPS_Home\bin”. Once the server is up and running we can open the management console by typing the below URL “https://localhost:9443/carbon/admin/login.jsp&#8221; and login with the admin/admin user and password.

BpsLogin

now Zip only the source files, wsdl and deploy.xml and then upload the zip archieve to BPS server. in “Main->Process->add”, when the process gets successfully uploaded it will be shown under “Main -> Process -> list”
once the deployment is complete its time for us to test our BPEL process. BPS provice a tool internally to test the process or we can use SOAP UI to test it(I prefer to use BPS Tool ‘TryIt’)

click on the process name this will take us to the process specific page and there we can find TryIt tool. please follow the screens as below.

process after deploy

try it

once we click on the try it. this will open a testing tool where we can send request and response will be shown.
Testing

In my next write up we will see how to call Java Code from BPEL Process.
Happy BPEL coding 🙂

Using a Bean Data Control in Oracle ADF 11g

Hi All, here is small tutorial in Oracle ADF technology, how to use Data Controls. Basically there are three different types of data controls in ADF

  • Bean Data Control
  • URL service Data Control
  • PlaceHolder Data Control

In this tutorial i am going to elaborate on Bean Data control.this tutorial shows a simple databound application using JavaBeans and Oracle ADF Faces.

Step 1: Create a New Application and Project

From the main menu, choose File > New. In the New Gallery, expand the General category and select Applications. Then in the Items list, select Custom Application and click OK.

new_project

2. To follow along with the example, enter DataBoundADF as the application name and click Next.
3. Enter Model as the project na
4. Click Finish.

The Projects panel in the Application Navigator should look like this:
Model

Step 2: Create a Simple JavaBean Class

In the Application Navigator, right-click the project you just created and choose New > General > Java Class, then click OK.

new_javaclass

2.In the Create Java Class dialog, enter Contact as the class name, and com.spark.adf.tutorial as the package name. Accept the default values and click OK.

3.In the source editor, add code to create a simple JavaBean class.

package com.spark.adf.tutorial;

/**
 * @author Pavan Kumar Mantha
 */
public class Contact {

    private String name;
    private String email;

    public Contact() {
        super();
    }

    public Contact(String name, String email) {
        this.name = name;
        this.email = email;
    }

    /**
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     *
     * @return
     */
    public String getName() {
        return name;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getEmail() {
        return email;
    }
}

Click saveall icon Save All to save your work.

In the Application Navigator, you should see Contact.java in the com.spark.adf.tutorial package in the Application Sources folder.

Step 3: Create a Service Class

In the Application Navigator, right-click the Model project and choose New > General > Java Class, then click OK.

In the Create Java Class dialog, enter AddressBook as the class name. Accept the package name as com.spark.adf.tutorial.service, and the remaining default values, then click OK.

3.In the source editor, add code to create a collection Java class.
Delete all the generated code and replace with the following code:

package com.spark.adf.tutorial.service;


import com.spark.adf.tutorial.Contact;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @author Pavan Kumar Mantha
 */
public class AddressBook {

    List<Contact> contacts = new ArrayList<Contact>();

    public AddressBook() {
        super();
        contacts.add(new Contact("Steve", "steve@acme.org"));
        contacts.add(new Contact("Charles", "cyoung@acme.org"));
        contacts.add(new Contact("Karl", "kheint@acme.org"));
        contacts.add(new Contact("Mik", "mik_meir@acme.org"));
        contacts.add(new Contact("Yvonne", "yvonne_yvonne@acme.org"));
        contacts.add(new Contact("Sung", "superstar001@acme.org"));
        contacts.add(new Contact("Shailyn", "spatellina@acme.org"));
        contacts.add(new Contact("John", "jjb@acme.org"));
        contacts.add(new Contact("Ricky", "rmartz@acme.org"));
        contacts.add(new Contact("Shaoling", "shaoling@acme.org"));
        contacts.add(new Contact("Olga", "olga077@acme.org"));
        contacts.add(new Contact("Ron", "regert@acme.org"));
        contacts.add(new Contact("Juan", "jperen@acme.org"));
        contacts.add(new Contact("Uday", "udaykum@acme.org"));
        contacts.add(new Contact("Amin", "amin@acme.org"));
        contacts.add(new Contact("Sati", "sparek@acme.org"));
        contacts.add(new Contact("Kal", "kalyane.kushnane@acme.org"));
        contacts.add(new Contact("Prakash", "prakash01@acme.org"));
    }

    public List<Contact> findAllContacts() {
        return contacts;
    }

    public List<Contact> findContactByName(String name) {

        String namePattern = ".*" + (name != null ? name.toUpperCase() : "") + ".*";
        List<Contact> l_contacts = new ArrayList<Contact>();
        for (Contact contact : contacts) {
            if (Pattern.matches(namePattern, contact.getName().toUpperCase())) {
                l_contacts.add(contact);
            }
        }
        return l_contacts;
    }
}

4. Click saveall icon Save All to save your work.

Step 4: Create a Data Control for the Service Class
1. In the Application Navigator, right-click AddressBook.java and choose Create Data Control.

DataControls

2.In the Bean Data Control Interface Chooser dialog, click OK without selecting an option.

JDeveloper adds the data control definition file (DataControls.dcx ) to the project, and opens the file in the overview editor.
dcx_overview

3.In the Application Navigator, expand the Data Controls panel, then expand AddressBook.
DataControls

Step 5: Create a JSF Page

1. From the main menu, choose File > New > General > Projects > Custom Project, then click OK.

new_genproj

2. Enter View as the project name. Then select ADF Faces from the Available list and shuttle icon shuttle it to the Selected list.

3. Click Finish.
You should see the View project in the Application Navigator.

4. In the Application Navigator, right-click the View project and choose New > Web Tier > JSF/Facelets > Page, then click OK

5. In the Create JSF Page dialog, enter ContactList.jsf as the file name. Make sure Facelets is the selected document type.

6. On the Page Layout page, select Blank Page. On the Managed Bean page, select Do Not Automatically Expose UI Components in a Managed Bean.

7. Click OK.
By default JDeveloper displays the new JSF Facelets page in the visual editor.

8. In the Component Palette, ADF Faces page, Layout panel, drag borderlayout icon Panel Stretch Layout and drop it on the blank page in the visual editor.

When you drag the component to the visual editor, you should see a target rectangle with the name Form on the page; this means the component you are dragging will be inserted inside that target component.

9. click save all icon to save the work.

Step 6: Bind an ADF Faces Table Component to the Service Bean
1. In the Data Controls panel, expand AddressBook, then expand findAllContacts().

dcpalette3

2. Click and drag Contact to the center facet on the page in the visual editor. From the Create context menu, choose Table > ADF Read-only Table.

createcontextmenu

3. In the Edit Table Columns dialog, select Enable Sorting.edittablecols

4. Accept the default values and click OK.
The page in the visual editor should look similar to this:

tableineditor

5.In the Application Navigator, right-click ContactList.jsf and choose Run.

If the Create Default Domain dialog displays, enter the default password, for example weblogic1, in the Password and Confirm Password fields, then click OK.

The page in the browser should look similar to this:
tableinbrowser1

I will teach how to bind “Bind to a Parameterized Method and a Parameter” in my next post.
Happy ADF data binding. 🙂

Implementing Oracle Coherence Cache in WebApplications

Hi All, in past i have written one article regarding oracle coherence cache and its simple implementation. from past couple of months we are implementing coherence in our project and i thought to put its implementation here, so lets start with the topic. lets create a database table as below

create table product(product_id varchar2(5),product_name varchar2(50),unit_price varchar2(5),quantity varchar2(5));

prior to creating this example you need to have the coherence and weblogic installed here(code is tested with coherence 3.7 and weblogic 12c)

create a dynamic web project in eclipse and put coherence.jar as dependent lib, which acts as coherence server inside the weblogic application server.
proj_struct

Now lets design the form/page to insert the details
Note: here i am using the servlet 3.0 api and to get the database connection i used the @Resource injection(JSR specification)

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<script scr="js/jquery.js"></script>
<script>
	$(document).ready(function() {
		if (!("autofocus" in document.createElement("input"))) {
			$("#q").focus();
		}
	});
</script>
</head>
<body>
	<form action="writetoCache" method="post">
	<table>
		<tr>
			<td>Product ID:</td>
			<td><input name="prod_id" id="prodid" autofocus required></td>
		</tr>
		<tr>
			<td>Product Name:</td>
			<td><input name="productName" id="name" required></td>
		</tr>
		<tr>
			<td>Unit Price:</td>
			<td><input name="unitPrice" id="unit_price"></td>
		</tr>
		<tr>
			<td>Total Quantity:</td>
			<td><input name="totQty" id="totQty"></td>
		</tr>
		<tr>
			<td>
				<input type="submit" value="SaveDetails">
			</td>
		</tr>
	</table>
		 
	</form>
</body>
</html>

Now lets write the controller for this above JSP, the aim of this controller is to write the data to database and cache server as well

package com.spark.coherence.cache.controller;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;

/**
 * Servlet implementation class WriteToCacheController
 */
@WebServlet("/writetoCache")
public class WriteToCacheController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Resource(name = "oracleDS")
	DataSource dataSource;

	Connection connection;
	PreparedStatement preparedStatement;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public WriteToCacheController() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub

		String productId = request.getParameter("prod_id");
		String productName = request.getParameter("productName");
		String unitPrice = request.getParameter("unitPrice");
		String Qunatity = request.getParameter("totQty");
		String sql = "insert into product values(?,?,?,?)";
		try {
			connection = dataSource.getConnection();
			System.out.println("-------------- Connection Closed Status: "
					+ connection.isClosed() + " ------------------");
			preparedStatement = connection.prepareStatement(sql);
			preparedStatement.setString(1, productId);
			preparedStatement.setString(2, productName);
			preparedStatement.setString(3, unitPrice);
			preparedStatement.setString(4, Qunatity);

			preparedStatement.execute();
			writeToCache(productId, productName, unitPrice, Qunatity);
			
			RequestDispatcher requestDispatcher = request.getRequestDispatcher("getRecord.jsp");
			requestDispatcher.forward(request, response);

		} catch (SQLException e) {
			System.out
					.println("--------------------------Exception no record insert into Database !---------------------");
			e.printStackTrace();
		}
		
		
	}

	/**
	 * @param productId
	 * @param productName
	 * @param unitPrice
	 * @param Qunatity
	 */
	public void writeToCache(String productId, String productName,
			String unitPrice, String Qunatity) {

		CacheFactory.ensureCluster();
		NamedCache namedCache = CacheFactory.getCache("product");
		System.out.println("connected to cluster: "
				+ CacheFactory.getCluster().getClusterName()
				+ " With cache name " + namedCache.getCacheName());

		Map<String, String> dbObject = new HashMap<String, String>();
		dbObject.put("productId", productId);
		dbObject.put("productName", productName);
		dbObject.put("unitPrice", unitPrice);
		dbObject.put("quantity", Qunatity);

		if (namedCache.get(productId) == null) {
			namedCache.put(productId, dbObject);
		}

		System.out
				.println("------------- Object got cached ! -----------------");
		
	}
	
}

Once we are done with the insertion of data to database and cache, now its time to fetch the data either from database or cache. here the logic is if data is available in cache the controller pull data from cache if not it will pull from database and also update cache with the latest data so that next time it will from cache but not from database.

<%@page import="java.util.Map"%>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	<form action="readCache" method="post">
		<table>
			<tr>
				<td>Product ID:</td>
				<td><input name="prod_id" id="prodid" autofocus required></td>
			</tr>
			<tr>
				<td><input type="submit" value="getDetails"></td>
			</tr>
		</table>
	</form>

	<%
		Map cacheObject = (Map) session.getAttribute("cacheObj");
		if (cacheObject != null) {
	%>
	<table>
		<thead>
			<tr>
				<td>Product ID</td>
				<td>Product Name</td>
				<td>Unit Price</td>
				<td>Quantity Ordered</td>
			</tr>
		</thead>
		<tbody>
			<tr>
				<td><%=cacheObject.get("productId")%></td>
				<td><%=cacheObject.get("productName")%></td>
				<td><%=cacheObject.get("unitPrice")%></td>
				<td><%=cacheObject.get("quantity")%></td>
			</tr>
		</tbody>
	</table>

	<%
		}
	%>
</body>
</html>

ReadFromCacheController.java:

/**
 * 
 */
package com.spark.coherence.cache.controller;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.sql.DataSource;

import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;

/**
 * @author Sony
 * 
 */
@WebServlet("/readCache")
public class ReadFromCacheController extends HttpServlet {

	@Resource(name = "oracleDS")
	DataSource dataSource;

	Connection connection;
	PreparedStatement preparedStatement;
	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		super.doGet(req, resp);
	}

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		CacheFactory.ensureCluster();
		NamedCache namedCache = CacheFactory.getCache("product");
		
		String productId = request.getParameter("prod_id");
		HttpSession httpSession = request.getSession();
		Map<String, String> cacheObject = (Map)namedCache.get(productId);
		
		if(cacheObject != null){
			System.out.println("----------- Read from cache -------------");
			httpSession.setAttribute("cacheObj", cacheObject);
			RequestDispatcher requestDispatcher = request.getRequestDispatcher("getRecord.jsp");
			requestDispatcher.forward(request, response);
		}else{
			System.out.println("----------- Read from db and update cache -------------");
			httpSession.setAttribute("cacheObj", readFromDatabase(productId));
			RequestDispatcher requestDispatcher = request.getRequestDispatcher("getRecord.jsp");
			requestDispatcher.forward(request, response);
		}
	}
	
	public Map<String, String> readFromDatabase(String productId){
		
		String sql = "select * from product where product_id = ?";
		Map<String, String> dbObject = new HashMap<String, String>();
		
		try {
			connection = dataSource.getConnection();
			preparedStatement = connection.prepareStatement(sql);
			preparedStatement.setString(1, productId);
			ResultSet resultSet = preparedStatement.executeQuery();
			
			while (resultSet.next()) {
				dbObject.put("productId", resultSet.getString("product_id"));
				dbObject.put("productName", resultSet.getString("product_name"));
				dbObject.put("unitPrice", resultSet.getString("unit_price"));
				dbObject.put("quantity", resultSet.getString("quantity"));
			}
			
		}catch(SQLException sqlException){
			sqlException.printStackTrace();
		}
		writeToCache(dbObject,productId);
		return dbObject;
	}
	
	/**
	 * @param productId
	 * @param productName
	 * @param unitPrice
	 * @param Qunatity
	 */
	public void writeToCache(Map<String, String> dbObject,String productId) {

		CacheFactory.ensureCluster();
		NamedCache namedCache = CacheFactory.getCache("product");
		
		if (namedCache.get(productId) == null) {
			namedCache.put(productId, dbObject);
		}
		
	}
}

now that all coding is done now here is some config related to project, first i have implemented a ServletListener
for notifying contextDestroyed,contextInitialized events

now in order to connect with our coherence server the following two config files are required.

coherence-config.xml

<?xml version="1.0"?>
<!DOCTYPE cache-config SYSTEM "cache-config.dtd">
<cache-config>
    <caching-scheme-mapping>
        <cache-mapping>
            <cache-name>product</cache-name>
            <scheme-name>example-distributed</scheme-name>
        </cache-mapping>
    </caching-scheme-mapping>
 
    <caching-schemes>
        <distributed-scheme>
            <scheme-name>example-distributed</scheme-name>
            <service-name>DistributedCache</service-name>
            <backing-map-scheme>
                <local-scheme />
            </backing-map-scheme>
            <autostart>true</autostart>
        </distributed-scheme>
    </caching-schemes>
</cache-config>

tangosol-coherence-override.xml

<?xml version="1.0" encoding="UTF-8"?>
<coherence
	xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config http://xmlns.oracle.com/coherence/coherence-operational-config/1.2/coherence-operational-config.xsd">
	<cluster-config>
		<member-identity>
			<cluster-name>MyCluster</cluster-name>
		</member-identity>
		<unicast-listener>
			<address system-property="tangosol.coherence.localhost">192.168.0.100</address>
			<port system-property="tangosol.coherence.localport">8088</port>
		</unicast-listener>
		<multicast-listener>
			<time-to-live system-property="tangosol.coherence.ttl">60</time-to-live>
		</multicast-listener>
	</cluster-config>

	<configurable-cache-factory-config>
		<init-params>
			<init-param>
				<param-type>java.lang.String</param-type>
				<param-value system-property="tangosol.coherence.cacheconfig">
					coherence-cache-config.xml
				</param-value>
			</init-param>
		</init-params>
	</configurable-cache-factory-config>
</coherence>

Now as a final step lets run the application by deploying to weblogic server and below are the screen shots.

landing-page

now fill the details and submit the form and it should look as shown.

after-save

If suppose we query any record that is not available in cache it should get that from database and update cache as shown below.
read_and_update

if you query any record that is available in cache, it should directly read from cache and it will not hit database.
read_direct_cache

Advantage of implementing cache technology is, it will drastically improve the performance of the applications.
Happy cache 🙂