How to make J2EE weblogic application resilient to database problems - java

I have a Web application running on Oracle Weblogic Server 11g.
It uses a datasource defined in the application server to connect to the Oracle Database (11g too), its class is
oracle.jdbc.xa.client.OracleXADataSource
If for some reason the database becomes not present and then comes
backs, the application is running ok (it gets exceptions while trying
to access the db but this is fine and then can again get some new
connections when the db comes back)
However, if the database is down during weblogic server startup,
the datasource is not deployed on the server and the application
throws an exception because it has not any datasource available, the
deployment is marked as failed and of course nothing does repair this
automatically.
Is there a way to make the datasource be deployed even if the database is not present during server startup ? (such that the application becomes usable when the database is back)

Why do you want to deploy an application without a valid datasource?
You could possibly fake the datasource (create a dummy datasource with the same JNDI name) and assuming that the application does not validate datasource schema at startup you will get a semi-functional running application (which will fail with the first DB interaction).
When the real datasource is up and running you won't be able to switch to it. You will still have to restart the application server.
Update:
According to the J2EE spec (1.5 version) resources are binded during the deployment process. I believe that it is possible to implement a custom Factory that will return dummy / active datasource. Does it worth the effort to implement? ;)
EE.5.6.2 Deployer’s Responsibilities
Bind the resource manager connection factory reference to a resource manager connection factory that exists in the operational environment. The Deployer may use, for example, the JNDI LinkRef mechanism to create a symbolic link to the actual JNDI name of the resource manager connection factory. The re- source manager connection factory type must be compatible with the type de- clared in the res-type element.

The option you are looking for is "Connection Creation Retries", check this link
"If set and if the database is unavailable when the data source is created, WebLogic Server attempts to create connections in the pool again after the number of seconds you specify, and will continue to attempt to create the connections until it succeeds. This option applies to connections created when the data source is created at server startup ..."

set "Initial Capacity" http://docs.oracle.com/cd/E14571_01/web.1111/e13814/jdbc_tuning.htm#i1028616 to 0: weblogic on startup will not attempt to create any connection, and will not fail if the DB is not available.

Related

How to handle re-connects to the DB with ActiveJDBC

I've a Spring Boot Java application in production that uses ActiveJDBC to access a MariaDB database.
If at launch the application boots before the db server, of if the db server crashes and restarts, the apps doesn't re-estabilish the connection with the db.
ActiveJDBC is on version 1.4.13 and if possible I'd prefer not upgrading it, to avoid possible breakages. The db parameters are configured using the database.properties file and typically the usage pattern is:
try {
Base.open();
...
} finally {
Base.close();
}
Is there a way to circumvent this problem, without monitoring and relaunching the application? Maybe using connection pools? If this is the case, are there any docs or examples?
If you are using a direct JDBC connection in your database.properties file, a new connection will be open every time you execute Base.open(). This means that any old connection that is broken is not relevant anymore. If you use a JDNI pool such as:
production.jndi=java:comp/env/jdbc/acme
then you want to configure your containers' pool to ensure that every connection served from the pool is valid just before the pool serves the connection to your app. It is up to the implementation and documentation of your container/pool how to do that.
In any case, I do not think you are going to have issues.

websphere wasjdbcDataSource to XADataSource

i already setup oracle xadatasource in websphere, and i want get datasource by using spring context lookup jndi , exception happen when i start my app : WasjdbcDataSource incompatible with javax.sql.XADataSource.
how can i solve this?
In a Java EE application server, such as WebSphere Application Server, even though you configure the XA-capable javax.sql.XADataSource, the application (and Spring) should always expect to use it as javax.sql.DataSource. Look in the Spring configuration if there is a way to indicate the expected type of javax.sql.DataSource rather than javax.sql.XADataSource. The XADataSource API is intended only for the application server's own internal use in order to accomplish two-phase commit. The user always interacts with it as javax.sql.DataSource, and gains the ability to enlist multiple resources in a single global transaction.

When to put configuration in file.properties or Jndi

For a long time in many IT services, I see some complex process to manage Java EE application configuration depending of the environments:
- custom tools, with Database or not, to manage replacement in the properties file (unzip war, replace, zip war...)
- Externalize properties file in obscure directory in the server (and some process to update it some time) and some time with a JNDI configuration...
- maven profile and lot of big properties files
But for database connection everybody use jndi datasource.
Why this is not generalized for all configurations that depend of environment ?
Update : I want deal with other variable than datasource, there is no question about datasource : it's in configured in JNDI for Java EE application. After if you want hack JNDI...
Setting up database connectivity (like user name, password, URL, driver etc.) somewhere in the application server has several advantages over doing it yourself in the WAR:
The app server can be a central point where the DB is configured, and you might have several WARs running on that server sharing a DB. So you need to set it up only once.
The DB settings, especially the credentials (username, password) are stored somewhere in the app server instead of somewhere in the WAR. That can have security implications (for instance, restricting access to that file is easier done than in a WAR archive).
You can set up one JNDI path to retrieve a DataSource instance pointing to the DB and do not need to worry about username and password anymore. If you have multiple app servers (one live system, one test system, several developer machines) with different DB URLs and credentials, then you can just configure that in each app server individually and deploy the WAR files without the need to change DB settings (see below).
The server might provide additional services, like connection pools, container managed transactions, etc. So again, you don't have to do it on your own in the WAR.
This is true for other services provided by the app server as well, for example JavaMail.
There are other cases where it you want to configure something that is specific to one web application and does not rely on the environment (the app server), like logging (although that may be set up in the app server, too). In those cases you might prefer using static config files, for instance log4j.properties.
I want to illustrate the third bullet point a bit further ...
Suppose you have one WAR in three app servers (developer machine, test server, live server).
Option 1 (DB setup in WAR)
Create a database.properties :
db.url=jdbc:mysql://localhost:3306/localdb
db.user=myusername
db.pass=mysecretpassword
#db.url=jdbc:mysql://10.1.2.3:3306/testdb
#db.user=myusername
#db.pass=mysecretpassword
#db.url=jdbc:mysql://10.2.3.4:3306/livedb
#db.user=myusername
#db.pass=mysecretpassword
Before you deploy it somewhere, you need to check if your settings are pointing to the right DB!
Also, if you check this file in to some version control system, then you might not want to publish your DB username/password to your local machine.
Option 2 (DB setup in App Server)
Imagine you have configured the three servers with their individual DB settings, and each of them registers the DB with the JNDI path java:database/mydb.
Then you can retrieve the DataSource like so:
Context context = new InitialContext();
DataSource dataSource = (DataSource) context.lookup("java:database/mydb");
This is working on every app server instance and you can deploy your WAR without the need to modify anything.
Conclusion
By moving the configuration to the app server you'll have the advantage of separating settings depending on the environment from your app code. I would prefer this whenever you have settings involving IP addresses, credentials, etc.
Using a static .properties file on the other hand is simpler to manage. I would prefer this option when dealing with settings that have no dependencies to the environment or are app specific.

Some confusion surrounding JDBC Resources and JDBC Connection pools Glassfish

I am about to make a connection to my database and I am using EJB and JPA. I have recently started doing these technologies so I have some problems understand it all at this point:)
I know that the persistence.xml is needed in order to use JPA. It is the file where I configure how to connect to the database, that I know. However it seems like there are multiple ways of doing it.
What would be the difference (or when should I even use the one alternative over the other?) of defining properties such as username, database, password etc. in the persistence.xml file and in Glassfish? Advantages/disadvantages if any.
Underneath on the image I posted I have JDBC Resources and JDBC Connection Pools. I am a litte confused about the terminology of the two. Why don't we add properties such as username, database, password and so on in the JDBC Resources? Could someone explain the difference between them and what they mean?
JDBC Resources
A JDBC resource (data source) provides applications with a means of
connecting to a database. Typically, the administrator creates a JDBC
resource for each database accessed by the applications deployed in a
domain. (However, more than one JDBC resource can be created for a
database.)
http://download.oracle.com/docs/cd/E19316-01/820-4335/ablih/index.html
I think it strange that we add such properties on the pool but not in the resource, but I probably misunderstand the concepts.
In the "JDBC connection pools" you can create container managed JDBC data sources (with connection pooling capabilities). The data source needs to know about at least the JDBC driver, the JDBC URL, username and password.
In the "JDBC resources" you can bind those container managed JDBC data sources to one or more JNDI names so that they are by JNDI available to the deployed web application.
In the persistence.xml you can specify whether to use a local data source or to use a container managed data source. If you want to use a container managed data source, then you should specify its JNDI name. Using a container managed data source has the advantage that you can share a single data source among multiple web applications. In case of JPA, it has also the advantage that you can make use of JTA (container managed transactions) so that you don't need to call transaction.begin(), commit(), rollback() etc in every method.

Context specific usernames for connections on a Java EE Datasource (JBoss 5.1)

We have an application that needs to access a database that is owned by a different team.
That database has security inside the database (triggers, table permissions, etc) and so we need to establish a connection to the database using the same username/password that connected to our EJB.
We're running on JBoss 5.1. Standard Java EE solutions are preferred, but JBoss specific answers will do.
At the moment our solution is
Create a datasource in JBoss with no user-id password
Require the client to pass their username/password into the EJB (the EJB is a stateful session bean (SFSB), and remembers the username/password)
The session bean creates a new connection using DataSource.getConnection(String, String)
The connection is "created" from the datasource at the start of each request (The datasource implementation might reuse an existing connection)
The main problem we have is connection pooling.
The JBoss connection pool doesn't manage separate pools for each username - they're all thrown into 1 big pool, and the username is checked after the object is retrieved from the pool (inside InternalManagedConnectionPool).
If the usernames don't match, then the connection is removed from the pool & destroyed.
This means that as soon as we have 2 users, there's a 50% chance that any connection that is put into the pool will be destroyed when it is next accessed. And as we increase the number of users, those odds get a lot worse.
We can't simply create 1 connection in the SFSB and retain it because JBoss is too smart for us, and it detects that we've left a connection open and automatically returns it to the pool for us, so the next request to the SFSB will fail with a "not associated" connection.
It would also be nice if we could simply get JBoss to create a connection as "the currently logged in user", but the solution we have is bearable.
My googling has failed to find any recommended patterns for doing this sort of thing. Everyone seems to assume that you want your datasource to use a single user for all connections (which is nice when it's possible, but I can't do that in this case)
The only solutions I can some up with are
Don't use a container provided datasource. Put the JDBC URL into a configuration value somewhere and create connections myself (possibly with the help of spring)
Bind a different Datasource implementation (possibly a custom one) into JNDI
Has anyone got any better solutions? Or pointers to recommended practices in this area?
(The database is Sybase ASE 15, but I doubt that makes any difference to the solution)
A bit more reading of the documentation has led me to what appears to be the solution.
Adding
<application-managed-security/>
into my datasource file seems to have fixed the problem of pooling the connections.
I'm not sure how I missed that the first time around.

Categories