Does Tomcat use cached versions of pl/sql modules? - java

Ok imagine this situation. I make a change to a pl/sql module, recompile it and everything is fine. No errors.
I then try to access a GUI screen on an application that runs on Tomcat. The screen calls a pl/sql module in an oracle database.
When i submit the form which should have called that pl/sql module for processing the data, i get this error
ORA-20001: ORA-06508: PL/SQL: could not find program unit being called
I checked all packages in $USER_OBJECTS and there is nothing with a status of INVALID.
I restarted Tomcat and then it starts working. Does this mean that when i recompiled the package the first time i effectively removed some cached reference to the package which Tomcat was using?
The connection to the database is via JDBC and DBCP connection pools. Does the recompile maybe invalidate the connection?

This issue is with the JDBC connection pools and is an issue you get with all app servers using JDBC connection pools, not just Tomcat. The connection pools will keep a number of connections open in the pool ready for the next request. If a PL/SQL package has been referenced by the connection and is recompiled then the next call to that package will raise an ORA-06508 error. This will affect packages anywhere in the call stack - not just the package you called directly.
To resolve this some app servers (like Weblogic) have a test method that is called periodically. If the test fails the connection is removed from the pool or refreshed in some way. I'm not sure what mechanism Tomcat has.
Another way to address it is to call dbms_session.reset_package as the first method call in your JDBC call. This will clear the package state from you're session. This approach isn't recommended as it has a performance overhead plus any package-scoped variables are reset so package initialisation blocks need to be called again - another performance hit.
If you've got the issue and you haven't got a way of dropping bad connections you'll need to reset the whole connection pool as any connection in the pool will suffer from the same exception.

The screen calls a pl/sql module in an
oracle database.
No, it doesn't. Assuming you're running a servlet based web-app on Tomcat then your browser sends a request to Tomcat, which invokes the relevant servlet and then some java class in the web-app will execute a pl/sql program as a CallableStatement.
The key to this is how the java class executes the CallableStatement and whether it retains a reference to it or prepares it each time it executes it. Can you shed any light on this?
Edit:
I beleive the Oracle JDBC driver is capable of performing statement caching, which may be causing the problem. Have a read of the driver docs to get more info.

The error you are getting usually indicates that the stored procedure/package either:
1) doesn't exist by the name you are trying to call it with (from your Java class)
2) is missing a grant EXECUTE privilege to the user (defined by the JDBC connection) that is trying to execute it
3) is missing a synonym, if it is being executed via its name only (i.e. without a schema prepended)
4) is being called without the correct number and types of parameters

Related

When should connection.close() be invoked in a j2ee project?

I didn't use any framework since it's only a little project. Now I invoke connection.close() in the destroy() method of the main servlet. But there are some problems.
I don't know when servlet.destroy() is invoked...I thought when the browser is closed is the time it's invoked,but it seems wrong.
I found out that if I don't operate the page visiting my project,after some time,destroy() is invoked,then the connection will be closed.But the project is running some code that maybe periodically write to the database,that case a exception will be thrown.
Any solutions? And I want to know when the servlet.destroy() will be invoked.
That only works if you have one shared connection.
A better solution is to use the JNDI connection pooling capability built into your servlet engine. You want to use a connection in the smallest method scope possible and return it to the pool. You'll be able to serve more clients with a small connection pool that way.

Get JDBC connection working in play framework (java)

Was wondering, what steps am I missing to get a jdbc embeded h2 database working in my play application? Following these docs.
So far editted Application.conf file to contain this:
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:databases/test"
db.default.user=test
db.default.password="testtest"
Next I created a libs directory and added the jar file
h2-1.3.174.jar
Is this necessary or does the provided driver handle all types of h2 databases (embeded and server - I know it handles in memory)?
Now in the controler how can I access the database? Do I have to start/shutdown the database?
I know I can get connections from the getConnection() method in play.db. But everytime I execute a statement through this connection I get an exception saying no data is available. If I then check - looks like directory
databases/test
was not created so no database files exist.
What am I missing?
H2 works out of the box. Just create a new project in the terminal.
Otherwise, to your listing:
I think you should change db.default.url="jdbc:h2:databases/test" to db.default.url="jdbc:h2:mem:play"
don't need to create lib directories. It's all handeled by the build in dependency mgmt sbt
Just use the model objects and call save/update. No need to call start/shutdown
you are in a framework, it's all there ready for you...
I think you should start reading the documentation from the beginning to the end and examine the example applications. It's all there what you are looking for.
In addition to myborobudur's answer I'll only mention, that you don't need to use memory database, as you can for an instance use file storage (Embedded) or even run H2 as a server and then connect to it with TCP in Server Mode... Everything is clearly described in H2 documentation.

Issue when deploying application to GlassFish Server - mapping issue?

I'm trying to deploy an application to my GlassFish Server environment. I've set it up so that GlassFish creates a connection pool to a postgreSQL database on another server (not localhost) where the database is located. I test the connection and then try to deploy the application. It fails with a java.lang.RuntimeException: EJB Container initialization error, and my error log contains the following: http://ideone.com/UlZXut (put it here due to its size). There were other warnings above these, but they only referred to tables already existing.
As according to this, I thought that the required sun-cmp-mappings.xml file (the one I assume would be necessary for this correct mapping) would be automatically generated upon deployment, but it seems I was wrong. Could anyone shed some light on this situation?
My apologies if this is not the absolute best part of SE to post this, but it is related to development tools and I did see a number of related posts.
Your error log indicates that you are trying to create table(s) with DOUBLE as a datatype. In Postgresql, that datatype is actually called "double precision". What happens if you revise the table definition to use "double precision" instead?
on startup Glassfish tries to create the DB tables for your java code. It fails to do that and it fails to startup.
Check the configuration of your ORM mapper.

How can I store sensitive data in Java configuration files?

I have some code that I want to make public. The code sends email via servers, connects to databases, and other tasks requiring usernames/passwords.
I'd like to store the passwords and such in a seperate configuration file so that I don't have to sanitize my code on every commit.
How can I do this? It would be easy to do in C using #define, but I'm not sure how to accomplish this in Java.
EDIT: The environment I'm using is Glassfish
The basic method is put the information in a properties file and use the Properties class to load it at run time. If you're using a J2EE server, database connections are configured in the server and the code references them by an abstract name.
I think I should add that if you're using a server, how to configure it and how to get the connections to your code will vary by server and J2EE level so post your environment. Using the Properties class is pretty obvious just by looking at the javadoc and the load() methods.
In glassfish, go to the admin console and under Resources create a new connection pool. That defines your database connection and will share a pool of those connections among your applications. Now under JDBC Resources, create a new entry that maps that pool to a name. The name is usually something like jdbc/myappname.
For a J2EE5 or later application, you can now add this as a class level variable:
#Resource(mappedName="jdbc/myappname") DataSource myDS;
At runtime the server will inject that resource to your database pool. Then when you need a connection, you can do this inside any method:
Connection conn = myDS.getConnection();
The result is your code doesn't have to care at all about the database connection information or managing a pool of connections. You can deploy the identical code on development and production servers, and they will get an appropriate connection. In order to get the injection, it has to be a class the server creates like an EJB, servlet, tag library handler, or JSF managed bean.

Instantiating Oracle Driver results in InvocationTargetException

I have a simple web service that uses an oracle database. When I test the service internally it works fine, however, calling the web service through my client (on the same machine but in a different WAR) throws an invocationtargetexception. I've finally discovered it's an issue with instantiating the OracleDriver. It doesn't throw any exception at all so I cannot find out what the error is.
Googling has only provided a solution of using oracle.jdbc.driver.OracleDriver instead of oracle.jdbc.OracleDriver but that doesn't seem to fix anything. The jar I'm using is ojdbc14.jar and, as far as I can tell, it's included in the class path for the web service properly... since it works when I test the service with a simple main method.
EDIT:
The InvocationTargetException is generated by an AxisFault from the Axis server. The invocationtargetexception is a wrapper class, and my attempts to try to extract the exception using .getCause() always return null.
I am deploying the service using jboss and was including the driver JAR file in the library for the source but not for the server. Including the driver in /jboss/server/default/lib resolved it.
2 WARs? I suppose your ojdbc.jar is located inside WEB-INF/lib of the web service's WAR.
Maybe your WAR is inside an EAR, so you should reference the driver in MANIFEST.MF.
More info: http://java.sun.com/j2ee/verified/packaging.html
Without more information, it's hard to provide concrete suggestions; I have however had experience with an Oracle driver that attempts to connect via native OCI libraries, fails to find those libraries installed on the system, and throws an InvocationTargetException. This is all from very vague memory, so your mileage will almost certainly vary.
It's been a while, but if memory serves me, I had a case where the connection URL was incorrectly configured, and OracleDriver (or one of its wrappers) iterated through a set of possible connection methods, trying to find one that worked. In the case that the URL was correctly configured, it never got to the OCI attempt (the thin connection method attempt came first), but if the connection URL was misconfigured, the thin attempt would fail, causing the OCI attempt, which then also failed because the OCI client was not installed on the host (resulting in an InvocationTargetException.)
So, some things to check:
Is the connection URL valid? If you're using the same connection URL in both places, are you sure that both processes are binding to the same NIC? If they are binding to different NICs, it might cause connection oddities, even on the same host.
Is the environment the same in both cases - if the OCI client is getting used in your development environment, there are likely several environment variables it depends on. If those environment variables aren't set identically in the environment where the servlet container is running, I'd expect different behavior.

Categories

Resources