How to use CachedRowSet in Google App Engine? - java

I am using Google App Engine (Endpoints) to generate a simple API service.
I'm currently trying to make my queries to the database faster and more efficient, so I decided to double check where I was calling ResultSet and Connections and closing them.
However I want to use CachedRowSet and it almost seems impossible given that when I try to access CachedRowSetImpl() the logger returns:
java.lang.NoClassDefFoundError: com.sun.rowset.CachedRowSetImpl is a
restricted class. Please see the Google App Engine developer's guide
for more details
So I did some investigation and Google App Engine's JRE whitelist includes:
javax.sql.rowset.CachedRowSet
but not
com.sun.rowset.CachedRowSetImpl
Does that make any sense? How can I initialize/use CachedRowSet otherwise?
My code:
public ResultSet getRecordsWhereInt(String table, String where, int condition) throws SQLException {
c = DatabaseConnect();
preStatement = c.prepareStatement("SELECT * FROM " + table + " WHERE " + where + " = ?");
preStatement.setInt(1, condition);
CachedRowSet rowset = new CachedRowSetImpl();
rowset.populate(preStatement.executeQuery());
c.close();
return rowset;
}
Any help would/guidance would be appreciated.
Update 1 (09/06/2015):
Investigating further, I found that you can implement CachedRowSetImpl's functionality using RowSetProvider.newFactory().createCachedRowSet();
However, Google has also restricted use to RowSetProvider().
That left me with the only other whitelisted library RowSetFactory. So I made my own, implementing RowSetFactory according to Oracle's implementation:
public class CachedRowSetFactory implements RowSetFactory {
public CachedRowSet createCachedRowSet() throws SQLException {
return new CachedRowSetImpl();
}
public FilteredRowSet createFilteredRowSet() throws SQLException {
return null;
}
public JdbcRowSet createJdbcRowSet() throws SQLException {
return null;
}
public JoinRowSet createJoinRowSet() throws SQLException {
return null;
}
public WebRowSet createWebRowSet() throws SQLException {
return null;
}
}
And then used it like this:
CachedRowSet crs = new CachedRowSetFactory().createCachedRowSet();
However, even this fails. The above example returns a Null Pointer Exception when I try to populate it with a working result set. I'm guessing the factory implementation isn't 100% correct or that I'm skipping over something obvious.
Update 2 (11/06/2015):
I tried rolling my own implementation of CachedRowSetImpl, and of the RowSetProvider by duplicating some of the libraries by hand and eliminating the libraries not covered in App Engines Whitelist. Was not successful. I know I need to give up on this but I'm determined to make this work.

CahecRowSet is an interface so obviously this is whitelisted.
Interface CachedRowSet
I am guessing you are connecting a Google CloudSQL instance.
from the javadoc :
A CachedRowSet object is a container for rows of data that caches its
rows in memory, which makes it possible to operate without always
being connected to its data source.
What you are trying to do does not make sense IMO. AppEngine does not keep state between different requests and certainly not when your application auto-scales and new instances spin up.
Why don't you cache your results in Memcache, this will persist over subsequent requests and different instances.

Related

What to Do when JDBC Driver is Invalid?

I'm working on a Java project that uses an Oracle database. When I create a new Oracle driver:
jdbcDriver driver = new jdbcDriver();
...I check it to see if it is valid using:
if (!driver.isValid())
{
throw new UncheckedSqlException("jdbcDriver not valid");
}
What is the correct procedure if the driver is invalid? That is, there is no way to store the data and retry later asynchronously (i.e. without locking up the app), since the database is unavailable. Is the assumption that if I just retry a few times, I'll get a valid driver?
UPDATE
Thanks to EJP for correctly pointing out that jdbcDriver is a class in my code. That is correct -- it is a class in a code base I am working on. EJP requests to have the relevant details posted. Here they are.
package us.mydev.jdbc.util;
import java.sql.*;
import javax.naming.*;
import javax.sql.*;
import org.apache.log4j.Logger;
import us.mydev.data.exception.UncheckedSqlException;
public class jdbcDriver
{
[.....]
public jdbcDriver()
{
try
{
m_iActiveConnections++;
if (showLogMessages)
{
log.debug("jdbcDriver() created, hashcode = " + this.hashCode()
+ ",Active Connection Count is " + m_iActiveConnections);
log.debug("Data Source is " + DS_STANDARDUSER);
}
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup(DS_STANDARDUSER);
mydevGetJDBCConn getConn = new sqlConn(ds);
m_conn = getConn.getConnection();
m_iDatabaseType = getConn.getDBType();
}
catch (NamingException _exp)
{ // handle any errors
log.error("failed", _exp);
}
}
public boolean isValid() throws SQLException
{
return m_conn != null && m_conn.isValid(10);
}
[.....]
}
I am finding that after this code:
jdbcDriver driver = new jdbcDriver();
boolean driverIsValid = driver.isValid();
...driverIsValid is false about once in every 1000 or so database accesses. I would imagine that this is an artifact of my current dev system -- I have Oracle running in a virtual machine.
Would it be unusual (or unheard of) for driverIsValid to be false in production in a situation like this? And if it is not unheard-of -- how is it usually handled, given that I can't save the relevant data to the database -- that is, can I just retry getting a database connection a few times and expect to get one?
UPDATE #2
Based on what I've learned from the responses, I need to ask this question using no code from the objects defined in the code base I am working on. I'm going to accept the answer provided by Wen-Bin Luo and re-ask the question more properly.
I think you are meaning if a connection is still valid at time of checking. The isValid method returns whether or not a connection is usable. This method can be invoked at any time you like and allows you to set a timeout.
According to the official manual, the method is
particularly useful in combination with a retry mechanism.
helpful when used in conjunction with the connection timeout and connection harvesting features.
You of course can retry the method in the hope of the database issue resolves afterwards, but more generally you set a timeout and after that you may have to take appropriate action and close the connection.
try { conn = poolDataSouorce.getConnection ... } catch (SQLException sqlexc)
{
if (conn == null || !((ValidConnection) conn).isValid())
// take the appropriate action
conn.close
}
For more information, please check https://docs.oracle.com/cd/B28359_01/java.111/e10788/connect.htm#CHDIDEEB

searching for multiple occurrences of variables in a method

I have a problem with cursor leakage in my Java project.
Typical example:
private void doSomething() throws Exception {
String sql1= "some sql statement";
String sql2= "some other sql statement";
PreparedStatement ps = null;
ResultSet rs = null;
try {
Connection con = getConnection();
ps = con.prepareStatement(sql1);
rs = ps.executeQuery();
//do something with the ResultSet rs
//[Need to call ps.close here. Otherwise I risk getting ORA-01000.]
ps = con.prepareStatement(sql2);
ps.executeQuery();
} catch (Exception e) {
} finally {
ps.close();
rs.close();
}
}
Since I have a rather large code base I would like to be able to find all methods
having two or more variables named sql.
Alternativly finding methods with two (or more) calls for prepareStatement without
calling ps.close; between the two.
I am using Eclipse and the file search has a regex option. Maybe thet is the way to go?
If so, what would it look like?
Recent versions of Eclipse (I used Juno [4.2]) will show a warning on those lines:
You can enable this warning in the Eclipse preferences:
Even for larger size code bases, you can filter the problems view for this warning in order to find these places in the code.
You can avoid having to close resources manually (if you are using at least JDK 7) by using a try with resources
try(con=getConnection()){
try(ps = con.prepareStatement()){
try(rs=ps.executeQuery()){
...
}
}
}
Anything that implements Autoclosable can be used in a try with resources and the resource gets automatically closed for you. No need to implement complicated resource closing operations anymore.
See the Try-with-Resources Tutorial
What you want to do is kind of static program analysis. As there are specialized tools for that, you may also write your own tool for this specific task.
In that way, you could count lines containing rs=ps.executeQuery and rs.close():
for(File file:sourceFiles) {
int openedResultSets = count("rs=ps.executeQuery");
int closedResultSets = count("rs.close()");
if (openedResultSets > closedResultSets) {
log.error(file.getName());
}
}
But it should be more complex because probably not only this snippet is used in your projects. Therefore I suppose you should write some code, not only one regexp.
Although specialized tools are expensive in most cases, probably some trial version will be enough for you.
There are FindBugs rules to find this, such as
ODR_OPEN_DATABASE_RESOURCE
ODR_OPEN_DATABASE_RESOURCE_EXCEPTION_PATH
OBL_UNSATISFIED_OBLIGATION
more if you look for the keyword 'resource' in the bug description
If you are not specifically looking for resource leaks, but rather for two or more variables named sql*, you can write a Checkstyle check to find them, possibly as a subclass of LocalVariableNameCheck. This is not a difficult kind of check, but requires coding and deployment work.

Mock database driver

Is there some kind of JDBC driver which simply ignores database calls?
For the development I am migrating an application to a virtual machine. Here I want to work on the GUI part only. But the application makes several requests to a database which doesn't let the application even start. I don't want to change the application code at this time since the database is pretty much coupled.
So I was thinking there could be a JDBC driver which just returns empty results for queries.
I decided to write an own simple mock driver. This was pretty much straight forward and did what I want. I can switch the database driver of the application by a configuration file so I could let the application use my driver on a simple way.
Then I extended the driver to return data which it parses from CSV files. I published the code on google code maybe someone else can get use of it: dummyjdbc
There are some "void" JDBC drivers as part of Mocking framewroks, for example MockDriver from Mockrunner.
But using it requires some coding.
That's because when Java application connects to a database it provides a JDBC URL in form jdbc:mysql://localhost. The system is searching which driver is registered in it to handle this kind of URL and chooses the right driver. The info about which URL type driver supports is contained in the driver itself, and it's impossible for a mock driver to hold all known URL types in it - there's no such thing as wildcarding there and any list would not be full.
So, if you're able to call JDBCMockObjectFactory.registerMockDriver() in the application before it connects to the database - it will do the job. If not - I don't think it's possible. However, slight modification of the driver code would do it... but again - coding is required.
jOOQ ships with a MockConnection that can be provided with a MockDataProvider, which is much easier to implement than the complete JDBC API. This blog post shows how to use the MockConnection:
http://blog.jooq.org/2013/02/20/easy-mocking-of-your-database/
An example:
MockDataProvider provider = new MockDataProvider() {
// Your contract is to return execution results, given a context
// object, which contains SQL statement(s), bind values, and some
// other context values
#Override
public MockResult[] execute(MockExecuteContext context)
throws SQLException {
// Use ordinary jOOQ API to create an org.jooq.Result object.
// You can also use ordinary jOOQ API to load CSV files or
// other formats, here!
DSLContext create = DSL.using(...);
Result<MyTableRecord> result = create.newResult(MY_TABLE);
result.add(create.newRecord(MY_TABLE));
// Now, return 1-many results, depending on whether this is
// a batch/multi-result context
return new MockResult[] {
new MockResult(1, result)
};
}
};
// Put your provider into a MockConnection and use that connection
// in your application. In this case, with a jOOQ DSLContext:
Connection connection = new MockConnection(provider);
DSLContext create = DSL.using(connection, dialect);
// Done! just use regular jOOQ API. It will return the values
// that you've specified in your MockDataProvider
assertEquals(1, create.selectOne().fetch().size());
There is also the MockFileDatabase, which helps you matching dummy results with SQL strings by writing a text file like this:
# This is a sample test database for MockFileDatabase
# Its syntax is inspired from H2's test script files
# When this query is executed...
select 'A' from dual;
# ... then, return the following result
> A
> -
> A
# rows: 1
# Just list all possible query / result combinations
select 'A', 'B' from dual;
> A B
> - -
> A B
# rows: 1
select "TABLE1"."ID1", "TABLE1"."NAME1" from "TABLE1";
> ID1 NAME1
> --- -----
> 1 X
> 2 Y
# rows: 2
My framework Acolyte is a tested JDBC driver designed for such purposes (mock up, testing, ...): https://github.com/cchantep/acolyte
It already used in several open source projects, either in vanilla Java, or using its Scala DSL:
// Register prepared handler with expected ID 'my-unique-id'
acolyte.Driver.register("my-unique-id", handler);
// then ...
Connection con = DriverManager.getConnection(jdbcUrl);
// ... Connection |con| is managed through |handler|
Never heard of such a driver myself. If you don't find one, you could instead use a DB like HSQLDB. You can configure it to use in-memory tables, so nothing else gets written to disk. You would have to use a different connection string, though.
If you want to do unit tests, not an integration tests, than
you can use a very basic and simple approach, using Mockito only, like this:
public class JDBCLowLevelTest {
private TestedClass tested;
private Connection connection;
private static Driver driver;
#BeforeClass
public static void setUpClass() throws Exception {
// (Optional) Print DriverManager logs to system out
DriverManager.setLogWriter(new PrintWriter((System.out)));
// (Optional) Sometimes you need to get rid of a driver (e.g JDBC-ODBC Bridge)
Driver configuredDriver = DriverManager.getDriver("jdbc:odbc:url");
System.out.println("De-registering the configured driver: " + configuredDriver);
DriverManager.deregisterDriver(configuredDriver);
// Register the mocked driver
driver = mock(Driver.class);
System.out.println("Registering the mock driver: " + driver);
DriverManager.registerDriver(driver);
}
#AfterClass
public static void tearDown() throws Exception {
// Let's cleanup the global state
System.out.println("De-registering the mock driver: " + driver);
DriverManager.deregisterDriver(driver);
}
#Before
public void setUp() throws Exception {
// given
tested = new TestedClass();
connection = mock(Connection.class);
given(driver.acceptsURL(anyString())).willReturn(true);
given(driver.connect(anyString(), Matchers.<Properties>any()))
.willReturn(connection);
}
}
Than you can test various scenarios, like in any other Mockito test e.g.
#Test
public void shouldHandleDoubleException() throws Exception {
// given
SomeData someData = new SomeData();
given(connection.prepareCall(anyString()))
.willThrow(new SQLException("Prepare call"));
willThrow(new SQLException("Close exception")).given(connection).close();
// when
SomeResponse response = testClass.someMethod(someData);
// then
assertThat(response, is(SOME_ERROR));
}
If you're using Spring, make your own class that implements Datasource and have the methods do nothing.

How can I update my MySQL database from a Java applet?

I'm new to Java and I need some advice/information on how to debug my Java Applet.
I have created a applet that simply updates a MySQL database. The applet seems to load in the web page with no errors. When I click on my button to update the database it seems to actually make the call to the applet, BUT nothing happens, i.e. no new inserts are made to the database, and the page returns properly.
I have taken the applet code and tested it in a Java desktop app. It works fine, no changes other than removing the "extend Applet" modifier. In the desktop app the database gets updated properly.
If I was given some pointers on how to write to the Java Console window that might help me in debugging the code - but I don't know how to do that. I'm not sure what else to try to find the issue. Everything seems correct to me.
BTW: I'm using Netbeans 6.7 in Windows 7 with the MySQL server and Glassfish 2.1 on a CENTOS (Linux) system.
Here is my code for the applet:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.me.db;
import java.applet.*;
import java.sql.*;
/**
*
* #author Rick
*/
public class dbapplet extends Applet {
/**
* Initialization method that will be called after the applet is loaded
* into the browser.
*/
public void init() {
// TODO start asynchronous download of heavy resources
}
public long SaveToDatabase(String subject, String note, int priority,
String category, String isOpen, String currentSession) {
Connection con = null;
Statement stmt = null;
StringBuilder sb = new StringBuilder();
long lastInsertId = -1;
try {
//build the insert
int IsOpen = (isOpen.contains("1")) ? 1 : 2;
sb.append("INSERT INTO 'LogDetails' ('category', 'priority',
'subject', 'note', 'is_open', 'has_attachements') VALUES");
sb.append(" (");
sb.append("'" + category + "',");
sb.append(priority + ",");
sb.append("'" + subject + "',");
sb.append("'" + note + "',");
sb.append("b'" + IsOpen + "',");
sb.append("b'0');");
//connect and execute the insert
String dbURL = "jdbc:mysql://localhost/authentication";
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection(dbURL, "xxxxxxx", "yyyyyyyy");
stmt = con.createStatement();
stmt.execute(sb.toString());
//get the last inserted id
ResultSet rs = null;
rs = stmt.executeQuery("SELECT LAST_INSERT_ID()");
if (rs.next()) {
lastInsertId = rs.getLong(1);
}
rs.close();
} catch (Exception e) { //database problem
System.out.println("Error " + e.getMessage());
System.out.println(sb.toString());
}
return lastInsertId;
} //end of SaveToDatabase
public void QuickSaveToDataBase() {
//disgard the result for now - lets see if we can get this working
this.SaveToDatabase("Quick Save", "Testing of the Quick Save Function",
1, "Testing", "1", "skjdkjd-junk");
}
}
JDBC in Applet should be avoided if all possible. Here are the security issues you will be facing,
You have to open up your database to all IP addresses unless this is an inhouse or enterprise app.
Your database password will be in the applet, readable by anyone with a little reverse-engineering.
If you really want do this, you need to use trusted Applet by signing it.
Since you've got localhost as the server's address..., unless you're running the mysql server on the same box, this will cause a problem. Also, I believe there are security restrictions that disallow contacting localhost over a port from a Java Applet.
Hope this helps.
Applets run in a sandbox that (when in browser) dramatically restrict what they can do. In general, they can't open up connection to any host other than the one they were served up from.
This site: http://www.securingjava.com/chapter-two/chapter-two-2.html is a little dated, but gives you a good general idea for what restrictions you'll be facing.
The most likely reason for the failure is a classloader exception. The applet's classloader is a URLClassloader that can load classes only from certain URLs due to the security implications.
In this case, the applet classloader is most likely unable to load the MySQL JDBC driver. If you have to make the applet work, place the MySQL driver's jar files in an area on the web server that is accessible by the applet, and use the archive attribute of the applet tag to enable the classloader to load the driver.
Why should you not do this?
Although the answer given above will work technically, it is a really bad practice to expose your database on the internet or a DMZ(de-militarized zone); that normally includes an intranet as well in certain companies. Presumably, you are doing this for studying applets and not for production usage. ZZ Coder has already pointed this out.

How do I connect to an Access database over a LAN using Java?

Do you know of any good guides on how to access an Access database using Java?
I know the basics and basic SQL, but I'm thinking more about access control.
private static final String accessDBURLPrefix = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=";
private static final String accessDBURLSuffix = ";DriverID=22;READONLY=false}";
// Initialize the JdbcOdbc Bridge Driver
static {
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
} catch(ClassNotFoundException e) {
System.err.println("JdbcOdbc Bridge Driver not found!");
}
}
/** Creates a Connection to a Access Database */
public static Connection getAccessDBConnection(String filename) throws SQLException {
filename = filename.replace('', '/').trim();
String databaseURL = accessDBURLPrefix + filename + accessDBURLSuffix;
return DriverManager.getConnection(databaseURL, "", "");
}
Some useful links:
http://blog.taragana.com/index.php/archive/how-to-access-ms-access-database-from-jdbc/
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=2691&lngWId=2
If you mean using relational databases in Java, you'll need to know JDBC.
You won't be able to do much with security using JDBC. You'll have to build it into the application using something like JAAS or Spring Security.
You can share a database over a shared drive on LAN n then add it to System DSN of other PCs and you can share access database over LAN .. Worked for me like that
I know string is old but maybe useful for someone like me i was frustrated finding a proper and easy way for sharing
JDBC is the way to go. Google for "JDBC tutorial" + mysql, you will get all you need.

Categories