On the bright side the text is well written in American English. It is well organized, full of helpful images of the older JDeveloper 11.1.1.2 version, tutorials and hands on practice. The setup instructions are accurate, detailed and the full source code is available online too.
On the dark side, the text is full of marketing lecture, whole chapters of promoting the suite, using rather banal and boring expressions of the type: "best of breed software" and so on. What is worse is that instead of warning the reader of potential hazards, which might risk a project's outcome, the authors seem to prefer to conceal the product defects.
Consider for example chapter 10. On page 254 it reads: "The next chapter provides instructions on running and testing the process." But what follows is Using Process Composer, neither running nor testing the application. What is more, a defect is hidden here: if one follows the relevant OTN online tutorials to proceed on his own, one hits on a bug, mentioned here. For the JDeveloper 11.1.1.4 user the process becomes eventually visible in BPM Workspace in Application panel, only if one restarts the application server; which is rather unacceptable for production deployments.
All in all, the book offers a spherical hands on introduction to the BPMN suite, including ADF (sadly only business components, no EJB's) and other relevant technologies by insiders, that is oracle employees. However, a more pragmatic approach to acknowledging defects and providing workarounds, if possible, would be ideal! Furthermore, a word about the myth of developing via the oracle SOA platform, without writing any Java code, which oracle marketing endorsed. After all, Mr Piotr Bazan summarizes so right, what the man in the street thinks about it: "Have to say I've never worked with such buggy tools where every step brings a new problem." Isn't that the reasons that JDeveloper related jobs are so hard to find worldwide on the one hand, and the salaries offered are way more than the average on the other?
Showing posts with label SOA. Show all posts
Showing posts with label SOA. Show all posts
Friday, 18 November 2011
Thursday, 8 September 2011
The Java SOA cookbook, by Eben Hewitt
On the bright side the cook book is well written, in American English, with some spelling errors.The error page of the book presents at the moment only unconfirmed errata:
http://oreilly.com/catalog/errataunconfirmed.csp?isbn=9780596520731
The book consists of a series of useful stand alone ...dishes; articles structured like this: specific problem, relevant solution, discussion of java code, criticism and alternatives. The reader may not study the book from the start of the menu to the end page sequentially, one might well consult the book about everyday tasks, ie finding a specific file in jarred libraries in linux, and only that. The ...chef expresses his opinion openly about purity of ingredients, ie using cookies is not ReST style programming, uses mainly open source tools to cook; such as Eclipse, Netbeans, Glassfish, .Net clients and some weblogic, but sadly for oracle fans, no flavour of JDeveloper at all! However, the author is not prejudiced against oracle products, as he praises the enterprise service bus.
On the dark side, some of the recipes are incomplete, probably due to space restrictions, meaning that sometimes the input to a servlet is not dynamic; fed by a database but static, hard coded values in a constructor of a convenience class. Moreover, the source code for each chapter offered on line is all pasted in a single file, not separate class files, thus finding the snippet you need can be time consuming.
All in all, this is a very useful cookbook, presenting advanced java version 1.6 code, practical solutions to real life problems, excluding design patterns. It offers plenty of food for thought, as it tries to answer a daily question asked by the vast majority of women, developers and chefs for centuries: what shall we cook today? Bon Appetit ladies and gentlemen!
http://oreilly.com/catalog/errataunconfirmed.csp?isbn=9780596520731
The book consists of a series of useful stand alone ...dishes; articles structured like this: specific problem, relevant solution, discussion of java code, criticism and alternatives. The reader may not study the book from the start of the menu to the end page sequentially, one might well consult the book about everyday tasks, ie finding a specific file in jarred libraries in linux, and only that. The ...chef expresses his opinion openly about purity of ingredients, ie using cookies is not ReST style programming, uses mainly open source tools to cook; such as Eclipse, Netbeans, Glassfish, .Net clients and some weblogic, but sadly for oracle fans, no flavour of JDeveloper at all! However, the author is not prejudiced against oracle products, as he praises the enterprise service bus.
On the dark side, some of the recipes are incomplete, probably due to space restrictions, meaning that sometimes the input to a servlet is not dynamic; fed by a database but static, hard coded values in a constructor of a convenience class. Moreover, the source code for each chapter offered on line is all pasted in a single file, not separate class files, thus finding the snippet you need can be time consuming.
All in all, this is a very useful cookbook, presenting advanced java version 1.6 code, practical solutions to real life problems, excluding design patterns. It offers plenty of food for thought, as it tries to answer a daily question asked by the vast majority of women, developers and chefs for centuries: what shall we cook today? Bon Appetit ladies and gentlemen!
Tuesday, 23 August 2011
Providing the model layer for a ReSTful web service
In this new article we shall discuss about implementing the model layer for a simple REST style web service, presented in a book authored by Eben Hewitt, called SOA Cookbook. In example 8-1 the author presents a plain servlet which draws hard coded values from a pojo called ProductCatalog. The XML values returned in the browser are the ones that are statically hard coded in the pojo's constructor. The original idea to extend the example, was to provide dynamic data from querying a database. Providing an entity bean for the Product and a stateless ejb 3 as a facade to query, seemed as a straightforward suggestion. As far as java 1.6 and JDeveloper 11.1.2 was concerned, that was merely wishful thinking!
The first exception deprived me of using directly the entity manager to access the db:
com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
javax.persistence.EntityManager is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at javax.persistence.EntityManager
at public javax.persistence.EntityManager com.soacookbook.ProductCatalog.entityManager
at com.soacookbook.ProductCatalog
javax.persistence.EntityManager does not have a no-arg default constructor.
this problem is related to the following location:
at javax.persistence.EntityManager
at public javax.persistence.EntityManager com.soacookbook.ProductCatalog.entityManager
at com.soacookbook.ProductCatalog
The most I could do this way was to access the db using a EJB client. The EJB code won't be displayed for brevity! Although I have received a warning that samplecode.oracle.com in its current form is being decommissioned on November 1st, 2011, the full source code can be found here, and is given as usual, without any guarantee of support, etc.
The view layer for now, is to remain as is!
The original code for the servlet from the aforementioned book, which was to remain intact, follows:
package com.soacookbook.web;
import com.soacookbook.ProductCatalog;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
public class SimpleRestServlet extends HttpServlet {
private static final String CONTENT_TYPE = "text/xml; charset=UTF-8";
private static final String DOC_TYPE = null;
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
public SimpleRestServlet() {
super();
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
System.out.println("DoGet invoked on RESTful service.");
ProductCatalog catalog = new ProductCatalog();
Source xmlSource = asXml(catalog);
ServletOutputStream out = response.getOutputStream();
response.setContentType("text/xml");
StreamResult st = new StreamResult(out);
try {
Transformer t = TransformerFactory.newInstance().newTransformer();
t.transform(xmlSource, st);
} catch (Exception e) {
throw new ServletException(e);
}
System.out.println("All done.");
}
private static Source asXml(ProductCatalog pc) throws ServletException {
System.out.println("Marshalling...");
Source source = null;
Document doc = null;
try {
JAXBContext ctx = JAXBContext.newInstance(ProductCatalog.class);
Marshaller m = ctx.createMarshaller();
DocumentBuilder parser =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
doc = parser.newDocument();
System.out.println("Products=" + pc);
m.marshal(pc, doc);
System.out.println("Marshalled catalog to XML.");
} catch (JAXBException je) {
throw new ServletException(je);
} catch (ParserConfigurationException pce) {
throw new ServletException(pce);
}
source = new DOMSource(doc);
System.out.println("Returning XML source.");
return source;
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
doGet(request, response);
}
}
The model layer with the dynamic query:
The table script as generated by JDeveloper 11.1.2:
CREATE TABLE "FUSIONEJB3"."PRODUCT"
(
"ID" VARCHAR2(255 BYTE) NOT NULL ENABLE,
"PRICE" NUMBER(19,4),
"NAME" VARCHAR2(255 BYTE),
PRIMARY KEY ("ID") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "USERS" ENABLE
)
SEGMENT CREATION IMMEDIATE PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE
(
INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT
)
TABLESPACE "USERS" ;
Impressive, isn't it? Next populate the table with sample data.
REM INSERTING into PRODUCT
Insert into PRODUCT (ID,PRICE,NAME) values ('GermanBonds',50,'Euro BRD Bonds');
Insert into PRODUCT (ID,PRICE,NAME) values ('USShares ',20,'US dollar mutual fund common shares');
The Product entity follows next:
package com.soacookbook.entities;
import java.io.Serializable;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.xml.bind.annotation.XmlType;
@XmlType
@Entity
@NamedQueries( { @NamedQuery(name = "Product.findAll",
query = "select o from Product o") })
public class Product implements Serializable {
private String id;
private String name;
private BigDecimal price;
public Product() {
}
public Product(String id, String name, BigDecimal price) {
this.id = id;
this.name = name;
this.price = price;
}
@Id
@Column(nullable = false)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
}
Although the first thought was to preserve the original working source code provided by the book author, some modifications were necessary. The final form of ProductCatalog follows:
package com.soacookbook;
import com.soacookbook.client.ProductCatalogSEClient;
import com.soacookbook.entities.Product;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class ProductCatalog {
private List<Product> products;
public ProductCatalog() {
super();
ProductCatalogSEClient productCatalogSEClient = new ProductCatalogSEClient();
products = productCatalogSEClient.getAllProducts();
}
//Don't you dare, no other getter there!
public void setProducts(List<Product> products) {
this.products = products;
}
}
Had you dared to generate an accessor, this would be the exception:
Application-managed EntityManagers, outside the Java EE container, save the day!
The first successful attempt to access the db was via the Java SE client:
package com.soacookbook.client;
import com.soacookbook.ProductCatalog;
import com.soacookbook.entities.Product;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class ProductCatalogSEClient {
private EntityManager entityManager;
private EntityManagerFactory entityManagerFactory;
private Hashtable emProps = new Hashtable();
public ProductCatalogSEClient() {
super();
}
public static void main(String[] args) {
ProductCatalogSEClient productCatalogSEClient = new ProductCatalogSEClient();
List<Product> products = productCatalogSEClient.getAllProducts();
Iterator i = products.iterator();
while (i.hasNext())
{
Product product = (Product) i.next();
System.out.println("Id:"+ product.getId() +" Name:"+product.getName()
+ " price " + product.getPrice());
}
}
public List<Product> getAllProducts(){
List<Product> products= null;
try {
entityManagerFactory =
Persistence.createEntityManagerFactory("JavaSEClient");
// not the same with example8-1 !
entityManager = entityManagerFactory.createEntityManager(emProps);
Query query = entityManager.createNamedQuery("Product.findAll");
products=query.getResultList();
} catch (Exception e) {
// TODO: Add catch code
e.printStackTrace();
} finally {
entityManager.close();
entityManagerFactory.close();
}
return products;
}
}
A second introduction to EE is superfluous: no more user credentials please!
However, if one copied the working properties for the SE client and pasted to the EE edition unit:
Internal Exception: java.sql.SQLException: User: fusionEJB3, failed to be authenticated.
Error Code: 0
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:309)
at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:138)
at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:94)
at org.eclipse.persistence.sessions.DatasourceLogin.connectToDatasource(DatasourceLogin.java:162)
The correct persistence.xml has no user credentials for the EJB client, unlike the java SE one:
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="1.0">
<persistence-unit name="example8-1">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/fusionEJB3</jta-data-source>
<class>com.soacookbook.entities.Product</class>
<properties>
<property name="eclipselink.target-server" value="WebLogic_10"/>
<property name="eclipselink.target-database" value="Oracle"/>
<property name="eclipselink.logging.level" value="ALL"/>
</properties>
</persistence-unit>
<persistence-unit name="JavaSEClient" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.soacookbook.entities.Product</class>
<properties>
<property name="eclipselink.target-server" value="WebLogic_10"/>
<property name="eclipselink.target-database" value="Oracle"/>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
<property name="javax.persistence.jdbc.password" value="fusionEJB3"/>
<property name="javax.persistence.jdbc.user" value="fusionEJB3"/>
<property name="eclipselink.logging.level" value="ALL"/>
<property name="eclipselink.orm.validate.schema" value="true"/>
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@hera:1521:orcl"/>
</properties>
</persistence-unit>
</persistence>
Finally, if one types: http://localhost:7101/example8-1/Products
the XML datagram appears:
<productCatalog>
<products><id>GermanBonds</id><name>Euro BRD Bonds</name><price>50</price></products>
<products><id>USShares </id><name>US dollar mutual fund common shares</name><price>20</price></products>
</productCatalog>
Making use of EJB 3.1 features via Netbeans 7.0.1
If one has the option of using the latest jdk 1.7, things can be far less complicated:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.soacookbook.facade;
import com.soacookbook.entities.Product;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author Nick
*/
@XmlRootElement
@Stateless
@LocalBean
public class ProductCatalog implements Serializable {
private static final long serialVersionUID = 1L;
@PersistenceContext(unitName="chapter8-1-ejbPU")
private EntityManager em;
private List<Product> products;
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public List<Product> getAllProducts() {
Query query = em.createNamedQuery("Product.findAll");
products = new ArrayList<Product>();
//logger.info("Query max results: "+ query.getMaxResults());
products = query.getResultList();
return products;
}
}
As far as the servlet is concerned, one may now use dependency injection:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.soacookbook.web;
import com.soacookbook.facade.ProductCatalog;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
/**
* @date Aug 26, 2011
* @author Nick
*/
public class SimpleRestServlet extends HttpServlet {
@EJB
private ProductCatalog catalog;
public void init(ServletConfig config) throws ServletException {
//try {
super.init(config);
/*Context context = new InitialContext();
catalog =
(ProductCatalog) context.lookup("java:global/chapter8-1/chapter8-1-ejb/ProductCatalog");*/
catalog.getAllProducts();
/* } catch (NamingException ex) {
Logger.getLogger(SimpleRestServlet.class.getName()).log(Level.SEVERE, null, ex);
}*/
}
public SimpleRestServlet() {
super();
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
try {
System.out.println("DoGet invoked on RESTful service.");
Source xmlSource = asXml(catalog);
ServletOutputStream out = response.getOutputStream();
response.setContentType("text/xml");
StreamResult st = new StreamResult(out);
try {
javax.xml.transform.Transformer t = TransformerFactory.newInstance().newTransformer();
t.transform(xmlSource, st);
} catch (Exception e) {
throw new ServletException(e);
}
System.out.println("All done.");
} catch (Exception ex) {
Logger.getLogger(SimpleRestServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static Source asXml(ProductCatalog pc) throws ServletException {
System.out.println("Marshalling...");
Source source = null;
Document doc = null;
try {
JAXBContext ctx = JAXBContext.newInstance(ProductCatalog.class);
Marshaller m = ctx.createMarshaller();
DocumentBuilder parser =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
doc = parser.newDocument();
System.out.println("Products=" + pc);
m.marshal(pc, doc);
System.out.println("Marshalled catalog to XML.");
} catch (JAXBException je) {
throw new ServletException(je);
} catch (ParserConfigurationException pce) {
throw new ServletException(pce);
}
source = new DOMSource(doc);
System.out.println("Returning XML source.");
return source;
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
doGet(request, response);
}
}
The first exception deprived me of using directly the entity manager to access the db:
com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
javax.persistence.EntityManager is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at javax.persistence.EntityManager
at public javax.persistence.EntityManager com.soacookbook.ProductCatalog.entityManager
at com.soacookbook.ProductCatalog
javax.persistence.EntityManager does not have a no-arg default constructor.
this problem is related to the following location:
at javax.persistence.EntityManager
at public javax.persistence.EntityManager com.soacookbook.ProductCatalog.entityManager
at com.soacookbook.ProductCatalog
The most I could do this way was to access the db using a EJB client. The EJB code won't be displayed for brevity! Although I have received a warning that samplecode.oracle.com in its current form is being decommissioned on November 1st, 2011, the full source code can be found here, and is given as usual, without any guarantee of support, etc.
The view layer for now, is to remain as is!
The original code for the servlet from the aforementioned book, which was to remain intact, follows:
package com.soacookbook.web;
import com.soacookbook.ProductCatalog;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
public class SimpleRestServlet extends HttpServlet {
private static final String CONTENT_TYPE = "text/xml; charset=UTF-8";
private static final String DOC_TYPE = null;
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
public SimpleRestServlet() {
super();
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
System.out.println("DoGet invoked on RESTful service.");
ProductCatalog catalog = new ProductCatalog();
Source xmlSource = asXml(catalog);
ServletOutputStream out = response.getOutputStream();
response.setContentType("text/xml");
StreamResult st = new StreamResult(out);
try {
Transformer t = TransformerFactory.newInstance().newTransformer();
t.transform(xmlSource, st);
} catch (Exception e) {
throw new ServletException(e);
}
System.out.println("All done.");
}
private static Source asXml(ProductCatalog pc) throws ServletException {
System.out.println("Marshalling...");
Source source = null;
Document doc = null;
try {
JAXBContext ctx = JAXBContext.newInstance(ProductCatalog.class);
Marshaller m = ctx.createMarshaller();
DocumentBuilder parser =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
doc = parser.newDocument();
System.out.println("Products=" + pc);
m.marshal(pc, doc);
System.out.println("Marshalled catalog to XML.");
} catch (JAXBException je) {
throw new ServletException(je);
} catch (ParserConfigurationException pce) {
throw new ServletException(pce);
}
source = new DOMSource(doc);
System.out.println("Returning XML source.");
return source;
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
doGet(request, response);
}
}
The model layer with the dynamic query:
The table script as generated by JDeveloper 11.1.2:
CREATE TABLE "FUSIONEJB3"."PRODUCT"
(
"ID" VARCHAR2(255 BYTE) NOT NULL ENABLE,
"PRICE" NUMBER(19,4),
"NAME" VARCHAR2(255 BYTE),
PRIMARY KEY ("ID") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "USERS" ENABLE
)
SEGMENT CREATION IMMEDIATE PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE
(
INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT
)
TABLESPACE "USERS" ;
Impressive, isn't it? Next populate the table with sample data.
REM INSERTING into PRODUCT
Insert into PRODUCT (ID,PRICE,NAME) values ('GermanBonds',50,'Euro BRD Bonds');
Insert into PRODUCT (ID,PRICE,NAME) values ('USShares ',20,'US dollar mutual fund common shares');
The Product entity follows next:
package com.soacookbook.entities;
import java.io.Serializable;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.xml.bind.annotation.XmlType;
@XmlType
@Entity
@NamedQueries( { @NamedQuery(name = "Product.findAll",
query = "select o from Product o") })
public class Product implements Serializable {
private String id;
private String name;
private BigDecimal price;
public Product() {
}
public Product(String id, String name, BigDecimal price) {
this.id = id;
this.name = name;
this.price = price;
}
@Id
@Column(nullable = false)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
}
Some more modifications of the book code:
Although the first thought was to preserve the original working source code provided by the book author, some modifications were necessary. The final form of ProductCatalog follows:
package com.soacookbook;
import com.soacookbook.client.ProductCatalogSEClient;
import com.soacookbook.entities.Product;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class ProductCatalog {
private List<Product> products;
public ProductCatalog() {
super();
ProductCatalogSEClient productCatalogSEClient = new ProductCatalogSEClient();
products = productCatalogSEClient.getAllProducts();
}
//Don't you dare, no other getter there!
public void setProducts(List<Product> products) {
this.products = products;
}
}
Had you dared to generate an accessor, this would be the exception:
com.sun.xml.bind.v2.runtime.IllegalAnnotationsException:
1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "products"
this problem is related to the following location:at
public java.util.List com.soacookbook.ProductCatalog.getProducts()
at com.soacookbook.ProductCatalog
this problem is related to the following location:at
public java.util.List com.soacookbook.ProductCatalog.products
at com.soacookbook.ProductCatalog
Application-managed EntityManagers, outside the Java EE container, save the day!
The first successful attempt to access the db was via the Java SE client:
package com.soacookbook.client;
import com.soacookbook.ProductCatalog;
import com.soacookbook.entities.Product;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class ProductCatalogSEClient {
private EntityManager entityManager;
private EntityManagerFactory entityManagerFactory;
private Hashtable emProps = new Hashtable();
public ProductCatalogSEClient() {
super();
}
public static void main(String[] args) {
ProductCatalogSEClient productCatalogSEClient = new ProductCatalogSEClient();
List<Product> products = productCatalogSEClient.getAllProducts();
Iterator i = products.iterator();
while (i.hasNext())
{
Product product = (Product) i.next();
System.out.println("Id:"+ product.getId() +" Name:"+product.getName()
+ " price " + product.getPrice());
}
}
public List<Product> getAllProducts(){
List<Product> products= null;
try {
entityManagerFactory =
Persistence.createEntityManagerFactory("JavaSEClient");
// not the same with example8-1 !
entityManager = entityManagerFactory.createEntityManager(emProps);
Query query = entityManager.createNamedQuery("Product.findAll");
products=query.getResultList();
} catch (Exception e) {
// TODO: Add catch code
e.printStackTrace();
} finally {
entityManager.close();
entityManagerFactory.close();
}
return products;
}
}
A second introduction to EE is superfluous: no more user credentials please!
However, if one copied the working properties for the SE client and pasted to the EE edition unit:
Internal Exception: java.sql.SQLException: User: fusionEJB3, failed to be authenticated.
Error Code: 0
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:309)
at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:138)
at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:94)
at org.eclipse.persistence.sessions.DatasourceLogin.connectToDatasource(DatasourceLogin.java:162)
The correct persistence.xml has no user credentials for the EJB client, unlike the java SE one:
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="1.0">
<persistence-unit name="example8-1">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/fusionEJB3</jta-data-source>
<class>com.soacookbook.entities.Product</class>
<properties>
<property name="eclipselink.target-server" value="WebLogic_10"/>
<property name="eclipselink.target-database" value="Oracle"/>
<property name="eclipselink.logging.level" value="ALL"/>
</properties>
</persistence-unit>
<persistence-unit name="JavaSEClient" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.soacookbook.entities.Product</class>
<properties>
<property name="eclipselink.target-server" value="WebLogic_10"/>
<property name="eclipselink.target-database" value="Oracle"/>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
<property name="javax.persistence.jdbc.password" value="fusionEJB3"/>
<property name="javax.persistence.jdbc.user" value="fusionEJB3"/>
<property name="eclipselink.logging.level" value="ALL"/>
<property name="eclipselink.orm.validate.schema" value="true"/>
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@hera:1521:orcl"/>
</properties>
</persistence-unit>
</persistence>
Finally, if one types: http://localhost:7101/example8-1/Products
the XML datagram appears:
<productCatalog>
<products><id>GermanBonds</id><name>Euro BRD Bonds</name><price>50</price></products>
<products><id>USShares </id><name>US dollar mutual fund common shares</name><price>20</price></products>
</productCatalog>
Making use of EJB 3.1 features via Netbeans 7.0.1
If one has the option of using the latest jdk 1.7, things can be far less complicated:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.soacookbook.facade;
import com.soacookbook.entities.Product;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author Nick
*/
@XmlRootElement
@Stateless
@LocalBean
public class ProductCatalog implements Serializable {
private static final long serialVersionUID = 1L;
@PersistenceContext(unitName="chapter8-1-ejbPU")
private EntityManager em;
private List<Product> products;
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public List<Product> getAllProducts() {
Query query = em.createNamedQuery("Product.findAll");
products = new ArrayList<Product>();
//logger.info("Query max results: "+ query.getMaxResults());
products = query.getResultList();
return products;
}
}
As far as the servlet is concerned, one may now use dependency injection:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.soacookbook.web;
import com.soacookbook.facade.ProductCatalog;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
/**
* @date Aug 26, 2011
* @author Nick
*/
public class SimpleRestServlet extends HttpServlet {
@EJB
private ProductCatalog catalog;
public void init(ServletConfig config) throws ServletException {
//try {
super.init(config);
/*Context context = new InitialContext();
catalog =
(ProductCatalog) context.lookup("java:global/chapter8-1/chapter8-1-ejb/ProductCatalog");*/
catalog.getAllProducts();
/* } catch (NamingException ex) {
Logger.getLogger(SimpleRestServlet.class.getName()).log(Level.SEVERE, null, ex);
}*/
}
public SimpleRestServlet() {
super();
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
try {
System.out.println("DoGet invoked on RESTful service.");
Source xmlSource = asXml(catalog);
ServletOutputStream out = response.getOutputStream();
response.setContentType("text/xml");
StreamResult st = new StreamResult(out);
try {
javax.xml.transform.Transformer t = TransformerFactory.newInstance().newTransformer();
t.transform(xmlSource, st);
} catch (Exception e) {
throw new ServletException(e);
}
System.out.println("All done.");
} catch (Exception ex) {
Logger.getLogger(SimpleRestServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static Source asXml(ProductCatalog pc) throws ServletException {
System.out.println("Marshalling...");
Source source = null;
Document doc = null;
try {
JAXBContext ctx = JAXBContext.newInstance(ProductCatalog.class);
Marshaller m = ctx.createMarshaller();
DocumentBuilder parser =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
doc = parser.newDocument();
System.out.println("Products=" + pc);
m.marshal(pc, doc);
System.out.println("Marshalled catalog to XML.");
} catch (JAXBException je) {
throw new ServletException(je);
} catch (ParserConfigurationException pce) {
throw new ServletException(pce);
}
source = new DOMSource(doc);
System.out.println("Returning XML source.");
return source;
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
doGet(request, response);
}
}
The morale of the story
Automatically generated code is not certain to be error free! It could cause run time exceptions in one IDE and specific application servers, ie Weblogic 10.3.5. In addition, migration to newer jdk versions are advantageous in most cases.
Even though some resources, excellent books, or tutorials such as those from the open source or Sun Netbeans community, are highly advanced, demonstrating the latest technology quite well, some are still incomplete. Given that oracle bred java EE developers have a different philosophy, i.e. are accustomed to setup db access as a first step, it is obvious that there is a huge gap in the way of thinking, between the two communities. This gap is for Sun Oracle press, university, marketing, or whatever other department to bridge. Until then, all incomplete open source recipes are candidates for some kind of integration coding exercise, or maybe not?
Automatically generated code is not certain to be error free! It could cause run time exceptions in one IDE and specific application servers, ie Weblogic 10.3.5. In addition, migration to newer jdk versions are advantageous in most cases.
Tuesday, 8 February 2011
Setting up Oracle 11g Complex Event Processing (CEP) server
The power of change in human life has long fascinated people. Babies are born, other people pass away, employees are made redundant, others get promoted. Businessmen, or whole states, go bankrupt, while others prosper. Even at war, a sudden change in weather can reverse the outcome of an initially easy to win, battle. The highly educated executives soon realized that staying informed about business, environmental, or other changes is of vital importance. That's why they keep asking for suitable dynamic IT tools, such as the business activity monitor (BAM), Business Intelligence (BI) and CEP.
In order to briefly compare the characteristics of each technology, I shall quote a few lines of text of the new SOA Handbook authored by Lucas Jellema: "BAM may seem very similar to Business Intelligence (BI) as you know it, and of course there is a lot of similarity if not overlap. The key differentiator is the real-time aspect of BAM, along with the active alerting responsibility it has. The scope in time of BAM dashboards is usually fairly short—up to hours or days—and would hardly ever cross the quarter or year boundary, whereas traditional BI tends to take a look at data from a more historic, longer-term perspective in a more passive way."
Let us now focus on CEP. The scope of CEP is less than a hour, in other words the data are as dynamic, as your processor power and network speed permit. As for detailed setup instructions of the CEP server one can visit:
http://theo.vanarem.nl/2010/05/27/getting-started-with-oracle-11g-complex-event-processing-cep/
Once you are done with the setup you start the Jetty server and receive the following messages in the Eclipse Galileo 3.5.2 log:
<8 Φεβ 2011 2:36:28 μμ EET> <Notice> <LibExt> <BEA-000000> <The extension library bundle "oracle.jdbc.driver" was started successfully>
<8 Φεβ 2011 2:36:30 μμ EET> <Warning> <Store> <BEA-280101> <The persistent file store "tlog_WlevServer" is forced to use buffered I/O and so may have significantly degraded performance. Either the OS/hardware environment does not support the chosen write policy or the native wlfileio library is missing. See store open log messages for the requested and final write policies. See the documentation on store synchronous write policy configuration for advice.>
<8 Φεβ 2011 2:36:30 μμ EET> <Notice> <LoggingService> <BEA-320400> <The log file C:\Oracle\Middleware\singleServer\user_projects\domains\ocep_domain\defaultserver\server.log will be rotated. Reopen the log file if tailing has stopped. This can happen on some platforms like Windows.>
<8 Φεβ 2011 2:36:30 μμ EET> <Notice> <LoggingService> <BEA-320401> <The log file has been rotated to C:\Oracle\Middleware\singleServer\user_projects\domains\ocep_domain\defaultserver\server.log00016. Log messages will continue to be logged in C:\Oracle\Middleware\singleServer\user_projects\domains\ocep_domain\defaultserver\server.log.>
<8 Φεβ 2011 2:36:35 μμ EET> <Notice> <evs4j> <BEA-2049007> <The cluster protocol is disabled>
<8 Φεβ 2011 2:36:35 μμ EET> <Notice> <BDBProvider> <BEA-2052004> <Created and registered BDBProvider default-provider>
<8 Φεβ 2011 2:36:38 μμ EET> <Notice> <Spring> <BEA-2047000> <The application context for "com.oracle.cep.cartridge.jdbc" was started successfully>
...
Exception in thread "RMI Reaper" java.lang.OutOfMemoryError: PermGen space
For the solution to the problem one needs to consult a useful post published back in 2009:
http://oraclebpelindepth.blogspot.com/2009/04/javalangoutofmemoryerror-permgen-space.html
in order to edit the file: startwlevs.cmd, found in C:\Oracle\Middleware\singleServer\user_projects\domains\ocep_domain\defaultserver as shown:
@ECHO OFF
@rem Copyright 2006 BEA Systems, Inc.
call ".\setDomainEnv.cmd" %*
set DGC_ARGS=-Xgcprio:deterministic -XpauseTarget=10ms
set DEBUG_ARGS=-Xdebug -Xrunjdwp:transport=dt_socket,address=8453,server=y,suspend=n
set DGC=
set DEBUG=
set ARGS=
:loop
if "%1" == "" goto endloop
if "%1" == "-dgc" (
set DGC=%DGC_ARGS%
shift
) else if "%1" == "-debug" (
set DEBUG=%DEBUG_ARGS%
shift
) else if "%1" == "-debugPort" (
set DEBUG=-Xdebug -Xrunjdwp:transport=dt_socket,address="%2",server=y,suspend=n
shift
shift
) else (
set ARGS=%ARGS% "%1"
shift
)
goto loop
:endloop
"%JAVA_HOME%\bin\java" %JVM_ARGS% %DGC% %DEBUG% -Dwlevs.home="%USER_INSTALL_DIR%" -Dbea.home="%BEA_HOME%" -jar "%USER_INSTALL_DIR%\bin\wlevs.jar" %ARGS%
:finish
I quote from the aforementioned blog:
"Is this the final solution?
Not really, if you keep loading loads of new processes or huge number of classes this might delay your Out Of Memory Error but will not fix it.
The only solution?
The only solution is to bounce the server once you see this error.
Where else?
This is a general issue faced by all sun java based servers. When huge number if class are loaded as part of an application, this error is expected."
In short, it seems that not all some things change, some are everlasting and prosperous, such as software defects, which persist against any change in time, wear, version or any attempt to fix! Are java bugs really immortal?
In order to briefly compare the characteristics of each technology, I shall quote a few lines of text of the new SOA Handbook authored by Lucas Jellema: "BAM may seem very similar to Business Intelligence (BI) as you know it, and of course there is a lot of similarity if not overlap. The key differentiator is the real-time aspect of BAM, along with the active alerting responsibility it has. The scope in time of BAM dashboards is usually fairly short—up to hours or days—and would hardly ever cross the quarter or year boundary, whereas traditional BI tends to take a look at data from a more historic, longer-term perspective in a more passive way."
Let us now focus on CEP. The scope of CEP is less than a hour, in other words the data are as dynamic, as your processor power and network speed permit. As for detailed setup instructions of the CEP server one can visit:
http://theo.vanarem.nl/2010/05/27/getting-started-with-oracle-11g-complex-event-processing-cep/
Once you are done with the setup you start the Jetty server and receive the following messages in the Eclipse Galileo 3.5.2 log:
<8 Φεβ 2011 2:36:28 μμ EET> <Notice> <LibExt> <BEA-000000> <The extension library bundle "oracle.jdbc.driver" was started successfully>
<8 Φεβ 2011 2:36:30 μμ EET> <Warning> <Store> <BEA-280101> <The persistent file store "tlog_WlevServer" is forced to use buffered I/O and so may have significantly degraded performance. Either the OS/hardware environment does not support the chosen write policy or the native wlfileio library is missing. See store open log messages for the requested and final write policies. See the documentation on store synchronous write policy configuration for advice.>
<8 Φεβ 2011 2:36:30 μμ EET> <Notice> <LoggingService> <BEA-320400> <The log file C:\Oracle\Middleware\singleServer\user_projects\domains\ocep_domain\defaultserver\server.log will be rotated. Reopen the log file if tailing has stopped. This can happen on some platforms like Windows.>
<8 Φεβ 2011 2:36:30 μμ EET> <Notice> <LoggingService> <BEA-320401> <The log file has been rotated to C:\Oracle\Middleware\singleServer\user_projects\domains\ocep_domain\defaultserver\server.log00016. Log messages will continue to be logged in C:\Oracle\Middleware\singleServer\user_projects\domains\ocep_domain\defaultserver\server.log.>
<8 Φεβ 2011 2:36:35 μμ EET> <Notice> <evs4j> <BEA-2049007> <The cluster protocol is disabled>
<8 Φεβ 2011 2:36:35 μμ EET> <Notice> <BDBProvider> <BEA-2052004> <Created and registered BDBProvider default-provider>
<8 Φεβ 2011 2:36:38 μμ EET> <Notice> <Spring> <BEA-2047000> <The application context for "com.oracle.cep.cartridge.jdbc" was started successfully>
...
Exception in thread "RMI Reaper" java.lang.OutOfMemoryError: PermGen space
For the solution to the problem one needs to consult a useful post published back in 2009:
http://oraclebpelindepth.blogspot.com/2009/04/javalangoutofmemoryerror-permgen-space.html
in order to edit the file: startwlevs.cmd, found in C:\Oracle\Middleware\singleServer\user_projects\domains\ocep_domain\defaultserver as shown:
@ECHO OFF
@rem Copyright 2006 BEA Systems, Inc.
call ".\setDomainEnv.cmd" %*
set DGC_ARGS=-Xgcprio:deterministic -XpauseTarget=10ms
set DEBUG_ARGS=-Xdebug -Xrunjdwp:transport=dt_socket,address=8453,server=y,suspend=n
set DGC=
set JVM_ARGS=-XX:MaxPermSize=1024m
set DEBUG=
set ARGS=
:loop
if "%1" == "" goto endloop
if "%1" == "-dgc" (
set DGC=%DGC_ARGS%
shift
) else if "%1" == "-debug" (
set DEBUG=%DEBUG_ARGS%
shift
) else if "%1" == "-debugPort" (
set DEBUG=-Xdebug -Xrunjdwp:transport=dt_socket,address="%2",server=y,suspend=n
shift
shift
) else (
set ARGS=%ARGS% "%1"
shift
)
goto loop
:endloop
"%JAVA_HOME%\bin\java" %JVM_ARGS% %DGC% %DEBUG% -Dwlevs.home="%USER_INSTALL_DIR%" -Dbea.home="%BEA_HOME%" -jar "%USER_INSTALL_DIR%\bin\wlevs.jar" %ARGS%
:finish
I quote from the aforementioned blog:
"Is this the final solution?
Not really, if you keep loading loads of new processes or huge number of classes this might delay your Out Of Memory Error but will not fix it.
The only solution?
The only solution is to bounce the server once you see this error.
Where else?
This is a general issue faced by all sun java based servers. When huge number if class are loaded as part of an application, this error is expected."
In short, it seems that not all some things change, some are everlasting and prosperous, such as software defects, which persist against any change in time, wear, version or any attempt to fix! Are java bugs really immortal?
Wednesday, 29 December 2010
Setting up Oracle service registry 11.1.1
db options screen shot |
Last time I attended the Oracle day in Athens, Greece, I was impressed by a presales consultant stating that the real difficulties of SOA projects arise not in the first project, but in the second. That is when there is already a prebuilt foundation of services, on which one needs to base the new applications of the second project. This is the time to prove whether the initial design is worth of the effort, time and money spent.You have guessed it right, it is all about agility, adaptability to business, or IT changes, and service reuse!
In this new post the installation traits of Oracle service registry 11.1.1 will be mentioned. No need to clarify the purpose of existence of a service registry within the scope of SOA in this post. You might consult the current SOA governance literature, take for instance chapter 9 of: http://nickaiva.blogspot.com/2010/12/comments-on-ws-bpel-20-for-soa.html as an introduction. I quote some text: "In addition to reuse, a service registry can also be helpful when we need to migrate services from one server to the other. This can happen because of various reasons,
but one of the most common reasons is the migration between the development, test, and production environments. A service registry is also helpful when we need to version services and manage changes. With a service registry, we can also develop more loosely coupled composite applications, because we do not need to hard-code the service URLs. Rather, the application will resolve URLs at run time."
Let's now proceed with the setup. The first installation attempts failed with rather cryptic error messages. Well, another personality trait which is very important to programmers and pretty scarce to find, is not being too lazy to type a helpful error message, when exceptions occur. So, the technical data follow:
OS is windows 7 64bit, not officially tested by Oracle at present
DB version is 11.1.0.6.0 64bit
Java version 1.6.0_20 64bit
JDBC driver at C:\app\Nick\product\11.1.0\db_1\jdbc\lib\ojdbc6.jar
The log output follows:
Expanding C:\Users\Nick\Downloads\ofm_osr_generic_11.1.1.2.0_disk1_1of1\oracle-service-registry-11.1.1.jar to C:\Oracle\Middleware\registry111 ...
Building scripts ...
Platform is Windows
Preparing 'admin' account ...
Preparing account_list ...
Preparing permission_list ...
Preparing approval management ...
Creating standalone configuration ...
Java returned: 1
Installation failed. If accessible, see "C:\Oracle\Middleware\registry111\log\install.log".
To correct installation parameters and resume installation click Recovery.
Next come the contents of C:\Oracle\Middleware\registry111\log\install.log:
#
#Tue Dec 28 15:42:49 EET 2010
db.system.name.condition=oracle
install.server.operator.name=Oracle
oracle.database.admin.password=***
oracle.database.datafile=uddinode.dbf
oracle.server.host=hera
oracle.database.admin.user=system
install.server.smtp.port=25
oracle.database.password.confirmation=***
install.http.connector=8081
alldb.create.datasource.name=jdbc/registryDS
install.server.smtp.password.confirmation=***
install.server.admin.mail=nickaiva@
install.os.is.win.andcondition=true
create.desktop.icons=no
porting.standalone.http.port=8080
oracle.database.tablespace=uddinode
install.server.smtp.default.sender.name=
install.server.smtp.password=***
porting.https.use=yes
alldb.install.registry.name=Oracle Service Registry
account.backend.type.condition=database
install.server.smtp.title=
install.server.admin.name=admin
alldb.create.datasource.weblogic=no
security.ssl.password=***
alldb.install.demo.data=no
install.server.admin.password.confirmation=***
security.ssl.username=uddiadmin
dist.version=11.1.1
install.server.smtp.default.sender.email=
porting.standalone.https.port=8443
alldb.create.datasource=yes
alldb.jdbc.custom.uribox=no
install.type.condition=standalone
install.server.smtp.host=[ SMTP server hostname ]
alldb.install.demo.data.settings=
create.menu.items=yes
alldb.create.drop.condition=createComplete
oracle.database.name=orcl
install.directory=C\:\\Oracle\\Middleware
registry111
install.server.admin.password=***
oracle.server.port=1521
db.showall.condition=false
alldb.jdbc.custom.urifield=
alldb.jdbc.drivers.paths=C\:\\app\\Nick\\product\\11.1.0\\db_1\\jdbc\\lib
ojdbc6.jar
porting.hostname=hera
security.ssl.password.confirmation=***
porting.type.condition=jetty
install.server.smtp.account.name=
oracle.database.user=uddiuser
install.windows.menu=Oracle Service Registry 11.1.1
oracle.database.password=***
[echo] Expanding C:\Users\Nick\Downloads\ofm_osr_generic_11.1.1.2.0_disk1_1of1\oracle-service-registry-11.1.1.jar to C:\Oracle\Middleware\registry111 ...
[echo] Building scripts ...
[echo] Platform is Windows
[echo] Preparing 'admin' account ...
[echo] Preparing account_list ...
[echo] Preparing permission_list ...
[echo] Preparing approval management ...
[echo] Creating standalone configuration ...
[java] BUILD FAILED
[java] C:\Oracle\Middleware\registry111\etc\setup\database.xml:737: The following error occurred while executing this line:
[java] C:\Oracle\Middleware\registry111\etc\setup\database.xml:339: The following error occurred while executing this line:
[java] C:\Oracle\Middleware\registry111\etc\setup\database.xml:422: The following error occurred while executing this line:
[java] C:\Oracle\Middleware\registry111\etc\setup\database.xml:207: The following error occurred while executing this line:
[java] C:\Oracle\Middleware\registry111\etc\db\oracle\installOracleDB.xml:99: The following error occurred while executing this line:
[java] C:\Oracle\Middleware\registry111\etc\db\oracle\installOracleDB.xml:166: Java returned: 1
[java] Total time: 4 seconds
Java returned: 1
Installation failed. If accessible, see "C:\Oracle\Middleware\registry111\log\install.log".
To correct installation parameters and resume installation click Recovery.
However many times one tries, with the options selected as shown in the db options screen shot, the installation fails due to some build error of the db scripts. Although the installation appears to have failed, the db uddiuser schema has been actually created. On the contrary, some people report that one is better off to create the schema on his own, as you can see in the references. Thus, when one runs installation the next time, having selected an existing db schema "Connect to schema" option, all appears to go well. Well, not everything! If one uses jetty instead of weblogic server, the create data source option does not apply. Therefore, one needs to uncheck the selection, in order to avoid receiving a "Cannot obtain new connection" exception.
The morale of the story is quite obvious, if related to the introduction of the current post: the first time is just the basis, the second time is what matters most. Happy new year to you all!
Further references:
http://www.javamonamour.org/2010/05/trouble-installing-oracle-service.html
OSR - Oracle Service Registry won't create database datasource
Tuesday, 21 December 2010
Comments on WS-BPEL 2.0 for SOA Composite Application with Oracle SOA Suite 11g, by Matjaz B. Juric, Marcel Krizevnik
On the bright side, the text is written in American English, formal, well organized and neat, having the last sentence of each paragraph linking to the following one. Although the title sounds pretty familiar, the content of the book is actually about the newer version of BPEL 2.0. That's what makes this particular book unique, as the time of this writing. I quote: "Oracle SOA Suite 11g PS2 supports BPEL 2.0. However, BPEL 2.0 is only supported at runtime and not in JDeveloper. BPEL 2.0 support in Oracle SOA Suite 11g PS2 is not yet production ready, so by default, BPEL version 1.1 is used. However, we can write BPEL 2.0 code in text mode (graphical mode is currently not supported)." This book will help readers utilize BPM suite for integrating BPEL with BPMN. Readers will be able to explore BPEL 2.0 activities, loops, decisions, flow control, variables, scopes and other constructs that will enable them to develop BPEL processes. The authors dig into advanced BPEL topics, such as fault handlers, event handlers, compensation, concurrent activities, links, correlations, message properties, dynamic partner links, process lifecycle, and more. The text is accompanied by two online appendices about the syntax of the BPEL versions 1.1 and the newer 2.0, the full source code, in addition to a sample chapter and its table of contents, which can be found here. Furthermore, the authors use UML sequence, activity diagrams to describe the composite applications, which is useful to the analysts and designers and scarce to find in competitive books.
On the dark side, there are a few spelling errors, the first 3 chapters are rather tedious to read, since there is no hands on practice, nor questions and answers for the reader to exercise. The action starts in chapter 4 and forward on. However, there is only purely descriptive text, with no full, step by step detailed instructions how to build from scratch the application, or how to setup the SOA suite. In addition, parts of the application source code is given as is, i.e. java classes, without any explanation how it was created, or how to deploy it correctly; For example, EmployeeTravelStatus, in chapter 4, should perhaps be deployed as a shared library, or a stand alone application?
All in all, the book is a complete and detailed treatise on BPEL 2.0, presenting its origins, other BPEL servers available in the market such as tibco, exotic themes such as Oracle service registry, Business process architect, and so on. Its project is an application about employees travel requests and booking the cheapest available ticket offered by the airline companies, etc. The book is no introduction to BPEL, but of fairly advanced level, since drag and drop operations are rarely mentioned, the authors prefer to edit the source BPEL and XML code directly, which can be error prone, especially for beginners. Its source code is full of advanced java classes, so developing web services using java, XML basics, look like prerequisites.
Further references:
You can visit the book page at the publisher's site
Further references:
You can visit the book page at the publisher's site
Monday, 22 November 2010
SOA: Decoupling the database adapter service from the BPEL process
BPEL process |
Consider for instance a standard JEE web application which requires access to a database. Using the hard coded jdbc connection string to provide the connection details, requires editing the source code, compiling , testing and redeploying, when a new database is provided or the application needs to become distributed. On the other hand, using a jdbc data source, permits the reuse of the code only with modifying the relevant deployment descriptors by the web administrator. This analogy exists also in the example SOA application, which requires database access , and will be presented next.
composite.xml |
This semi decoupled situation is actually presented as an anti-paradigm or anti-pattern. That is, an example case, that you should avoid by all means, since you must abandon the simple drag and drop operations, you now need to manually edit the xml files to solve the problem of fully decoupling. The steps necessary to decouple the second db adapter follow in brief. The final bpel process we are to implement and the final composite.xml is shown:
final form of BPEL process |
final form of composite |
If you 'd rather not delve into the manually editing details, you can consider the following steps as optional, skip them and jump to the next horizontal line to read the two last paragraphs. This is a very long post after all!
Well, if you insist on going beyond drag and drop operations, here is a way of doing it:
First, start by creating the XSD definitions for the PatientDataService.xsd:
<schema targetNamespace="http://stmatthews.hospital.com/patient/PatientDataService"
xmlns:hospital="http://stmatthews.hospital.com/patient/PatientDataService"
xmlns="http://www.w3.org/2001/XMLSchema">
<element name="PatientDataServiceProcessRequest"
type="hospital:patientIdType" />
<element name="PatientDataServiceProcessResponse"
type="hospital:patientType"/>
<!--Add on the 2 following elements for decoupling-->
<element name="PatientRecord"
type="hospital:patientType"/>
<element name="PatientIdentifier"
type="hospital:patientIdType"/>
...
Based on those, it is easy to create the Mediator and its WSDL as shown.
Next, you need to edit the PatientRecordProvider.wsdl file, so that you don't get this screen shot when you wire the mediator to the db adapter, to the bpel process and later insert the new assign and the invoke activities:
old type is now wrong |
<?xml version= '1.0' encoding= 'UTF-8' ?>
<wsdl:definitions
name="PatientRecordProvider"
targetNamespace="http://stmatthews.hospital.com/patient/PatientDataService"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:inp1="http://stmatthews.hospital.com/patient/PatientDataService"
xmlns:tns="http://stmatthews.hospital.com/patient/PatientDataService"
xmlns:out1="http://stmatthews.hospital.com/patient/PatientDataService"
>
<wsdl:types>
<schema xmlns="http://www.w3.org/2001/XMLSchema" >
<import namespace="http://stmatthews.hospital.com/patient/PatientDataService" schemaLocation="xsd/PatientDataService.xsd" />
</schema>
<schema xmlns="http://www.w3.org/2001/XMLSchema" >
<import namespace="http://stmatthews.hospital.com/patient/PatientDataService" schemaLocation="xsd/PatientDataService.xsd" />
</schema>
</wsdl:types>
<!--replace RequestMessage with patientRecordRequestMessage
and refresh the variables in the assign and invoke windows
to get the patientIdentifier appear instead of the older patientQualifier -->
<wsdl:message name="patientRecordRequestMessage">
<wsdl:part name="request" element="inp1:PatientIdentifier"/>
</wsdl:message>
<wsdl:message name="replyMessage">
<wsdl:part name="reply" element="inp1:PatientRecord"/>
</wsdl:message>
<wsdl:portType name="patientDataServices_ptt">
<wsdl:operation name="getPatientRecord">
<wsdl:input message="inp1:patientRecordRequestMessage"/>
<wsdl:output message="inp1:replyMessage"/>
</wsdl:operation>
</wsdl:portType>
</wsdl:definitions>
Next you declare the new patientRecordRequestMessage type to be used, so:
Thus, you now get to this screen shot instead of the old, wrong one, which shows the patientIdentifier (ID):
The process goes on, you delete the old wire, the old invoke and assign activities, insert new as shown in the final form of the bpel picture, and edit their properties to define the parameters correctly, to avoid such failing build messages:
...
[scac] FATAL_ERROR: in PatientDataService.bpel(168): wrong messageType
[scac] messageType "{http://stmatthews.hospital.com/patient/PatientDataService}requestMessage" of variable "Invoke_PatientRecordProvider_getPatientRecord_InputVariable" does not match the expected messageType "{http://stmatthews.hospital.com/patient/PatientDataService}patientRecordRequestMessage" in <invoke>
[scac] Make sure the correct variable is used in invoke
BUILD FAILED
that is, if you follow the screen shots:
new invoke properties |
Delete the old transform, insert a new one and edit as shown:
Create the xsl mappings:
You end with deployment and testing the composite, as shown:
The question surely arises: is it really worth bothering to edit all those xml files, is it not error prone? I quote: "The Mediator has several functions that all help promote decoupling and agility. It maps from the canonical data structure to the potentially very specific schema for the adapter service, possibly including any value conversions that may be required. When the Database Adapter Service is replaced by a different service implementation, hence with new WSDL and XSD definitions, the BPEL process is unaffected, because the Mediator shields it from these changes. When the data is for some reason distributed over multiple databases, and based on some patient property we have to determine which of those databases to access, the Mediator will take care of this content-based routing. In addition, the Mediator can handle problems with availability of the database service, retrying calls or taking alternative steps. Moreover, the Mediator may present what is a synchronous service through an asynchronous interface, which allows a client such as a BPEL process to continue with other, parallel activities or to be dehydrated altogether to free up resources after the call is made, instead of blocking the thread waiting for the reply, which could take fairly long."
Finally, the gist of this post is: BPEL processes should never call to adapter services directly. There should always be a Mediator in between. Sooner or later the need to decouple will arise, if you design correctly straight from the beginning, you won't waste your time and effort. So, next time you are about to wire a database adapter, think twice!
Further references
http://oracle-fusion-blogs.com/oracle-fusion-osb-mediator/
Wednesday, 27 October 2010
Comments on Oracle SOA Suite 11g Handbook, by Lucas Jellema
On the bright side, the book offers a plethora of web resources, apart from the textbook itself. The online supplements are actually a way of previewing it by studying the material mentioned, before buying the book. The text is well organized with a few spelling errors. It delves deeply into XML code details, such as creating the xsd files and editing them. The historical review serves well as an introduction, presenting both the evolution of technologies and relevant acronyms, such as SLA, SCA and so on. Moreover, the step by step guidance offered, is most of the times, easy to understand and follow. Furthermore, some parts of the source code is available online, including the intermediate steps. The chapter about complex event processing is remarkable, however one needs Eclipse Galileo, not Helios, to follow the hands on guidance.
On the dark side, some sections are too long to read. Once you are done with the printed text, the online supplements must follow. Besides, the huge volume of information is often hard to manage, therefore rather messy. Some parts of text are duplicated, some others missing. For instance, on page 74 it reads: "Details for the configuration of JMS, JDBC, and UMS can be found online in Appendix C." which has been actually until recently missing. In chapter 7 some errors are reported, due to missing steps, or xsl files and a misleading image, but not yet confirmed. In addition, parts of the source code are missing, like the XML file SimplePatient.xsd mentioned on page 109. Moreover, some spelling errors are critical, omitting an 'a' from 'asynchronous', surely changes the meaning! Some crucial xpath expressions have typographical errors as well. Web services presented in the text such as ConsultWithHealthInsurers in chapter 11, are not implemented. Furthermore, in chapter 13, page 448: "The wiki provides configuration details for setting up a local e-mail server with these domains and accounts based on the JavaEmail project" but no such details actually existed until recently. Such errors, or missing information prevent the reader from completing the practice, build the necessary self confidence and continue. Unfortunately, the source code for chapters 10 and above has not been available until recently, due to broken links.The code for chapter 15 is still missing. Although most times the known bugs of soa suite are mentioned, this is not true for the ADF service data objects examples of chapter 20.
All in all, the text is of average quality, the author has striven to equally balance the theoretical and practical views of the subject. It offers an introduction to XML, XPath too, some of hands on practice. Hence, the book is definitely among the top choices for the reader who would like an introductory book, but clearly inferior to the Getting started with SOA 11g, as far as quality and precision of hands on practice is concerned. As far as quantity, the difference in number of pages speaks for itself!
On the dark side, some sections are too long to read. Once you are done with the printed text, the online supplements must follow. Besides, the huge volume of information is often hard to manage, therefore rather messy. Some parts of text are duplicated, some others missing. For instance, on page 74 it reads: "Details for the configuration of JMS, JDBC, and UMS can be found online in Appendix C." which has been actually until recently missing. In chapter 7 some errors are reported, due to missing steps, or xsl files and a misleading image, but not yet confirmed. In addition, parts of the source code are missing, like the XML file SimplePatient.xsd mentioned on page 109. Moreover, some spelling errors are critical, omitting an 'a' from 'asynchronous', surely changes the meaning! Some crucial xpath expressions have typographical errors as well. Web services presented in the text such as ConsultWithHealthInsurers in chapter 11, are not implemented. Furthermore, in chapter 13, page 448: "The wiki provides configuration details for setting up a local e-mail server with these domains and accounts based on the JavaEmail project" but no such details actually existed until recently. Such errors, or missing information prevent the reader from completing the practice, build the necessary self confidence and continue. Unfortunately, the source code for chapters 10 and above has not been available until recently, due to broken links.The code for chapter 15 is still missing. Although most times the known bugs of soa suite are mentioned, this is not true for the ADF service data objects examples of chapter 20.
All in all, the text is of average quality, the author has striven to equally balance the theoretical and practical views of the subject. It offers an introduction to XML, XPath too, some of hands on practice. Hence, the book is definitely among the top choices for the reader who would like an introductory book, but clearly inferior to the Getting started with SOA 11g, as far as quality and precision of hands on practice is concerned. As far as quantity, the difference in number of pages speaks for itself!
Monday, 18 October 2010
JDeveloper 11g: Making use of Http Analyzer for testing and debugging
Anyone who has developed a JEE or SOA application, sooner or later faces some kind of unexpected, or strange behaviour of the system under development. However helpful the audit process screens of the weblogic server, once you enter and submit the sometimes numerous input values, one is not allowed to tamper with the request values anymore; you just wait until you get hopefully a response, or an error. An interesting , but often overlooked, alternative is Http Analyzer. It lets you save some time, by copying the request so that you don't have to enter all values from scratch, you can edit the value of interest and resend your modified request. Let's see some specific examples.
In order to quickly set it up, you go to "Tools" menu and click on "Preferences" in JDeveloper 11g as shown in the image. You need to copy the "Listen on port" value, which is 8099. Next, you need to setup the browser of your choice. The images below show the screen shots for Mozilla Firefox, I suppose finding your way in IE or other browser won't be such an onerous task!
Again click on "Options", then on "Advanced", "Network" and lastly on "Settings" to reach the connection settings window as shown . You need to select "Manual proxy configuration", enter your computer name, and paste the port number you copied before, i.e 8099. The "No proxy for" section must not contain any entries, such as localhost, nor 127.0.0.1, because in that case Http Analyzer will only analyze your internet requests! When you are done with debugging, you might need to reenter here your old values. That means you need to save them, i.e in a new back up text file! For an alternative more elegant configuration using profiles, you can consult the JDeveloper documentation, by searching for"Configuring External Web Browsers"
In order to quickly set it up, you go to "Tools" menu and click on "Preferences" in JDeveloper 11g as shown in the image. You need to copy the "Listen on port" value, which is 8099. Next, you need to setup the browser of your choice. The images below show the screen shots for Mozilla Firefox, I suppose finding your way in IE or other browser won't be such an onerous task!
Again click on "Options", then on "Advanced", "Network" and lastly on "Settings" to reach the connection settings window as shown . You need to select "Manual proxy configuration", enter your computer name, and paste the port number you copied before, i.e 8099. The "No proxy for" section must not contain any entries, such as localhost, nor 127.0.0.1, because in that case Http Analyzer will only analyze your internet requests! When you are done with debugging, you might need to reenter here your old values. That means you need to save them, i.e in a new back up text file! For an alternative more elegant configuration using profiles, you can consult the JDeveloper documentation, by searching for"Configuring External Web Browsers"
Testing a trivial ADF form
Next, you start the application, using the "Run project" button, and click the "Start HTTP analyzer" button. The small form of the ADF ejb bidding application window appears. You should now see the output in the log window. If you enter the form values and submit, the HTTP analyzer captures all submitted values. You can now copy the request, edit only the bidder's name for instance, and resend.
Testing a plain SOA component
For the second example, you need to reenter your old settings to your browser(i.e. No proxy). The request values will be submitted by JDeveloper itself, by right clicking on the service, as shown.
Here a US stock exchange price in dollars, i.e. for OTE or GE, is converted into a different currency, i.e. EUR or GBP for British pounds. You can see the request and response values as well. As mentioned before, you need to copy the request, modify only where necessary and resubmit.
Although the examples given are deliberately simple, a small relevant quotation will be given, concerning the importance of retaining the input parameters, and another alternative as well. I quote from the Oracle SOA Suite 11g Developer's guide: "If you have a very complicated interface, you may not want to have to enter the parameter values every time you test the composite. In 10g, there was a facility to set a default input to a BPEL process. Unfortunately, there is no such facility for 11g composites. In order to avoid retyping complex inputs, the input can be saved to a file and then pasted into the test dialog every time...". Finally, if your needs are bigger, you might consider another alternative testing tool like SOAPUI which is available online.
Here a US stock exchange price in dollars, i.e. for OTE or GE, is converted into a different currency, i.e. EUR or GBP for British pounds. You can see the request and response values as well. As mentioned before, you need to copy the request, modify only where necessary and resubmit.
Although the examples given are deliberately simple, a small relevant quotation will be given, concerning the importance of retaining the input parameters, and another alternative as well. I quote from the Oracle SOA Suite 11g Developer's guide: "If you have a very complicated interface, you may not want to have to enter the parameter values every time you test the composite. In 10g, there was a facility to set a default input to a BPEL process. Unfortunately, there is no such facility for 11g composites. In order to avoid retyping complex inputs, the input can be saved to a file and then pasted into the test dialog every time...". Finally, if your needs are bigger, you might consider another alternative testing tool like SOAPUI which is available online.
Subscribe to:
Posts (Atom)