Java IoT Authors: Zakia Bouachraoui, Yeshim Deniz, Carmen Gonzalez, Elizabeth White, Pat Romanski

Related Topics: Java IoT

Java IoT: Article



Several fun and important secrets of SQLJ will be unlocked today. Our show will include the following numbers:

  • Some magic tricks for taming the SQLJ translator to do your bidding.
  • Some incantations to turn you into a SQLJ debug-mon.
  • An initiation to the mysteries of execution contexts - for getting full control over executing SQL statements - and of connection contexts.
  • A happy story of brotherly love between JDBC and SQLJ.
  • A map of the hidden location containing all of the remaining SQLJ details that the wonderful folks from Java Developer's Journal neither would or could let me fit into this column.
Little space and much to say - let's get started right away!

Your Own Private Translator...Is Talking Back
Don't fret if you're stuck and need help - the SQLJ translator may just be able to give you what you need. Enjoy the following translator command-line options:

  • sqlj -help shows a short help message with the important SQLJ command line options. And when you just say sqlj by itself this is also recognized as a cry for help.
The Translator-Chameleon Is Serving Up Bugs
How I wish that SQLJ translation were built into the javac Java compiler. But tough luck - it ain't! The translator strives hard to make it appear however as if the only difference is saying sqlj instead of javac.

Nice: You can freely mix .sqlj and .java source files on the command line. The translator also has some implicit make capability similar to javac. Oh yes, it automatically invokes your Java compiler - but you already knew that!

Nice: The translator reports error messages from your Java compiler on the original SQLJ file and not on the generated Java file.

Not Nice: When your program throws exceptions at runtime, line numbers - such as those issued by printStackTrace() - are shown in terms of the generated Java files.

Incantation #1
Add the flag -linemap to your command line during translation. Then the translator will fix up file names and the line numbers in those class files to show the original SQLJ files. If you want this on by default (which it probably should have been in the first place), then create an environment variable SQLJ_OPTIONS with the value "-linemap". Or you can add the line sqlj.linemap to a sqlj.properties file.

Still Not Nice: If you use Sun's Java debugger jdb to debug your SQLJ program, you'll see that...this tip does not work: jdb refuses to show the SQLJ source. No wonder — they only taught it about .java source files!

Magic spell #2
Shout -jdblinemap instead of -linemap whenever you must trick that silly little (de)bugger.

God Mode: Well, not quite...You can trace the goings-on in the SQLJ runtime by installing a profile auditor in your SQLJ profile files (remember those pesky little .ser files that hold the static SQL information of your program). After the usual translation and compilation you add tracing with the following command:
sqlj -P-debug *.ser
Have fun drinking from the fire hose!

More Dizzying Debugging Spells
Remember the JDBC Genie? On many platforms (such as Oracle's), SQLJ runtime calls turn into calls to JDBC at the end of the day. You can trace JDBC calls with DriverManager.setLogStream() (or setLogWriter).

Don't count out them IDEs: Oracle's JDeveloper has been supporting SQLJ programming and debugging for a while. Other IDEs may offer SQLJ support Real Soon Now.

Smokey Bear Says: Only you can prevent runtime bugs. You should always provide the translator with the

option, so that it can check your SQL code for real.

Become a Control Freak - with ExecutionContexts
At times you need to obtain additional information about a SQL statement that just ran or you need to control exactly how you want SQL statements to be executed. Take the following examples:

  • The statement might have resulted in a warning (not an exception) that you want to inspect.
  • An UPDATE or DELETE statement reports the number of rows that was changed or - respectively - removed.
  • You want to set a timeout or designate a prefetch size for queries.
  • You want to batch several SQL statements and have them all executed together, rather than pay a round trip to the database for each one. In particular, you want to combine the repeated execution of a DML statement, such as an INSERT, an UPDATE or a DELETE that takes on different values for its bind-variables.

All of this - and more - is available on the sqlj.runtime.ExecutionContext. Every connection context (remember, this is the SQLJ equivalent to JDBC connections) has an associated ExecutionContext which can be accessed with getExecutionContext(). Your static DefaultContext also has one. Consider this example:

import sqlj.runtime.ref.DefaultContext;
import sqlj.runtime.ExecutionContext;
#sql { UPDATE emp SET sal = sal * 2 };
ExecutionContext ec = DefaultContext.getDefaultContext().getExecutionContext();
System.out.println( ec.getUpdateCount() + " employees are rejoicing.");
Or, you can terminate a whole bunch of bad guys in a single batch as follows.
String[] badGuys = { "HORRIBLE", "TERRIBLE", "NOGOOD", "VERYBAD" };
for (int i=0; i<badGuys.length; i++) {
#sql { DELETE FROM emp WHERE ename = :(badGuys[i]) }; }
If we hadn't issued executeBatch() explicitly, then the badGuys' execution would happen implicitly when a different #sql statement is encountered. Alternatively, we could have used ec.setBatchLimit(4); to tell SQLJ to always flush a batch implicitly once 4 rows have accumulated. This convenience feature is not (yet?) offered by JDBC.

Being Well Connected - Explicitly
Until now you've been brainwashed. You were led to believe that there's only a single, static connection in your SQLJ program, set once with DefaultContext.setDefaultContext(...) and then forgotten about. Even though this makes great marketing copy, it's not the (only) way the world works.

If you're connecting to more than one schema, if you're running an applet in a browser or if you're connecting to the database in a multithreaded program, then you should - nay, you must - use explicit SQLJ connections.

Don't worry: it's really easy. You just put the connection context instance (or an expression evaluating to one) in those square brackets:

An example:
import sqlj.runtime.ref.DefaultContext;
DefaultContext ctx =
new DefaultContext("jdbc:oracle:oci8:@", "scott", "tiger", false);
#sql [ctx] { UPDATE emp SET sal = sal * 2 };
Tip: Always use explicit connection contexts, unless you know that your program owns the world and requires only a single, static database connection.

Rolling Your Own Connection
Sometimes you need to distinguish between different schemas or databases. Consider a program that establishes connections to two different database schemas. The PILOTS schema has personnel data, flight hours and so on for pilots, and the JETS schema contains maintenance and flight data of aircraft. Your program is working on two different sets of tables, views and stored procedures. Now you need to verify your SQLJ statements against both of these schemas. Typed connection contexts are what let you do this. First, declare two different context types:

#sql context Pilots;
#sql context Jets;

At runtime, you connect to each of the schemas using the appropriate type:

Pilots pconn = new Pilots("jdbc:oracle:oci8:@","pilots","ace",false);
Jets jconn = new Jets("jdbc:oracle:oci8:@","jets","stratos",false);
Then the connection context type of the #sql statement clearly shows whether you want a Pilots or a Jets connection:
#sql [pconn] { INSERT INTO pilot VALUES ( .... ) }; // Pilots context
#sql [jconn] { UPDATE maintenance SET status = Checkup( .... ) }; // Jets context
Of course at translate time you also need to explain how to connect to the database for both connection context types:
sqlj [email protected]=pilots/ace [email protected]=jets/stratos MyFile.sqlj
SQLJ and JDBC: Living in Perfect Harmony
SQLJ works just fine and dandy with static SQL - where you know the shape of SQL statements and queries beforehand. But what if your application has to make up the WHERE clause in a SELECT statement on the fly - guess you'd better forget all about SQLJ, right?

Not so quick - SQLJ and JDBC are actually close-knit buddies. JDBC connections and SQLJ connection contexts are mutually convertible and so are java.sql.ResultSets and SQLJ iterators. Let's look at the specifics.

Connecting from JDBC to SQLJ
All connection context constructors and initializers can take an existing JDBC connection. Example:

java.sql.Connection conn = DriverManager.getConnection(....);
DefaultContext ctx = new DefaultContext(conn);
Now SQLJ and JDBC share the same session. Closing the SQLJ context will also clean up the JDBC connection.

Connecting from SQLJ to JDBC
All SQLJ connection contexts have the getConnection() method that allows you to retrieve an underlying JDBC connection. For example, if your program uses the static default context, the following will do:

java.sql.Connection conn =
Passing Result Sets from JDBC to SQLJ
If you want to pass off a JDBC result set as a SQLJ iterator, you can do so with a SQLJ CAST statement:
SomeIterator iter;
java.sql.ResultSet rs = stmt.executeQuery();
#sql iter = { CAST :rs };
Why that CAST statement and not simply a Java constructor? So that any vendor's SQLJ runtime implementation can scrutinize that result set very closely.

Passing Iterators fromSQLJ to JDBC
This one's a breeze. You just call the iterator's getResultSet() method and - voilˆ - your JDBC ResultSet.

Exercise 1: Why might it be useful to convert a JDBC result set into a SQLJ iterator or vice versa?

Jump into the Fray
Hope you enjoyed the journey, even though we've not yet seen all the vistas. We stopped short of covering the new fun JDBC 2.0 features that made it into SQLJ, such as support for various SQL LOB types, named SQL types, DataSources and scrollable iterators. Nor did we look at how to put iterator subclassing to use or how connection caching meshes with SQLJ or even speculate what directions SQLJ might take in the future. Is there a place to learn more? In my totally biased opinion (Oracle pays my bills, after all) the vastest amount of information on SQLJ is on the Oracle Technology Network site at http://technet.oracle.com. You'll find the world's most humongous SQLJ manual that answers more questions than you could ever dream of, as well as demos, samples, papers, an FAQ and so on. Beware, though, the Oracle-specific is happily stirred in with the generic.

Better yet, do it. If you want to get involved on the standards side, subscribe to the SQLJ partners mailing list at [email protected]. Or, if you want to hack the SQLJ reference implementation - yep, all source, all public domain - go to www.sqlj.org. Or download one of the SQLJ implementations from the IBM, Informix, or Oracle Web site and get started.

Summary of SQLJ Syntax

  • Connection context declaration and use:
    #sql context CtxType;
    CtxTypectx = new CtxType(url, user, pwd, auto-commit);
    #sql [ctx] { ...sql statement... };
  • Setting the translate-time connection for CtxType:
    sqlj [email protected]=user/pwd ...
  • ExecutionContext declaration and use:
    import sqlj.runtime.ExecutionContext;
    ExecutionContext ec = new ExecutionContext();
    ... set properties on ec ...
    #sql [ec] { ...sql statement... };
    ... retrieve warnings, update count, side-channel results, etc. from ec ...
  • Using an explicit ExecutionContext and an explicit connection context:
    #sql [ctx, ec] { ...sql statement... };
  • Casting SQLJ iterators to JDBC result sets:
    SqljIterator iter;
    #sql iter = { CAST :jdbc_result_set };

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.

IoT & Smart Cities Stories
Blockchain is a new buzzword that promises to revolutionize the way we manage data. If the data is stored in a blockchain there is no need for a middleman - the distributed database is stored on multiple and there is no need to have a centralized server that will ensure that the transactions can be trusted. The best way to understand how a blockchain works is to build one. During this presentation, we'll start with covering the basics (hash, nounce, block, smart contracts) and then we'll crea...
History of how we got here. What IoT devices are most vulnerable? This presentation will demonstrate where hacks are most successful, through hardware, software, firmware or the radio connected to the network. The hacking of IoT devices and systems explained in 6 basic steps. On the other side, protecting devices continue to be a challenging effort. Product vendors/developers and customers are all responsible for improving IoT device security. The top 10 vulnerabilities will be presented a...
As the fourth industrial revolution continues to march forward, key questions remain related to the protection of software, cloud, AI, and automation intellectual property. Recent developments in Supreme Court and lower court case law will be reviewed to explain the intricacies of what inventions are eligible for patent protection, how copyright law may be used to protect application programming interfaces (APIs), and the extent to which trademark and trade secret law may have expanded relev...
Never mind that we might not know what the future holds for cryptocurrencies and how much values will fluctuate or even how the process of mining a coin could cost as much as the value of the coin itself - cryptocurrency mining is a hot industry and shows no signs of slowing down. However, energy consumption to mine cryptocurrency is one of the biggest issues facing this industry. Burning huge amounts of electricity isn't incidental to cryptocurrency, it's basically embedded in the core of "mini...
At CloudEXPO Silicon Valley, June 24-26, 2019, Digital Transformation (DX) is a major focus with expanded DevOpsSUMMIT and FinTechEXPO programs within the DXWorldEXPO agenda. Successful transformation requires a laser focus on being data-driven and on using all the tools available that enable transformation if they plan to survive over the long term. A total of 88% of Fortune 500 companies from a generation ago are now out of business. Only 12% still survive. Similar percentages are found throug...
At CloudEXPO Silicon Valley, June 24-26, 2019, Digital Transformation (DX) is a major focus with expanded DevOpsSUMMIT and FinTechEXPO programs within the DXWorldEXPO agenda. Successful transformation requires a laser focus on being data-driven and on using all the tools available that enable transformation if they plan to survive over the long term. A total of 88% of Fortune 500 companies from a generation ago are now out of business. Only 12% still survive. Similar percentages are found throug...
Every organization is facing their own Digital Transformation as they attempt to stay ahead of the competition, or worse, just keep up. Each new opportunity, whether embracing machine learning, IoT, or a cloud migration, seems to bring new development, deployment, and management models. The results are more diverse and federated computing models than any time in our history.
At CloudEXPO Silicon Valley, June 24-26, 2019, Digital Transformation (DX) is a major focus with expanded DevOpsSUMMIT and FinTechEXPO programs within the DXWorldEXPO agenda. Successful transformation requires a laser focus on being data-driven and on using all the tools available that enable transformation if they plan to survive over the long term. A total of 88% of Fortune 500 companies from a generation ago are now out of business. Only 12% still survive. Similar percentages are found throug...
Atmosera delivers modern cloud services that maximize the advantages of cloud-based infrastructures. Offering private, hybrid, and public cloud solutions, Atmosera works closely with customers to engineer, deploy, and operate cloud architectures with advanced services that deliver strategic business outcomes. Atmosera's expertise simplifies the process of cloud transformation and our 20+ years of experience managing complex IT environments provides our customers with the confidence and trust tha...
Where many organizations get into trouble, however, is that they try to have a broad and deep knowledge in each of these areas. This is a huge blow to an organization's productivity. By automating or outsourcing some of these pieces, such as databases, infrastructure, and networks, your team can instead focus on development, testing, and deployment. Further, organizations that focus their attention on these areas can eventually move to a test-driven development structure that condenses several l...