How can I check if the connection to Filenet was successful? - java

My Spring Boot application should connect to Filenet, which it is doing fine with the Filenet Java SDK. Now I'd like to implement a health indicator, to periodically check if the connection is still okey. Which leads me to my question:
How do I check if the connection to Filenet is successful?
What I've already tried
Creating a connection and checking if I can get the ObjectStore, which always works and never throws any error:
Connection conn = com.filenet.api.core.Factory.Connection.getConnection("https://...");
Subject subject = UserContext.createSubject(conn, "User", "password", "jaasStanzaName");
UserContext uc = UserContext.get();
uc.pushSubject(subject);
ObjectStore os = Factory.ObjectStore.getInstance(Factory.Domain.getInstance(conn, null), "objectStoreName");
Trying to do any SQL query works sort of, because it throws an EngineRuntimeException.
// Same connection as above
SearchSQL sqlObject = new SearchSQL("SELECT * FROM ...");
SearchScope searchScope = new SearchScope(conn.getObjectStore());
IndependentObjectSet results = searchScope.fetchObjects(sqlObject, null, filter, true);
But using an Exception for logic and method flows seems to me like bad code.
So are there any good methods or tried practices that I am missing?
Thanks in advance

So I eventually solved it myself, although I'm sure there are better ways to do this.
fnService is a class that essentially does what the code in the question does: creating a connection and executing an SQL query. The query doesn't really have to make much sense, even if it finds nothing it won't throw an exception. It will have to be valid SQL though.
#Component
public class FilenetHealthIndicator implements HealthIndicator {
private final FilenetService fnService;
#Autowired
public FilenetHealthIndicator(FilenetService fnService) {
this.fnService = fnService;
}
#Override
public Health health() {
log.debug("Executing automated health check Filenet");
try {
//We try to make an SQL query, if something doesn't work it will throw an EngineRuntimeException
this.fnService.searchObjectStoreWithSqlQuery("SELECT Id FROM Document WHERE Id = '{B1111111-1111-1111-AFB1-1111CD1DF11E}'");
} catch (EngineRuntimeException e){
log.error("Automated health check cannot connect to Filenet");
return Health
.down(e)
.build();
}
log.debug("Automated health check to Filenet succeeded");
return Health
.up()
.build();
}
}

Related

WildFly/Jboss/persistance-unit/Entity Manager - How to create new connection every time when user calls GET API Endpoint

I'm trying to modify existing Java app (WildFly, Jboss, oracle) which currently working fine as using persistence-unit and EntityManager connect to Oracle database(using standalone.xml and persistence.xml). However, I need to create every time new connection to database for the user which calls new GET API Endpoint using credentials from the HttpHeaders. Currently, I'm creating new entitymanager object which session is commit, rollback nad close. Unfortunately time response for every call become higher and higher. There is warning about "PersistenceUnitUser" being already registered and memory usage constantly growing. So that is bad solution.
Is there any proper way to do it, which works witout any harms ?
P.S.
Currently app using standalone.xml and persistence.xml. And that is working fine. I'm calling java api endpoint using entity manager being connected as Admin user/pass but I need to create new connection using user/pass from the httpHeaders and call one sql statement to see proper results as ORACLE uses reserved word such us: 'user'. For instance : select * from table where create_usr = user. When done 'Main EntityManager will use data from it to continue some process.
Please see code example below :
#GET
#Path("/todo-list-enriched")
#Produces(MediaType.APPLICATION_JSON)
public Response getToDoListEnriched(#Context HttpHeaders httpHeaders, #QueryParam("skip") int elementNumber, #QueryParam("take") int pageSize, #QueryParam("orderby") String orderBy)
{
String userName = httpHeaders.getHeaderString(X_USER_NAME);
String userName = httpHeaders.getHeaderString(X_PASSWORD);
EntityManager entityManager = null;
try {
Map<String, String> persistenceMap = new HashMap<String, String>();
persistenceMap.put("hibernate.dialect","org.hibernate.dialect.Oracle8iDialect");
persistenceMap.put("hibernate.connection.username", asUserName);
persistenceMap.put("hibernate.connection.password", asPassword);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PersistenceUnitUser", persistenceMap);
entityManager = emf.createEntityManager();
if (!entityManager.getTransaction().isActive()) {
entityManager.getTransaction().begin();
}
-- Do some works as select, update, select
-- and after that
if (entityManager.getTransaction().isActive()) {
entityManager.getTransaction().commit();
}
}
catch (Exception ex)
{
if (entityManager != null && entityManager.getTransaction().isActive()) {
entityManager.getTransaction().rollback();
}
}
finally {
if (entityManager != null && entityManager.isOpen()) {
entityManager.close();
}
}
}
}
``
Best Regards
Marcin
You should define a connection pool and a datasource in the standalone.xml (cf. https://docs.wildfly.org/26.1/Admin_Guide.html#DataSource) and then use it in your persistence.xml and inject the EntitytManager in your rest service class (cf. https://docs.wildfly.org/26.1/Developer_Guide.html#entity-manager).
You may look at this example application: https://github.com/wildfly/quickstart/tree/main/todo-backend

Why oracle data base change listener is triggering multiple events in case of single update? [duplicate]

I need some Listener for any change(update, insert, delete) of Oracle database table.
Problem: I get many detection by single update on my table.
I think its oracle cache etc.
Is it possible only real changes to detect?
my code:
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleDriver;
import oracle.jdbc.OracleStatement;
import oracle.jdbc.dcn.DatabaseChangeEvent;
import oracle.jdbc.dcn.DatabaseChangeListener;
import oracle.jdbc.dcn.DatabaseChangeRegistration;
public class OracleDCN {
static final String USERNAME = "scott";
static final String PASSWORD = "tiger";
static String URL = "jdbc:oracle:thin:#localhost:1521:stingdev";
public static void main(String[] args) {
OracleDCN oracleDCN = new OracleDCN();
try {
oracleDCN.run();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void run() throws Exception{
OracleConnection conn = connect();
Properties prop = new Properties();
prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS, "true");
DatabaseChangeRegistration dcr = conn.registerDatabaseChangeNotification(prop);
try{
dcr.addListener(new DatabaseChangeListener() {
public void onDatabaseChangeNotification(DatabaseChangeEvent dce) {
System.out.println("Changed row id : "+dce.getTableChangeDescription()[0].getRowChangeDescription()[0].getRowid().stringValue());
}
});
Statement stmt = conn.createStatement();
((OracleStatement) stmt).setDatabaseChangeRegistration(dcr);
ResultSet rs = stmt.executeQuery("select * from EXAMPLE where ID=1");
while (rs.next()) {
}
rs.close();
stmt.close();
}catch(SQLException ex){
if (conn != null)
{
conn.unregisterDatabaseChangeNotification(dcr);
conn.close();
}
throw ex;
}
}
OracleConnection connect() throws SQLException {
OracleDriver dr = new OracleDriver();
Properties prop = new Properties();
prop.setProperty("user", OracleDCN.USERNAME);
prop.setProperty("password", OracleDCN.PASSWORD);
return (OracleConnection) dr.connect(OracleDCN.URL, prop);
}
}
Output:
Changed row id : AAAFSzAAAAAAAG8AAA
Changed row id : AAAFSzAAAAAAAG8AAA
Changed row id : AAAFSzAAAAAAAG8AAA
Changed row id : AAAFSzAAAAAAAG8AAA
Problem was I registered to database many times. The solution was check registered user for change events before register.
I checked that with this query:
select TABLE_NAME
from USER_CHANGE_NOTIFICATION_REGS
As already said you are responsible for releasing your DatabaseChangeNotification by unregistering them at your connection. In my case for some reason I am doing this when application server starts on tomcat. First I am releasing old registrations and then create new. I think I can reuse the old registration but anyway i am not.
I am doing something like this:
This query returns existing registrations. You must login as the same user that registered the notification.
SELECT REGID, CALLBACK FROM USER_CHANGE_NOTIFICATION_REGS
then code like this pseudo code unregisters the notification.
connection.unregisterDatabaseChangeNotification(REGID, CALLBACK) this is called for every row returned by the query.
Something else I found is that when updating a row using PL/SQL Developer using the included editor I receive multiple notifications for the same update. When using sql to update the row I receive one notification as expected. I don't know why is this happening but it is happening.
The point is that according to
https://docs.oracle.com/cd/E18283_01/appdev.112/e13995/oracle/jdbc/OracleConnection.html
you are responsible for releasing your DatabaseChangeNotification by unregister them at your Connection. Otherwise as described "The registration will continue to live after this connection is closed. You need to explicitly unregister it to destroy it in the server and release the resources in the driver."
Meaning if you test your sample code and you kill it, your registrations remains living on the server and you receive extra notifications after registering next DatabaseChangeNotification. Unfortunately I haven't found out yet hot to reconnect with living registration - I would need regId for that, but I have no clue yet how to obtain it from the OracleConnection.
From what I've read so far, I'm a bit confused as well.
Have you tried printing out the transactionId to see if it is, in fact, a unique event being generated?
System.out.println("DCE : regId="+dce.getRegristrationId()+"; transactionId="+dce.getTransactionId());
The listeners that I've been working with for JMS require an acknowledgment, but I don't see anything of that sort in the Oracle docs (http://docs.oracle.com/cd/B28359_01/java.111/b31224/dbmgmnt.htm).
I also found that it might disturb the oracle cache if the event treatment is unthreaded, but it looks you're already doing that too...
Good luck!
You will get an event for each commit that modifies one of the tables you're using in your query (in your code sample only one table called "EXAMPLE"). Think of it as "Table Change Notification" TCN. In other words you may get a lot of false positives because you're only interested in one row but you'll be notified if other rows are changed. It's then up to you to filter the events. This is why this feature should only be used for read mostly tables.
In 11gR2, Oracle improved this notification mechanism to allow a finer notification called "Query Change Notification". This time you will only be notified by changes that affect your query results. There is an option that needs to be turned on to enable QCN instead of TCN. Note that the server may not always be able to enable QCN. If the query is too complex it will fall back to TCN.
Please modify the event handler as follows:
public void onDatabaseChangeNotification(DatabaseChangeEvent dce) {
if (e.getRegId() == dcr.getRegId())
System.out.println("Changed row id : "+dce.getTableChangeDescription()[0].getRowChangeDescription()[0].getRowid().stringValue());
}
Correcting typo error:
Please modify the event handler as follows:
public void onDatabaseChangeNotification(DatabaseChangeEvent dce) {
if (dce.getRegId() == dcr.getRegId())
System.out.println("Changed row id : "+dce.getTableChangeDescription()[0].getRowChangeDescription()[0].getRowid().stringValue());
}

how can i connect from java to mysql server?

The error is that I cant open the connection to mysql database, it must be an error in parameters but I am confused , I have no idea where is the problem.
First you need to create a MySQL schema. Secondly, use JDBC to connect to your recently created database (via localhost - make sure you get the user/password right).
After that you should use DAO-like classes. I'll leave here a Connect class:
public class Connect {
private static final String USERNAME = "root";
private static final String PASSWORD = "12345";
private static final String URL = "localhost";
private static final String SCHEMA = "new_schema";
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection connect() throws SQLException {
return DriverManager.getConnection("jdbc:mysql://"+URL+"/"+SCHEMA+"?user="+USERNAME+"&password="+PASSWORD);
}
}
After you have the Connect class, you should connect to the database using Connection c = Connect.connect(). Here's a class that implements it.
public static List<Album> list() throws SQLException {
Connection c = Connect.connect();
ResultSet rs = c.createStatement().executeQuery("SELECT * FROM Albums");
List<Album> list = new ArrayList<>();
while (rs.next()) {
String name = rs.getString("nome"); // first table column (can also use 1)
String artist = rs.getString("artista"); // second table column (can also use 2)
Album a = new Album(name, artist);
list.add(a);
}
return list;
}
It should also give you an insight as to how you should use SQL commands.
If you'd like a more in-depth help you should post the code you used, otherwise it's difficult to give you a more "to-the-point" explanation.
JDBC URLs can be confusing. Suggest you try using a SQL tool that understands the JDBC protocol (such as the database development perspective in Eclipse) to validate the URL and make sure you can connect to the database before you start coding. Cutting and pasting a URL known to work into your code can avoid many problems.

Java JDBC efficiency: How long should a connection be maintained?

I'm still working on the same problem mention here. It seems to work fine especially after creating an AbstractModel class shown below:
public abstract class AbstractModel {
protected static Connection myConnection = SingletonConnection.instance().establishConnection();
protected static Statement stmt;
protected static ResultSet rs;
protected boolean loginCheck; // if userId and userLoginHistoryId are valid - true, else false
protected boolean userLoggedIn; // if user is already logged in - true, else false
public AbstractModel (int userId, Long userLoginHistoryId){
createConnection(); // establish connection
loginCheck = false;
userLoggedIn = false;
if (userId == 0 && userLoginHistoryId == 0){ // special case for login
loginCheck = true; // 0, 0, false, false
userLoggedIn = false; // set loginCheck to true, userLogged in to false
} else {
userLoggedIn = true;
try{
String query = "select \"user_login_session_check\"(" + userId + ", " + userLoginHistoryId + ");";
System.out.println("query: " + query);
stmt = myConnection.createStatement();
rs = stmt.executeQuery(query);
while (rs.next()){
loginCheck = rs.getBoolean(1);
}
} catch (SQLException e){
System.out.println("SQL Exception: ");
e.printStackTrace();
}
}
}
// close connection
public void closeConnection(){
try{
myConnection.close();
} catch (SQLException e){
System.out.println("SQL Exception: ");
e.printStackTrace();
}
}
// establish connection
public void createConnection(){
myConnection = SingletonConnection.instance().establishConnection();
}
// login session check
public boolean expiredLoginCheck (){
if (loginCheck == false && userLoggedIn == true){
closeConnection();
return false;
} else {
return true;
}
}
}
I've already posted the stored procedures and Singleton Pattern implementation in the link to the earlier question above.
I'm under the impression that I don't need to close the connection to the database after each single data transaction, as it would just slow the application. I'm looking at about 30 users for this system I'm building, so performance and usability is important.
Is it correct to prolong the connection for at least 3-4 data transactions? Eg. Validation checks to user inputs for some form, or, something similar to google's auto-suggest ... These are all separate stored function calls based on user input. Can I use one connection instance, instead of connecting and disconnecting after each data transaction? Which is more efficient?
If my assumptions are correct (more efficient to use one connection instance) then opening and closing of the connection should be handled in the controller, which is why I created the createConnection() and closeConnection() methods.
Thanks.
Your code should never depend on the fact, that your application is currently the only client to the database or that you have only 30 users. So you should handle database connections like files, sockets and all other kinds of scarce resources that you may run ouf of.
Thus you should always clean up after yourself. No matter what you do. Open connection, do your stuff (one or SQL statements) and close connection. Always!
In your code you create your connection and save it into a static variable - this connection will last as long as your AbstractModel class lives, probably forever - this is bad. As with all similar cases put you code inside try/finally to make sure the connection gets always closed.
I have seen application servers running ouf of connections because of web applications not closing connections. Or because they closed at logout and somebody said "we will never have more then that much users at the same time" but it just scaled a little to high.
Now as you have your code running and closing the connections properly add connection pooling, like zaske said. This will remedy the performance problem of opening/closing database connection, which truely is costly. On the logical layer (your application) you doesn't want to know when to open/close physical connection, the db layer (db pool) will handle it for you.
Then you can even go and set up a single connection for your whole session model, which is also supported by DBCP - this is no danger, since you can reconfigure the pool afterwards if you need without touching your client code.
Like Tomasz said, you should never ever depend on the fact that your application will be used by a small number of clients. The fact that the driver will timeout after a certain amount of time does not guarantee you that you will have enough available connections. Picture this: a lot of databases come pre-configured with a maximum number of connections set to (say) 15 and a timeout of (let's say) 10-15 minutes. If you have 30 clients and each does an operation, somewhere around half-way you'll be stuck short on connections.
You should handle connections, files, streams and other resources the following way:
public void doSomething()
{
Connection connection = null;
Statement stmt = null;
ResultSet rs = null;
final String sql = "SELECT ....");
try
{
connection = getConnection();
stmt = connection.createStatement();
rs = stmt.executeQuery(sql);
if (rs.next())
{
// Do something here...
}
}
catch (SQLException e)
{
e.printStackTrace();
}
finally
{
closeResultSet(rs);
closeStatement(stmt);
closeConnection(connection);
}
}
The try/catch/finally guarantees you that the connection will get closed no matter the outcome. If there is some sort of failure, the finally block will still close the connection, just like it would do, if things were okay.
Similarly, with file and streams you need to do the same thing. Initialize the respective object as null outside your try/catch/finally, then follow the approach above.
This misconception makes a lot of Java applications misbehave under Windows, where people don't close files (streams to files, etc) and these files become locked, forcing you to either kill the JVM, or even restart your machine.
You can also use a connection pool such as for example Apache's DBCP, but even then you should take care of closing your resources, despite the fact that internally, the different connection pool implementations do not necessarily close the connections.
You'are right that you don't need to close the connection after each call.
Bare in mind that that modern database implement internal connection pools, but your application still need to connect and retrieve a connection object, and this is what it does now.
You should consider using a database connection pool - there are various Java frameworks to provide you such a solution, and they will define (you will be able to configure of course) when a database connection pool is closed.
In general - you should ask yourself whether your database serves only your application, or does it serve other application as well - if it does not serve other application as well, you might be able to be more "greedy" and keep connections open for a longer time.
I would also recommend that your application will create on start a fixed number of connections (define it in your configuration with a value of "Minimum connections number") and you will let it grow if needed to a maximum connection numbers.
As I previously mentioned - the ideas are suggest are implemented already by all kinds of frameworks, for example - the DBCP project of Apache.
Here is the Singleton Pattern which I initialize the myConenction field in all my Models to:
public class DatabaseConnection {
private static final String uname = "*******";
private static final String pword = "*******";
private static final String url = "*******************************";
Connection connection;
// load jdbc driver
public DatabaseConnection(){
try{
Class.forName("org.postgresql.Driver");
establishConnection();
} catch (ClassNotFoundException ce) {
System.out.println("Could not load jdbc Driver: ");
ce.printStackTrace();
}
}
public Connection establishConnection() {
// TODO Auto-generated method stub
try{
connection = DriverManager.getConnection(url, uname, pword);
} catch (SQLException e){
System.out.println("Could not connect to database: ");
e.printStackTrace();
}
return connection;
}
}
public class SingletonConnection {
private static DatabaseConnection con;
public SingletonConnection(){}
public static DatabaseConnection instance(){
assert con == null;
con = new DatabaseConnection();
return con;
}
}
Of course each and every connection to the database from the app goes through a Model.

Hibernate: Simulate testConnectionOnCheckout option effect by java code

I'm using a web application and, sometimes, I have MySql connection problems.
Using the testConnectionOnCheckout and preferredTestQuery options in the Hibernate configuration file, I resolved the problem and my application is ok now.
But, for better performance, I'd like to obtain the effects of this option only when a particular event occurs in my application. For example:
try {
...........
}
catch(Exception e) {
// java code to obtain the same effect as
// testConnectionOnCheckout option with "Select 1" query
}
What Java code do I have to use?
The best way to answer such a question is to look it up in the source. So I encourage you to get the source of Hibernate and find the code that tests the connection.
but anyway, here's something simple
public static boolean checkConnection(String jdbcUrl, String user, String password){
boolean result = false;
try {
Configuration config = new AnnotationConfiguration().configure();
config.setProperty("hibernate.connection.url", jdbcUrl);
config.setProperty("hibernate.connection.username", user);
config.setProperty("hibernate.connection.password", password);
sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession();
Assert.assertFalse(sesssion.connection.isReadOnly());
result = true;
} catch(Throwable ex) {
return = false;
}
return result;
}

Categories