Spring boot log4j2 database appender - spring-boot

I am trying to use log4j2 database appender in a Spring boot project. I don't need any other database use in my project. I tried creating a ConnectionFactory using commons-dbcp2 and commons-pool2 (used sample codes available ), but unfortunately, Spring boot is failing during Startup, stating that it's unable to access ConnectionFactory. Seems like log4j2 is initialized before the ConnectionFactory. Is there a simple way to integrate log4j2 database appender in Spring boot, or it's something not possible? I don't want to make it complicated, and might use a different toolset, if these frameworks are not supposed to collaborate in a simpler manner.
Code that I used for ConnectionFactory:
DriverManagerConnectionFactory connectionFactory = new DriverManagerConnectionFactory(databaseUrl, properties);
PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null);
GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<PoolableConnection>(
poolableConnectionFactory);
poolableConnectionFactory.setPool(connectionPool);
this.dataSource = new PoolingDataSource<PoolableConnection>(connectionPool);

Related

Can't deploy Spring Boot (v2.6.6) project to Weblogic (v12.2.1.3) , due to javax.naming.NameNotFoundException

I'm trying to deploy a Spring boot application to weblogic, and connect the app to a Gridlink datasource using this method in #configuration to get the data source.
#Bean(name = "dataSourceA",destroyMethod = "")
public DataSource dataSourceA() throws NamingException {
JndiTemplate jndiTemplate = new JndiTemplate();
InitialContext ctx = (InitialContext) jndiTemplate.getContext();
return (DataSource) ctx.lookup(env.getProperty("DatabaseAGridLink"));
}
On Weblogic, the JNDI name for the data source is "DatabaseAGridLink", which I am hardcoding in the creation of the bean.
However, when I compile my project into a .war file and host on Weblogic- it runs into an error when searching for the data source:
javax.naming.NameNotFoundException: Unable to resolve 'DatabaseAGridLink'. Resolved ''; remaining
name 'DatabaseAGridLink'
If I restart my Weblogic, it no longer errors and the Spring Boot application can connect to the datasource on Weblogic, run db queries- functioning without issues. Problem is, this isn't a real solution- as any time the project is updated the Weblogic needs to be restarted and there are other applications running which makes this impossible irrespective of being a bad solution in the first place.
Thinking it's an issue with how the datasource is initialized in Spring boot, I have tried other methods of connection such as:
#Bean
public DataSource dataSourceA() throws Exception{
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
return dataSourceLookup.getDataSource("DatabaseAGridLink");
}
Or different ways of specifying the JNDI name on both data source initialization beans:
ctx.lookup(env.getProperty("java:jdbc/DatabaseAGridLink"));
ctx.lookup(env.getProperty("jdbc/DatabaseAGridLink"));
ctx.lookup(env.getProperty("java:comp/jdbc/DatabaseAGridLink"));
dataSourceLookup.getDataSource("java:jdbc/DatabaseAGridLink");
etc..
These changes has had no effect, other than the name no longer being found as none of these other naming schemes are valid.
What could be causing this failure of datasource connection between Spring Boot and a Weblogic instance? (Especially considering that it succeeds after weblogic is restarted, which seems to imply that the Spring boot app is indeed looking for the correct JNDI name with it's bean and this isn't a naming problem)

Creating a custom FactoryBean in Sprint Boot 2.3/Spring 5

I've got a spring-boot web application that's mostly working; my DataSource is properly configured by an external application.properties file.
Now I want to add properties to that file to help me instantiate and configure two instances of a class in my app. I have a APNsFactory that I currently instantiate manually and configure using JNDI, but I want to get away from JNDI calls:
#Bean
public
APNsFactory
apnsFactory()
throws
javax.naming.NamingException
{
sLogger.info("Configuring APNsFactory");
InitialContext ctx = new InitialContext();
APNsFactory f = new APNsFactory();
f.setProductionKeystorePath((String) ctx.lookup("java:comp/env/apns/prod/keystorePath"));
f.setProductionKeystorePassword((String) ctx.lookup("java:comp/env/apns/prod/keystorePassword"));
f.setDevelopmentKeystorePath((String) ctx.lookup("java:comp/env/apns/dev/keystorePath"));
f.setDevelopmentKeystorePassword((String) ctx.lookup("java:comp/env/apns/dev/keystorePassword"));
return f;
}
When running before in a standalone webapp container, Spring properly called that method and the JNDI context from the container’s <env-entry> tags was available.
I'm trying to update my APNsFactory to be a proper Spring FactoryBean<>, and I’ve given it a couple of #Autowire String variables that I want to be set by Spring Boot from the application.properties file.
For bonus points, I want this to be usable both in Spring Boot and in a standalone container like Tomcat or Resin.
For the life of me, I can't figure out how to get Spring to do this. There are dozens of examples for DataSources and other Beans already implemented by Spring, but none for a completely custom one, using application.properties, in a Spring Boot web environment.
I've seen some examples that use an XML config file, but I'm not sure how to do that with Spring Boot.
I don't think you need a factory bean here.
You already have spring boot that can read application.properties out-of-the-box:
So try the following:
Create key/values in the application.properties file:
myapp.keystore.path=...
myapp.keystore.passwd=...
// the same for other properties
Create ConfigurationProperties class
#ConfigurationProperties(prefix="myapp.keystore")
public class MyAppKeyStoreConfigProperties {
private String path; // the names must match to those defined in the properties file
private String passwd;
... getters, setters
}
In the class marked with #Configuration (the one where you create #Bean public APNsFactory apnsFactory()) do the following:
#Configuration
// Note the following annotation:
#EnableConfigurationProperties(MyAppKeyStoreConfigProperties.class)
public class MyConfiguration {
// Note the injected configuration parameter
#Bean public APNsFactory apnsFactory(MyAppKeyStoreConfigProperties config) {
APNsFactory f = new APNsFactory();
f.setProductionKeystorePath(config.getKeyPath());
and so on
}
}
I've intentionally didn't show the separation between production/dev stuff.
In spring boot you have profiles so that the same artifact (WAR, JAR whatever) can be configured to run with different profile and depending on that the corresponding properties will be read.
Example:
If you're running with prod profile, then in addition to application.properties that will be loaded anyway, you can put these keystore related definitions to application-prod.properties (the suffix matches the profile name) - spring boot will load those automatically. The same goes for dev profile of course.
Now I haven't totally understand the "bonus points" task :) This mechanism is spring boot proprietary way of dealing with configuration. In "standalone" server it should still have a WAR with spring boot inside so it will use this mechanism anyway. Maybe you can clarify more, so that I / our colleagues could provide a better answer

Spring boot provided "spring.datasource.password" can change to "spring.ds.pwd" without creating new bean for DataSource

My team is using latest spring boot for one of the project.
Spring provides database configuration in application.properties file and for password this is the key "spring.datasource.password"
Now, we want to change this to "spring.ds.pwd", but, the change should not required to create new Bean for datasource is it possible?
I followed below link, but, here new beans are creating to handle the session, which should not be expected. Other search information is also similar.
https://dzone.com/articles/spring-boot-jpa-mysql-sample-app-code-example
I was able to achieve what I want by overriding the DataSourceProperties java class with same package name.

Spring boot activemq overriding the connection factory

I am new to Spring boot and i am trying to lookup my own connection factory instead of using the default 'ConnectionFactory' which Spring boot provides and also trying to lookup the already defined queue without using dynamicqueues.
How can i do that?
Should i add jndi.properties file and add it there so i can lookup?
Can someone suggest?
The Spring Integration configuration by default is looking for a
Spring Bean called ‘connectionFactory’.
Spring Boot by default,
creates the JMS connection factory using the name
‘jmsConnectionFactory’.
#Bean
public ConnectionFactory jmsConnectionFactory() {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost");
return connectionFactory;
}
https://github.com/spring-projects/spring-boot/blob/v1.5.9.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQConnectionFactoryConfiguration.java

Spring Boot with Legacy tables

I want to use Spring Boot with Legacy database and use hibernate for the same. I have to access both DB2 and Teradata as data sources.I would like to know if this is possible ? I'm a newbie to Spring , SpringBoot and have no idea how to configure data sources , should i still need multiple xml configs etc. The demos in spring io sites are good but they dont deal with any of my requirement. Kindly point me in the right direction.
In Spring Boot it is very easy to configure multiple datasources. This part of the documentation describes the procedure in detail.
In essence, all you need to do is have the connection properties in a place where Spring boot can locate them (the easiest place is application.properties) and then configure the beans. The code would look like:
application.properties
datasource.primary.url=jdbc:mysql://localhost/test
datasource.primary.username=dbuser
datasource.primary.password=dbpass
datasource.secondary.url=jdbc:mysql://localhost/test2
datasource.secondary.username=dbuser2
datasource.secondary.password=dbpass2
Spring configuration file
#Bean
#Primary
#ConfigurationProperties(prefix="datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
#Bean
#ConfigurationProperties(prefix="datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
You will notice that no XML configuration is used which the preferred style these days. Actually using Spring Boot means that you don't have to write almost any configuration :)

Resources