Changing Spring bean properties on fly - java

I've got the following problem. There are 2 datasources for 2 dbs: current(A) and stand by(B). If A doesn't respond, I will try to connect B.
This is how I acheave that.
Interceptor checks if connection is bad
Interceptor will swap datasource URL, if something goes wrong
Datasources are Spring beans. So I change Spring bean properties on fly. Is that ok? Look at the code:
#Autowired
#Qualifier("dataSourceMain")
private oracle.jdbc.pool.OracleDataSource dsMain;
#Autowired
#Qualifier("dataSourceStandBy")
private oracle.jdbc.pool.OracleDataSource dsStandBy;
public void swapURL() {
try {
String dsMainURL = dsMain.getURL();
dsMain.setURL(dsStandBy.getURL());
dsStandBy.setURL(dsMainURL);
} catch (Exception e) {
e.printStackTrace();
}
}
As I can see, my code works, but I don't know if it's good approach or not.

Can you check if this solves your problem? Seems like a similiar question
dynamically change Spring data source
Which seems to be done in a more elegant way

If your data sources are pooled, then they will have a pool of connections waiting to be used or re-used. Depending on your strategy for pooling, your code could have no effect as you aren't telling the data source to evict existing pooled connections that are using the old URLs.
On a general point I suggest you use AbstractRoutingDataSource to safely swap datasources. See here
How to make safe frequent DataSource switches for AbstractRoutingDataSource?

Related

Postgres Hibernate set session variables for row level security

I am having trouble finding information about this issue I am running into. I am interested in implementing row level security on my Postgres db and I am looking for a way to be able to set postgres session variables automatically through some form of an interceptor. Now, I know that with hibernate you are able to do row-level-security using #Filter and #FilterDef, however I would like to additionally set policies on my DB.
A very simple way of doing this would be to execute the SQL statement SET variable=value prior to every query, though I have not been able to find any information on this.
This is being used on a spring-boot application and every request is expected to will have access to a request-specific value of the variable.
Since your application uses spring, you could try accomplishing this in one of a few ways:
Spring AOP
In this approach, you write an advice that you ask spring to apply to specific methods. If your methods use the #Transactional annotation, you could have the advice be applied to those immediately after the transaction has started.
Extended TransactionManager Implementation
Lets assume your transaction is using JpaTransactionManager.
public class SecurityPolicyInjectingJpaTransactionManager extends JpaTransactionManager {
#Autowired
private EntityManager entityManager;
// constructors
#Override
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
super.prepareSynchronization(status, definition);
if (status.isNewTransaction()) {
// Use entityManager to execute your database policy param/values
// I would suggest you also register an after-completion callback synchronization
// This after-completion would clear all the policy param/values
// regardless of whether the transaction succeeded or failed
// since this happens just before it gets returned to the connection pool
}
}
}
Now simply configure your JPA environment to use your custom JpaTransactionManager class.
There are likely others, but these are the two that come to mind that I've explored.

Is it possible to compact an embedded HSQL DB from a Spring Boot application?

I've created a Spring Boot application with an embedded, file-based HSQL database. The data file being created is getting fairly large, especially given the usage model, so I'm wondering if there is a way it can be compacted? Either manually or automatically?
The HSQL documentation indicates that there is a SHUTDOWN COMPACT command (which might take a while, according to the documentation), but I can't figure out how to configure Spring Boot to use it.
I'm open to forcing a SHUTDOWN COMPACT when shutting down the Spring Boot application (if that's the only option), or finding a way to issue a manual "compact" command (if HSQLDB supports such a command), or any other suggestions folks might have.
As mentioned, previous answer is one option, but the suggestion by boly38 is cleaner, and became my preferred approach.
#PreDestroy
public void preDestroy() {
try {
jdbcTemplate.execute("SHUTDOWN COMPACT");
} catch (DataAccessException e) {
// do nothing
}
}
This allows the application to control when the DB is compressed, and removes a potentially bad option from the end-user's hand.
Not sure if this is the best solution, but I did manage to find a solution. I added a REST API that can manually execute a CHECKPOINT DEFRAG command on the database.
In the main Spring Boot application class, I added a method for getting a JdbcTemplate like this:
#Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
I then decided to create a new REST controller (rather than use an existing one), to provide an API to manually compact the DB:
#RestController
#RequestMapping("/admintools")
public class TEVAdminToolsController {
#Autowired
private JdbcTemplate jdbcTemplate;
#GetMapping("/compressDB")
public Boolean compressDB() {
try {
jdbcTemplate.execute("CHECKPOINT DEFRAG");
} catch (DataAccessException e) {
return false;
}
return true;
}
}
This isn't great from a security perspective; for my use case that isn't a concern but for others it's probably a non-starter.
The two main points in this:
The #Bean for getting a JdbcTemplate
The call to jdbcTemplate.execute() for executing the "raw" SQL command

Embedded Derby in OSGi, creating multiple connection using connection pool

I want to create instances of a class which will have access to the underlying Embedded derby database and pass this class to each bundle binding to my database bundle using declarative services.
I have seen in the derby documentation that sharing one connection for multiple threads has many pitfalls. So I was thinking to create a connection for each instance of the class I am creating. Since I only want a very simple way to just create multiple connections and manage them, using "MiniConnectionPoolManager" here seems like a good option. The sample code for derby is shown below:
org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource dataSource = new org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource();
dataSource.setDatabaseName("c:/temp/testDB");
dataSource.setCreateDatabase("create");
MiniConnectionPoolManager poolMgr = new MiniConnectionPoolManager(dataSource, maxConnections);
...
Connection connection = poolMgr.getConnection();
...
connection.close();
But the documentation does not cover many things plus I am a beginner in using Database. My questions are:
When I am creating a new class that will need database connection to perform insert,update & other actions. Shall I pass the 'poolMgr' and call poolMgr.getConnection() from the newly created class?
When should I close this connection? I don't know for how long the bundle (user) will use the new class so shall I save the newly created connection in a private global variable and force the user to execute unregister class where I could then close the connection? Or shall I just close all connections when my database bundle is being deactivated.
Other suggestions are also appreciated to manage different classes accessing one database. Thank you in advance.
Edit:
The main class in my database bundle is always active as long as the application is running. It is the bundles requesting for an instance of a new class(performing database operation) that come and go. And also since it will be deployed in embedded system, I can only use small footprint applications.
You should get a connection from a connection pool when you need it and close the connection as soon as you can. It is the job of the connection pool to re-use connections, not yours.
In other words: Do not keep a connection alive until your consumer bundle is deactivated.
Connection pools normally implement DataSource interface, you should use the pools via it. In that case you can replace the pool implementation easily without changing your code. E.g:
#Component
public class MyComponent {
// Connection pool based DataSource
#Reference
DataSource dataSource;
public void myFunction() {
try (Connection c = dataSource.getConnection()) {
// Database operations
} catch (SQLException e) {
// TODO
}
}
}
When you find yourself repeating the same code many times (getting connection, catching SQLException), you can write a simple component that accepts functional interfaces. E.g.:
#Component
#Service
public class SQLHelper {
#Reference // This is a connection pool DataSource
private DataSource dataSource;
public <R> R execute(Callback<R> callback) {
try (Connection c = dataSource.getConnection()) {
return callback.call(c);
} catch (SQLException e) {
throw new UncheckedSQLException(e);
}
}
}
Your functional interface would look like this:
public interface Callback<R> {
R call(Connection connection);
}
And you would use it like this:
sqlHelper.execute((Connection c) -> {
// Do some stuff with the connection
});
Using transactions
If you want to use atomic transactions, I suggest that you should use org.apache.derby.jdbc.EmbeddedXADataSource together with org.apache.commons.dbcp.managed.BasicManagedDataSource from commons-dbcp. After that, you can handle transactions via JTA.
It is hard to use the JTA API directly. You should choose a library that helps you propagating transactions.
A small guide based on Declarative Services:
Install derby jar into your OSGi container
Install pax-derby bundle as well! By doing that, you will have a DataSourceFactory OSGi service
Install everit-dsf-bundle with its dependencies! You will see two new DS components. Create a configuration for the one called XADataSource via the webconsole! All configuration options have descriptions.
Install a JTA Transaction Manager into the OSGi container! You have several choices. I
Install everit-commons-dbcp-component with its dependencies! You will see two new DS components. Configure the Managed one in the webconsole and set the previously created XADataSource as the target! The transactional pool will take care of providing the same connection if you request-and-close connections whitin the scope of the same transaction.
normally use Aries Transaction Manager that embeds Geronimo TM.
Install everit-transaction-helper to your OSGi container! You will see a new OSGi service with the interface TransactionHelper (that is provided by a configurable DS component).
Now you have everything to write your code. Your component would similar to the following:
#Component
#Service
public class MyComponent {
#Reference
private DataSource dataSource;
#Reference
private TransactionHelper th;
public void myFunction() {
th.required(() -> {
try (Connection c = dataSource.getConnection()) {
// My SQL statements
} catch (SQLException e) {
// TODO
}
}
}
}
In case you do not need transaction handling, you can:
use the standard EmbeddedDataSource
use any non-transactional connection pool
skip the installation of the TransactionManager and TransactionHelper bundles
skip the usage of TransactionHelper from the code
A more complex guide (that also takes care of schema creation and uses OO based queries) is available at http://cookbook.everit.org/persistence/index.html.
Update
You do not have to get a connection for every SQL statement. You should get a connection, execute as many SQL statements that you can within a "moment" and than call close on the connection.
If you have to run three SQL statements right behind each other, you should request a connection, execute the three SQL statements and than call close on the connection
If you close the requested connection within the same function you requested it from the pool, you probably do things right. You might call other functions passing the connection as a parameter, but they should only use it to run SQL statements and than return.
You should not keep alive a connection and wait for another user action. That is the job of the connection pool. When you call close on a connection that is provided by a pool, the connection is not closed physically, but only retrieved to the pool.
You should keep the connection object in a local variable. If you use a member variable for your connection object, you should suspect that something is wrong with your code (the only exception is if you pass the Connection to an object that lives for a very short time and that object holds the connection in a member variable to have cleaner code).
Please note that if you use Java 6 or earlier, you should close the connection in a finally block to avoid unclosed connections.
MiniConnectionPoolManager might be a great solution for embedded devices as it is really "mini". The only issue is that it does not implement the DataSource interface so your business code shuold directly use the MiniCPM classes. By doing that, it will be much harder to switch to other Connection pool if you find a bug or you need a more complex pool later.
If you decide to use MiniCPM, I suggest that you should write a component that implements DataSource and delegates the getConnection() function to a MiniCPM instance. E.g.:
#Component
#Service
public class MiniCPMDataSourceComponent implements DataSource {
#Reference
protected ConnectionPoolDataSource cpDataSource;
private MiniConnectionPoolManager wrapped;
#Activate
public void activate() {
this.wrapped = new MiniConnectionPoolManager(cpDataSource);
}
#Override
public Connection getConnection() {
return wrapped.getConnection();
}
#Override
public Connection getConnection(String user, String password) {
throw new UnsupportedOperationException();
}
#Deactivate
public void deactivate() {
wrapped.dispose();
}
}
You can decorate this component with configuration possibilities like the max connection number and timeout (that is supported by MiniCPM). If you use the service that is provided by this component, you will be able to switch the connection pool without changing your business code. Also, your business bundle will not be wired directly to MiniCPM.

Making #Schedule run only once in a clustered environment

I have two tomee instances clustered.
Each one have a method annotated like
#Schedule(dayOfWeek = "*")
public void runMeDaily() {...}
I'd like to run this method only once a day. Not twice a day (one on each instance)
I could use a flag as described here Run #Scheduled task only on one WebLogic cluster node? or just elect some node, but I wonder if there's a more elegant way to do that.
This question is somewhat related to EJB3.1 #Schedule in clustered environment but I am not using JBOSS. (and it's not answered)
Im using same approach as in other thread - checking that particular host is the correct one to run job. But..
Im not very info ee tools, but in spring you can use profiles for that. Probably you can find similar solution for your needs. Take a look at http://spring.io/blog/2011/06/21/spring-3-1-m2-testing-with-configuration-classes-and-profiles
You can define two seperate beans:
#Configuration
#Profile("dev")
public class StandaloneDataConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.addScript("classpath:com/bank/config/sql/test-data.sql")
.build();
}
}
#Configuration
#Profile("production")
public class JndiDataConfig {
#Bean
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
and decide which one to turn on by switching profile. So your class with method annotated #Scheduled would be loaded only for specific profile. Ofcourse then you need to configure your app to turn on profile on of the nodes only. In spring app it would be as simple as passing -Dspring.profiles.active=profile to one of them.
I could only solve this using a non-Java EE solution, specific to the platform (proprietary). In my case, I am using TomEE+ and Quartz. Running Quartz in the clustered mode (org.quartz.jobStore.isClustered = true) and persisting the timers in a single database forces Quartz to choose an instance to trigger the timer, so it will only run once.
This link was very useful -- http://rmannibucau.wordpress.com/2012/08/22/tomee-quartz-configuration-for-scheduled-methods/
It's a shame Java EE does not specify a behavior for that. (yet, I hope) :-)
I solved this problem by making one of the box as master. basically set an environment variable on one of the box like master=true.
and read it in your java code through system.getenv("master"). if its present and its true then run your code.
basic snippet
#schedule()
void process(){
boolean master=Boolean.parseBoolean(system.getenv("master"));
if(master)
{
//your logic
}
}

Is it allowed to have instance variables in Spring Services?

I have a spring service that provides configuration data. When the service is invoked by the GUI, it loads the configuration data from the database. It turns out that this happens quite often during the rendering of a single request. I want to optimize this by caching the configuration data. However, I am not sure if this is a good programming style or if it is "allowed" to have an instance variable in a service.
Here is some example code of what I am thinking of doing:
#Serivce("MyConfigService")
public class MyConfigServiceImpl implements MyConfigService {
private Config cachedConfig;
#Override
public Config loadConfig() {
if (cachedConfig != null) {
// load config
cachedConfig = loadedConfig;
}
return cachedConfig;
}
#Override
public saveConfig(Config config) {
cachedConfig = null;
// save the configuration
}
}
Having a instance variable (not managed by spring) introduces the possibility of the service becoming thread unsafe. So I try to avoid them, or make sure they are thread safe.
You may want to look at #configurable and #postconstuct annotations to achieve your goals.
Are instance variables allowed in Spring service layer classes? Sure.
Is it a good idea to use one to save a reference to the Config object here?
Maybe, maybe not.
You're not showing how Config normally gets loaded... Does the same Config instance get returned to all users? i.e. - When User1 calls saveConfig then User2 calls loadConfig User2 gets the Config object User1 saved.
If so, you should be able to cache the value with no problems.
Also, instead of implementing it yourself, you could use Spring's annotation-based caching.
Instance variables is what Spring IoC container is all about; what is dubious in your design is that you have your own lazy-loading logic in loadConfig—that's the concern you must leave to Spring via lazy-init=true (or similar, I don't remember exactly). The design will also probably involve lookup methods and posibly request-scoped beans.

Categories