Enterprise JavaBeans - Part 6
Developing an N-tier EJB Application - Developing Session Beans
You can create a session bean by implementing the following steps:
The session bean we are about to develop acts as a client to a couple of entity beans and manages the workflow between these entities. Session beans can be also be used to create new entity instances and their data in the database. Our shopping cart session bean implemented in the following has methods to help the user to shop for various items.
Define the Home Interface
We begin by defining our home interface. Only one create method is defined to help us create session bean instances. The Listing 13 shows the CartHome interface definition.
package com.gopalan.Shop.Cart; import javax.ejb.*; import java.rmi.*; public interface CartHome extends EJBHome { Cart create () throws RemoteException, CreateException; }
Listing 13: The CartHome interface definition
Define the Remote Interface
Now to define the remote interface that will contain our business method interfaces. If you notice, we define two interfacescreateNewBook() and createNewAlbum() to help us create entity beans. We define methods like getBook()and getAlbum() to help us retrieve data. We define methods like addToBooksCart() and addToMusicCart() to help us build the shopping cart. The methods getNumberBooks(),getNumberAlbums(), getBooksTotal() getAlbumsTotal(),and getGrandTotal() help us get statistics we can provide to the user. Listing 14 shows the Cart Remote Interface.
package com.gopalan.Shop.Cart; import javax.ejb.*; import java.rmi.*; import java.util.*; import com.gopalan.Shop.Books.*; import com.gopalan.Shop.Music.*; public interface Cart extends EJBObject { public Books createNewBook (int isbn, String title, String authors, double price, int discount) throws RemoteException, CreateException; public Music createNewAlbum (int code, String album, String authors, double price, int discount) throws RemoteException, CreateException; public Books getBook (int isbn) throws RemoteException, FinderException; public Music getAlbum (int code) throws RemoteException, FinderException; public void addToBooksCart (int code) throws RemoteException; public void addToMusicCart (int code) throws RemoteException; public void flushBooksCart () throws RemoteException; public void flushMusicCart () throws RemoteException; public int getNumberBooks () throws RemoteException; public int getNumberAlbums () throws RemoteException; public double getBooksTotal () throws RemoteException; public double getAlbumsTotal () throws RemoteException; public double getGrandTotal () throws RemoteException; public Vector getBooksList () throws RemoteException; public Vector getMusicList () throws RemoteException; public Vector getBooksCart () throws RemoteException; public Vector getMusicCart () throws RemoteException; }
Listing 14: The Cart Remote interface definition
Implement the Session Bean
Our session bean invokes the home interfaces of two entity beansthe BooksBean and the MusicBean. The source code for the MusicBean, while not listed here, is similar to the BooksBean entity bean and is available on the accompanying CD along with all these sources. If you look at the setSessionContext()methods, you can see we get a reference to the home interface factory objects for the Books and Music bean. The setSessionContext() method is one of the first methods to be called when the container creates the session bean. This method also invokes our private init()method we use to initialize our data. Notice we cache data in the session bean. This ensures the entity bean is not invoked every time the client makes a call and minimizes our database access, thus, improving overall system performance. All the remote interfaces we defined for our business methods now have a body defined in the session bean.
When you read the listing, you find a certain ReturnSet class, which you will learn about soon.. The listing for the CartBean is shown in the Listing 15.
package com.gopalan.Shop.Cart; package com.gopalan.Shop.Cart; import java.rmi.*; import javax.ejb.*; import java.util.*; import com.gopalan.Shop.Books.*; import com.gopalan.Shop.Music.*; import com.gopalan.Shop.Cart.ReturnSet; public class CartBean implements SessionBean { SessionContext sessionContext; public BooksHome booksHome; public MusicHome musicHome; public Vector booksList = null, booksCart = null; public Vector musicList = null, musicCart = null; int totalBooks = 0, totalMusic = 0; double booksCost = 0, musicCost = 0, grandTotal = 0; void init () { booksList = new Vector (); booksCart = new Vector (); musicList = new Vector (); musicCart = new Vector (); ReturnSet result = null; for (int i=0; ;i++) { try{ BooksPK key = new BooksPK (i+1); Books found = booksHome.findByPrimaryKey (key); if (null == found) { break; } result = new ReturnSet (key.code, found.getTitle (), found.getAuthors (), found.getPrice (), found.getDiscount (), found.getDiscountedPrice ()); System.out.println ("isbn = "+ result.code + " Title = "+result.title+ " Authors = "+result.authors+ " Price = " + result.price); booksList.addElement (result); } catch (Exception e) { e.printStackTrace(); break; } } for (int i=0; ;i++) { try { MusicPK key = new MusicPK (i+1); Music found = musicHome.findByPrimaryKey (key); if (found == null) { break; } result = new ReturnSet (key.code, found.getAlbum (), found.getComposers (), found.getPrice (), found.getDiscount (), found.getDiscountedPrice ()); System.out.println ("code = "+ result.code + " Album = "+result.title+ " Composers = "+result.authors+ " Price = " + result.price); musicList.addElement (result); } catch (Exception e) { e.printStackTrace (); break; } } } // Implementation for all the Remote Interface business methods public Books createNewBook (int isbn, String title, String authors, double price, int discount) throws RemoteException, CreateException { Books book = booksHome.create (isbn, title, authors, price, discount); if (null != book) { booksList.addElement (new ReturnSet(isbn, title, authors, price, discount, book.getDiscountedPrice ())); } return book; } public Music createNewAlbum (int code, String album, String authors, double price, int discount) throws RemoteException, CreateException { Music music = musicHome.create (code, album, authors, price, discount); if (null != music) { musicList.addElement(new ReturnSet(code, album, authors, price, discount, music.getDiscountedPrice ())); } return music; } public void addToBooksCart (int isbn) throws RemoteException { try { Books book = getBook (isbn); if (null != book) { booksCart.addElement(new ReturnSet(isbn, book.getTitle (), book.getAuthors (), book.getPrice (), book.getDiscount (), book.getDiscountedPrice())); ++totalBooks; booksCost += book.getDiscountedPrice (); grandTotal+= book.getDiscountedPrice (); } } catch (Exception e) { e.printStackTrace (); } } public void flushBooksCart () throws RemoteException { grandTotal -= booksCost; totalBooks = 0; booksCost = 0; booksCart.removeAllElements (); } public void flushMusicCart () throws RemoteException { grandTotal -= musicCost; totalMusic = 0; musicCost = 0; musicCart.removeAllElements (); } public void addToMusicCart (int code) throws RemoteException { try { Music music = getAlbum (code); if (null != music) { musicCart.addElement(new ReturnSet(code, music.getAlbum (), music.getComposers (), music.getPrice (), music.getDiscount (), music.getDiscountedPrice())); ++totalMusic; musicCost += music.getDiscountedPrice (); grandTotal+= music.getDiscountedPrice (); } } catch (Exception e) { e.printStackTrace(); } } public Books getBook (int isbn) throws RemoteException, FinderException { return booksHome.findByPrimaryKey (new BooksPK (isbn)); } public Music getAlbum (int code) throws RemoteException, FinderException { return musicHome.findByPrimaryKey (new MusicPK (code)); } public Vector getBooksList () throws RemoteException { return booksList; } public Vector getMusicList () throws RemoteException { return musicList; } public Vector getBooksCart () throws RemoteException { return booksCart; } public Vector getMusicCart () throws RemoteException { return musicCart; } public int getNumberBooks () throws RemoteException { return totalBooks; } public int getNumberAlbums () throws RemoteException { return totalMusic; } public double getBooksTotal () throws RemoteException { return booksCost; } public double getAlbumsTotal () throws RemoteException { return musicCost; } public double getGrandTotal () throws RemoteException { return grandTotal; } // Implementation for all the Home Interface methods public void ejbCreate () throws RemoteException, CreateException { } // Implement all the mandatory methods required by the EJB Spec public void ejbActivate () throws RemoteException {} public void ejbPassivate () throws RemoteException {} public void ejbRemove () throws RemoteException {} public void setSessionContext (SessionContext context) throws RemoteException { sessionContext = context; try { booksHome = (BooksHome)Naming.lookup ("Books"); musicHome = (MusicHome)Naming.lookup ("Music"); init(); } catch (Exception ex) { throw new RemoteException ("Shop not found", ex); } } }
Listing 15: The CartBean enterprise bean implementation
To make working with vectors easier, we created a serializable ReturnSet class, which contains a member for each of the fields of the enterprise Bean in which we are interested. This enables us to store and retrieve each element of the Vector as a ReturnSet object. The listing for the ReturnSet class is shown in the Listing 16:
package com.gopalan.Shop.Cart; public class ReturnSet implements java.io.Serializable { public int code; public String title; public String authors; public double price; public int discount; public double ourPrice; public ReturnSet(int no, String name, String author, double cost, int disc, double cp) { code = no; title = name; authors = author; price = cost; discount = disc; ourPrice = cp; } }
Listing 16: The ReturnSet class definition
Compile the EJB Classes
You can now compile all the sources you developed as:
javac *.java
Declare the Deployment Properties
From here on, whatever we talk about is specific to the particular EJB server implementation. The EJBHome server requires we specify properties in four different files. These properties are used both in the container class generation and in deployment. We need to define the various properties that help you to generate the container classes. In a properties file, which we call Shop.ejbml, type in the Listing 17:
<!----------------------------------------------------------> <!------- Cart Session Bean ----------------> <!----------------------------------------------------------> <ejbml> <session-bean name="cart" descriptor="Cart/CartDeployment" package="com.gopalan.Shop.Cart" home="com.gopalan.Shop.Cart.CartHome" remote="com.gopalan.Shop.Cart.Cart" bean="com.gopalan.Shop.Cart.CartBean" type="stateful" timeout="3600" tx-attribute="TX_SUPPORTS" > </session-bean> </ejbml>
Listing 17: The Deployment Descriptors for the Cart EJB
The first few lines specify the name of our interfaces and that this is a session bean. We also specify our generated code should belong to the cup.chap8.Shop.Cart package.
Generate the Container Classes
The next step is to generate the container classes using the tools supplied by the EJB server/container vendor. When the entity and session beans are deployed, a number of container source and class files are generated with the following prefixes. A container is a set of classes generated by the deployment tool that manages an enterprise bean's persistence, transactional properties, and security. Now that our Shop.ejbml file is ready, we can generate and compile the container classes. For this we need to execute the HomeBase servers deployer tool. We do this as follows from the command line:
java com.ejbhome.Deployer .\conf\Shop.ejbml
We can now run the server as:
java com.ejbhome.Server
A snapshot of the console when the server is running and ready to receive client connections is shown in the following. The lines in boldface were the commands we typed in.
E:\>java com.ejbhome.Server
com.ejbhome.server.EnterpriseServer, initializing.
com.ejbhome.server.EnterpriseServer.fireContainerAdded() at (Compiled
Code)
com.ejbhome.VendorConfiguration.<init>() at (VendorConfiguration.java:57)
com.ejbhome.VendorConfiguration.getSystemCodeHelper() at (VendorConfiguration.java:174)
com.ejbhome.VendorConfiguration.getTransactionCodeHelper() at (VendorConfiguration.java:138)
com.ejbhome.VendorConfiguration.getCommsCodeHelper() at (VendorConfiguration.java:163)
com.ejbhome.VendorConfiguration.getTracingCodeHelper() at (VendorConfiguration.java:152)
com.ejbhome.VendorConfiguration.getPersistenceCodeHelper() at (VendorConfiguration.java:125)
com.ejbhome.VendorConfiguration.getSessionPassivationCodeHelper()
at (VendorConfiguration.java:185)
com.ejbhome.VendorConfiguration.getVendorPrefix() at (VendorConfiguration.java:100)
starting RMI registry on port 1099...
RMI registry on port 1099, has started.
com.ejbhome.server.EnterpriseServer.bindDataSources() at (Compiled
Code)
com.ejbhome.naming.spi.rmi.RMICtx.<init>() at (RMICtx.java:20)
registering XA data sources
com.ejbhome.sql.XADataSourceImpl.<init>(jdbc:odbc:Shop,{password=mouse,
user=user}) at (XADataSourceImpl.java:75)
com.ejbhome.naming.spi.rmi.RMICtx.bind() at (RMICtx.java:168)
com.ejbhome.server.EnterpriseServer.fireDataSourceAdded() at (Compiled
Code)
registered: Shop -> jdbc:odbc:Shop, as an XA pooled data
source [main]
com.ejbhome.naming.spi.rmi.RMICtx.<init>() at (RMICtx.java:20)
loading beans from: Books.ejbml
com.ejbhome.server.EnterpriseServer$2.startElement(ejbml) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(entity-bean)
at (EnterpriseServer.java:228)
com.ejbhome.VendorConfiguration.getHomeContainerClassName() at (VendorConfiguration.java:226)
com.ejbhome.VendorConfiguration.getVendorPrefix() at (VendorConfiguration.java:100)
com.ejbhome.container.AbstractEJBHome.<init>() at (AbstractEJBHome.java:136)
com.ejbhome.naming.spi.rmi.RMICtx.<init>() at (RMICtx.java:20)
com.ejbhome.naming.spi.rmi.RMICtx.lookup("Shop") at (RMICtx.java:35)
com.ejbhome.naming.spi.rmi.RMICtx.bind() at (RMICtx.java:168)
registered cup.chap8.Shop.Books.IonaBooksHome, as: Books.
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(container-managed)
at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (EnterpriseServer.java:228)
finished loading beans from: Books.ejbml
loading beans from: Cart.ejbml
com.ejbhome.server.EnterpriseServer$2.startElement(ejbml) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(session-bean)
at (EnterpriseServer.java:228)
com.ejbhome.VendorConfiguration.getHomeContainerClassName() at (VendorConfiguration.java:226)
com.ejbhome.VendorConfiguration.getVendorPrefix() at (VendorConfiguration.java:100)
com.ejbhome.container.AbstractEJBHome.<init>() at (AbstractEJBHome.java:136)
com.ejbhome.naming.spi.rmi.RMICtx.bind() at (RMICtx.java:168)
registered cup.chap8.Shop.Cart.IonaCartHome, as: cart.
finished loading beans from: Cart.ejbml
loading beans from: Music.ejbml
com.ejbhome.server.EnterpriseServer$2.startElement(ejbml) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(entity-bean)
at (EnterpriseServer.java:228)
com.ejbhome.VendorConfiguration.getHomeContainerClassName() at (VendorConfiguration.java:226)
com.ejbhome.VendorConfiguration.getVendorPrefix() at (VendorConfiguration.java:100)
com.ejbhome.container.AbstractEJBHome.<init>() at (AbstractEJBHome.java:136)
com.ejbhome.naming.spi.rmi.RMICtx.<init>() at (RMICtx.java:20)
com.ejbhome.naming.spi.rmi.RMICtx.lookup("Shop") at (RMICtx.java:35)
com.ejbhome.naming.spi.rmi.RMICtx.bind() at (RMICtx.java:168)
registered cup.chap8.Shop.Music.IonaMusicHome, as: music.
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(container-managed)
at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (EnterpriseServer.java:228)
finished loading beans from: Music.ejbml
loading beans from: Shop.ejbml
com.ejbhome.server.EnterpriseServer$2.startElement(ejbml) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(entity-bean)
at (EnterpriseServer.java:228)
com.ejbhome.VendorConfiguration.getHomeContainerClassName() at (VendorConfiguration.java:226)
com.ejbhome.VendorConfiguration.getVendorPrefix() at (VendorConfiguration.java:100)
com.ejbhome.container.AbstractEJBHome.<init>() at (AbstractEJBHome.java:136)
com.ejbhome.naming.spi.rmi.RMICtx.bind() at (RMICtx.java:168)
java.rmi.AlreadyBoundException: Books
registered cup.chap8.Shop.Books.IonaBooksHome, as: Books.
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (EnterpriseServer.java:228)
com.ejbhome.server.EnterpriseServer$2.startElement(container-managed)
at (Compiled Code)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(entity-bean)
at (Compiled Code)
com.ejbhome.VendorConfiguration.getHomeContainerClassName() at (VendorConfiguration.java:226)
com.ejbhome.VendorConfiguration.getVendorPrefix() at (VendorConfiguration.java:100)
com.ejbhome.container.AbstractEJBHome.<init>() at (AbstractEJBHome.java:136)
com.ejbhome.naming.spi.rmi.RMICtx.bind() at (RMICtx.java:168)
registered cup.chap8.Shop.Music.IonaMusicHome, as: Music.
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(property) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(container-managed)
at (Compiled Code)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(field) at (Compiled
Code)
com.ejbhome.server.EnterpriseServer$2.startElement(session-bean)
at (Compiled Code)
com.ejbhome.VendorConfiguration.getHomeContainerClassName() at (VendorConfiguration.java:226)
com.ejbhome.VendorConfiguration.getVendorPrefix() at (VendorConfiguration.java:100)
com.ejbhome.container.AbstractEJBHome.<init>() at (AbstractEJBHome.java:136)
com.ejbhome.naming.spi.rmi.RMICtx.bind() at (RMICtx.java:168)
registered cup.chap8.Shop.Cart.IonaCartHome, as: Cart.
finished loading beans from: Shop.ejbml
The Session Bean Client
The code to test out our session bean is given in the Listing 18:
package com.gopalan.Shop.Cart; import java.rmi.*; import java.util.*; public class CartTest { static final int NUMITEMS = 2; public static void main (String[] args) throws Exception { CartHome home = (CartHome)Naming.lookup ("Cart"); System.out.println ("Naming.lookup successful..."); if (null == home) { System.out.println ("null CartHome returned..."); } Cart cart = home.create (); String title = "Title"; String author= "Author"; for (int i = 0; i < CartTest.NUMITEMS; i++) { System.out.println ("code = " +(i+1) + " Title = " +title+(i+1) + " Author = " +author+(i+1) + " Creating cart.create..."); cart.createNewBook ((i+1),title+(i+1),author+(i+1),100.00,10); cart.createNewAlbum ((i+1),title+(i+1),author+(i+1),20.00,5); } for (int i = 0; i < CartTest.NUMITEMS; i++) { cart.addToBooksCart (i+1); cart.addToMusicCart (i+1); } Vector bookList = cart.getBooksList (); System.out.println ("Book List of size "+ bookList.size ()+" is..."); for (int i = 0; i < bookList.size(); i++) { ReturnSet set = (ReturnSet)bookList.elementAt (i); System.out.println ("code = " +set.code + " Title = " +set.title + " Author = " +set.authors); } Vector musicList= cart.getMusicList (); System.out.println ("Music List of size "+ musicList.size ()+" is..."); for (int i = 0; i < musicList.size(); i++) { ReturnSet set = (ReturnSet)musicList.elementAt (i); System.out.println ("code = " +set.code + " Title = " +set.title + " Author = " +set.authors); } Vector bookCart = cart.getBooksCart (); System.out.println ("Book Cart of size "+ bookCart.size ()+" is..."); for(int i = 0; i < bookCart.size (); i++) { ReturnSet set = (ReturnSet)bookCart.elementAt (i); System.out.println ("code = " +set.code + " Title = " +set.title + " Author = " +set.authors); } Vector musicCart = cart.getMusicCart (); System.out.println ("Music Cart of size "+ musicCart.size ()+" is..."); for (int i = 0; i < musicCart.size (); i++) { ReturnSet set = (ReturnSet)musicCart.elementAt (i); System.out.println ("code = " +set.code + " Title = " +set.title + " Author = " +set.authors); } System.out.println ("Total Books = " +cart.getNumberBooks () + " Total Albums = " +cart.getNumberAlbums () + " Book Cost = " +cart.getBooksTotal () + " Album Cost = " +cart.getAlbumsTotal () + " Grand Total =" + cart.getGrandTotal ()); } }
Listing 18: The CartTest session EJB client Application
Observe that we obtain a reference to our session beans home interface by doing a Naming.lookup("Cart") and then create our session bean using home.create(). The new entities are then created, adding records to the database via cart.createNewBook(). We then add items to our shopping cart by invoking the cart.addToBooksCart() method and display the various lists we maintain.
You can always refer to my Homepage at http://www.execpc.com/~gopalan for more EJB source code. Another good resource is the EJB-INTEREST@JAVA.SUN.COM mailing list from Sun and the EJBHome mailing list ejbhome-discuss@iona.com from Iona.
About the Author... |
Gopalan Suresh Raj is a Software Architect, Developer and an active Author. He is contributing author to a couple of books "Enterprise Java Computing-Applications and Architecture" and "The Awesome Power of JavaBeans". His expertise spans enterprise component architectures and distributed object computing. Visit him at his Web Cornucopia© site (http://www.execpc.com/~gopalan) or mail him at gopalan@execpc.com. |
This site was developed and is maintained by Gopalan Suresh Raj This page has been visited |
Last Updated : Dec 19, '98 |
Copyright (c) 1997-99, Gopalan Suresh Raj - All rights reserved. Terms of use. |
All products and companies mentioned at this site,are trademarks of their respective owners. |