I've been playing a bit around with GWT and am now trying to move from
the "Hello World" phase to some timid useful applications.
However I am struggling to find out how I can inform the embedded
tomcat in GWT to accept a datasource definition so that I can pick it
up in my backend by calling:
Context ctx = null;
try {
ctx = new InitialContext();
_source = (DataSource)ctx.lookup("java:comp/env/jdbc/myDB");
} catch (NamingException ne) {
...
}
I _can_ do it for a "normal" tomcat I control, by adding the resource
definitions in the server.xml file, but GWT does not seem to have this
file and no matter what I do, I seem to be unable to instruct the
embedded tomcat in a way that I can define and pick up my datasource.
Has anyone been able to connect to a jdbc datasource within the
embedded tomcat and is willing to give a short step-by-step howto on
where to put what files? It seems that I'm not the only one struggling
with that and I feel a verbose documentation is direly needed as this
request surely isn't exotic for any webapp that does actually fetch its
data from a database.
Thanks in advance
What you do in 'normal' tomcat is read the data in a servlet and write
it into your JSP page during a request. With GWT and AJAX you make a
request to a service (which extends servlet) and fill in your
form/table/whatever in the callback with the data returned.
If you are familiar with MVC, then GWT is the View, the service is the
Controller and the data sent between them is the Model.
That is what I meant with backend. The code that tries to pick up the
datasource _is_ a servlet extending the GWT's RemoteServiceServlet
class and all the stubs I need to declare are there. This works. My
Webapp is calling the service on the Tomcat.
What does not work is that I can connect to my database in the
service/servlet on the Tomcat. I can do it easily on any "normal"
standalone Tomcat where I deploy a .war, but I cannot do this in GWT's
hosted mode with the embedded Tomcat there. I just cannot find where to
put the xml definitions of the datasources (I need more than one) so
that the service works when in hosted mode.
Hosted mode is so damn fine to start and develop, but it's kind of
pointless debugging an application with no ability to connect to the
database. I probably could hardcode the datasources username/password
and connector strings in the servlet/service but that is simply going
back to the ice-age and I wish to refrain from doing so.
* copy my entire WEB-INF to the tomcat/webapps/ROOT/WEB-INF
* merge my web.xml with the web.xml there
* added nearly all contents from the WEB-INF/lib to the classpath of
the shell. If you are running from eclipse, that means editing the
runtime for the shell (Run... Create,manage, and run configurations)
I say nearly because some conflicted with the tomcat/shell
classloaders, so you are on a trial and error path here.
G.
-- Bruce
please anyone help me to get results from database..iam desperately
waiting for database results...
Thanks in advance
Regards
MK
Let me now
Rinaldo
/**
*
*/
private static final long serialVersionUID = 1L;
private Abitazioni[] DATI_CASA;
private static final Case[] NO_PEOPLE = new Case[0];
public SchedaCasaServiceImpl() {
TextLogger.info("Inizio oooooooo");
AbitazioniDAO abitMng = new AbitazioniDAO(); //Manager for my table
DATI_CASA = abitMng.getAllAbitazioni(); //
generateRandomCase();
}
private void generateRandomCase() {
TextLogger.info("Dentro generate trovate " + DATI_CASA.length);
for (int i = 0; i < DATI_CASA.length; i++) {
Case casa = new Case();//single record
casa.setCodiceCasa(DATI_CASA[i].getCodiceCasa());
casa.setNomeCasa(DATI_CASA[i].getNomeCasa());
casa.setLocalita("" + DATI_CASA[i].getIdLocalita());
lstCase.add(casa);
}
}
public Case[] getCase(int startIndex, int maxCount) {
int peopleCount = DATI_CASA.length;
int start = startIndex;
if (start >= peopleCount) {
return NO_PEOPLE;
}
int end = Math.min(startIndex + maxCount, peopleCount);
if (start == end) {
return NO_PEOPLE;
}
int resultCount = end - start;
Case[] results = new Case[resultCount];
for (int from = start, to = 0; to < resultCount; ++from, ++to) {
results[to] = (Case) lstCase.get(from);
}
TextLogger.info("startIndex = " + startIndex);
TextLogger.info("maxCount = " + maxCount);
return results; //return an array of record
}
private final List lstCase = new ArrayList();
}
As you can see I modify the Dynatable example
Hope that can help you
Regards
Rinaldo
This is what we are doing with our mortgage calculator you can see
running live on our website here:
http://www.cohomefinder.com/Colorado-mortgage.htm
When you choose the market rate drop down on the mortgage calculator,
it connects to a servlet that pulls the mortgage rates from the
database.
We've provided documentation and source code for this example here:
http://www.mooreds.com/weblog/archives/000355.html
Hope this helps!
Anthony
Colorado HomeFinder
www.COhomefinder.com
I think that Rinaldo might have an answer, but I think he posted the
wrong code. We want to be able to open a datasource using code like
Context ctx = new InitialContext();
DataSource source = (DataSource)ctx.lookup("java:comp/env/jdbc/myDB");
Just to clarify, this is code in the RemoteServiceServlet subclass, so
this code *runs on the server*, in the embedded tomcat servlet
container.
I really hope there's some way to do this.
Adam
I think (or suspect anyway) that Google plans on adding additional
configuration capability for the hosted tomcat instance, but this isn't
yet available.
Is there anyway that you can get to your required DataSource without
relying on JNDI? Or, could you use a DataManager (old JDBC 1.x) class
instead?
I struggled with this, and finally happened on the right combination
today. Here's what I had to do:
1. Add the file tomcat/conf/gwt/localhost/ROOT.xml, with the contents:
<Context docBase="ROOT" path="" reloadable="true">
<Resource name="jdbc/demogwt" auth="Container"
type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/demogwt">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<!-- your other parameters here -->
</ResourceParams>
</Context>
2. Add a couple of libraries to my project (and launcher
configuration!). These are the commons-dbcp.jar and
commons-pool.jar... both required to get DBCP working.
That's all I had to do. Took a couple of hours of hacking to get it
working, though.
-eric
I dont' find a way to post a zip file with a part of my project
so I try to explain it with my bad english
package:
com.sp.schedacasa.client (here all the widget, Service,ServiceAsync as
explained in google doc and some post in the forum)
com.sp.schedacasa.server (the servlet and the Hibernate Session
factory,...)
com.sp.schedacasa.server.db.tabelle (here the hibernate.cfg.xml, the
hbm.xml and all the other file generate by hibernate)
here is my hibernate config
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">java:MySqlDS</property>
<property
name="jndi.url">jdbc:mysql://localhost:3306/rslocal?useUnicode=true&amp;autoReconnect=true</property>
<property name="connection.username">rsAdmin</property>
<property name="connection.password">rsAdmin</property>
<property
name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.pool_size">20</property>
<property name="cglib.use_reflection_optimizer">true</property>
<property
name="jndi.class">org.jboss.cache.transaction.DummyContextFactory</property>
<property name="hibernate.dbcp.maxActive">8</property>
<property name="hibernate.dbcp.maxIdle">8</property>
<property name="hibernate.dbcp.max Wait">-1</property>
<property name="hibernate.dbcp.whenExhaustedAction">1</property>
<property name="hibernate.dbcp.test OnReturn">true</property>
<property name="hibernate.dbcp.ps.maxActive">8</property>
<property name="hibernate.dbcp.ps.maxIdle">8</property>
<property name="hibernate.dbcp.ps.maxWait">1800000</property>
<property name="hibernate.dbcp.ps.whenExhaustedAction">1</property>
<property
name="hibernate.jdbc.use_get_generated_keys">true</property>
<mapping
resource="com/sp/schedacasa/server/db/tabelle/Abitazioni.hbm.xml" />
<mapping
resource="com/sp/schedacasa/server/db/tabelle/Localita.hbm.xml" />
</session-factory>
</hibernate-configuration>
and my HibernateSessionFactory
package com.sp.schedacasa.server;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* Configures and provides access to Hibernate sessions, tied to the
current
* thread of execution. Follows the Thread Local Session pattern, see
* {@link http://hibernate.org/42.html}.
*/
public class HibernateSessionFactory {
/**
* Location of hibernate.cfg.xml file. NOTICE: Location should be on
the
* classpath as Hibernate uses #resourceAsStream style lookup for its
* configuration file. That is place the config file in a Java package
- the
* default location is the default Java package. <br>
* <br>
* Examples: <br>
* <code>CONFIG_FILE_LOCATION = "/hibernate.conf.xml".
* CONFIG_FILE_LOCATION = "/com/foo/bar/myhiberstuff.conf.xml".</code>
*/
private static String CONFIG_FILE_LOCATION =
"com/sp/schedacasa/server/db/tabelle/hibernate.cfg.xml";
/** Holds a single instance of Session */
private static final ThreadLocal threadLocal = new ThreadLocal();
/** The single instance of hibernate configuration */
private static final Configuration cfg = new Configuration();
/** The single instance of hibernate SessionFactory */
private static SessionFactory sessionFactory;
/**
* Returns the ThreadLocal Session instance. Lazy initialize the
* <code>SessionFactory</code> if needed.
*
* @return Session
* @throws HibernateException
*/
public static Session currentSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session != null && !session.isOpen())
session = null;
if (session == null) {
if (sessionFactory == null) {
try {
cfg.configure(CONFIG_FILE_LOCATION);
sessionFactory = cfg.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
session = sessionFactory.openSession();
threadLocal.set(session);
}
return session;
}
/**
* Close the single hibernate session instance.
*
* @throws HibernateException
*/
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close();
}
}
/**
* Default constructor.
*/
private HibernateSessionFactory() {
}
}
Hope that's can help you
Regards
Rinaldo
I just followed ur 2 steps ..but iam getting
javax.naming.NamingException: Cannot create resource instance..i tried
a lot...i have just created root.xml in
myproject/tomcat/cpnf/gwt/localhost/root.xml . I think we don't need to
add common-pool and dvcp jar bcoz by deafult we get it eith
naming-factory-dbcp.jar...
I have added the following data in myproject/tomcat/cpnf/gwt/web.xml to
avoid that error...oops nothing...
<resource-ref>
<description> DB Connection </description>
<res-ref-name> jdbc/mydb </res-ref-name>
<res-type> javax.sql.DataSource </res-type>
<res-auth> Container </res-auth>
</resource-ref>...
import java.sql.*;
public class connection {
public static void main(String[] args) throws SQLException {
try{
Connection con=null;
String driverName="oracle.jdbc.driver.OracleDriver";
Class.forName(driverName);
con=DriverManager.getConnection("jdbc:oracle:thin:@oserver1:1521:milton","greg","greg");
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery("select * from linked_records");
while(rs.next()){
int s =rs.getInt(2);System.out.println(s);
}
}
catch(ClassNotFoundException ce){System.out.println(ce);}
catch(Exception e){System.out.println(e);}
}
}
Iam getting good result as " 23785 " but when i used this same
code(as it is ) in my DemoServiceImpl, iam getting error
**** java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
****. So Iam unable to load the driver...i just wonder about
this..what am i doing wrong ...please please any one help...
I also had to modify myApplication-shell.cmd so that to include the
mysql jar file in the classpath:
@java -cp
"%~dp0\src;%~dp0\bin;C:/google/gwt-windows-1.0.21/gwt-user.jar;C:/google/gwt-windows-1.0.21/gwt-dev-windows.jar;C:/google/gwt-windows-1.0.21/mysql-connector-java-3.0.16-ga-bin.jar"
com.google.gwt.dev.GWTShell -out "%~dp0\www" %*
com.uniksoft.MyAPP02/MyAPP02.html
and then I was able to use JDBC in the hosted development shell.
public interface DataService extends RemoteService {
public Person[] getData();
}
public interface DataServiceAsync {
public void getData(AsyncCallback callback);
}
public class DataServiceImpl extends RemoteServiceServlet implements
DataService {
public Person[] getData() {
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
ArrayList values = new ArrayList();
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
con =
DriverManager.getConnection("jdbc:mysql://192.168.0.100:3306/flex","root","321erre1p");
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT First_Name, Last_Name, Days,
Hire_Date, Bonus " + FROM employees");
while (rs.next()) {
values.add( new Person(rs.getString(1), rs.getString(2),
rs.getDate(4).toString(), rs.getString(5)));
}
con.close();
stmt.close();
rs.close();
} catch(Exception e) {
System.out.println(e.toString());
}
return (Person[]) values.toArray( new Person[values.size()] );
}
}
In web.xml:
<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>testRPCServlet</servlet-name>
<servlet-class>com.uniksoft.server.DataServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>testRPCServlet</servlet-name>
<url-pattern>/data</url-pattern>
</servlet-mapping>
</web-app>
Hope this help.
Cheerio.