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

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)

Related

TypeMismatchNamingException in spring boot with IBM MQ

I am trying to create a Spring boot project to read messages from a queue and do some processing.
I have defined the Jndi ConnectionFactory in application.properties
spring.jms.jndi-name=java:/MyConnectionFactory
On starting the application I am getting the following exception:
Caused by: org.springframework.jndi.TypeMismatchNamingException: Object of type [class com.ibm.mq.connector.outbound.ConnectionFactoryImpl] available at JNDI location [java:/MyConnectionFactory] is not assignable to [javax.jms.ConnectionFactory]
I am deploying the code on a jboss server with the given jndi.
Not sure if in this scenario some different implementation is needed for the ConnectionFactory.
#Bean public DefaultMessageListenerContainer orderMessageListenerContainer() {
DefaultMessageListenerContainer endpoint = new DefaultMessageListenerContainer();
endpoint.setMessageListener(new YourMessageListener());
endpoint.setDestination("yourDestination");
endpoint.setConnectionFactory(connectionFactory());
return orderDefaultJmsListenerContainerFactory().createListenerContainer(endpoint);
}
Solved manually with DefaultMessageListenerContainer.

Spring Boot and Spring Session: How to control the DataSource

I'm experimenting with Spring Boot and Spring session together, specifically using JDBC.
Just adding the line in application.properties:
spring.session.store-type=jdbc
made it just work, which is nice because I happen to also have some data source properties in that file, ie
myapp.datasource.url=jdbc:mysql://localhost/etc...
myapp.datasource.driver-class-name=com.mysql.jdbc.Driver
But I'm actually using those for my own data source with my own configuration, like so:
#Configuration
#PropertySource("classpath:credentials.properties")
public class DataSourceConfig {
#Primary
#Bean(name = "dataSource")
#ConfigurationProperties(prefix = "myapp.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
}
and as far as I can tell, Spring Session is creating its own data source instead of using mine. Is there a way I can get it to use mine instead?
(my real data source has some additional configs with Hikari not shown here)
Spring Session itself does not create DataSource but rather uses the one present in your application context, if it's the either:
the only DataSource bean
DataSource marked as #Primary
Also if you wish to use a specific DataSource for Spring Session (for example, if you have multiple DataSources in your application) you can do that by:
annotating DataSource marked as designated for Spring Session by #SpringSessionDataSource (Spring Session 2.0 onwards)
providing JdbcTemplate bean that uses the desired DataSource and naming it springSessionJdbcOperations (Spring Session 1.x)
The Spring Session JDBC configuration capabilities and logic should be quite easy to understand from the JdbcHttpSessionConfiguration.

Initialize standalone databases, Spring Boot and MyBatis

I'm building Spring Boot + MyBatis project using standalone postgresql database.
Well, for some reason, "convention-based" database initialization doesn't occur. I added data source manually, created sql-scripts, but when I run the project, from the log it's not even processing these scripts. I want to understand how the process works for not-embedded databases.
Can one create an instance of data source using code?
Should I link data source in property file or separate class?
What one should do to link separate data source (postgresql in this case) with Spring Boot configuration?
Yes
#Bean
public DataSource dataSource() {
DataSourceBuilder.create()
.url("jdbc:postgresql://localhost:5432/database")
.username("username")
.password("password")
...
.build();
}
2-3. You can use property file along with providing java based DataSourceConfiguration
spring.datasource.url: jdbc:postgresql://localhost:5432/database
spring.datasource.username: username
spring.datasource.password: pasword
And refers these properties in your Configuration class as follows:
#Bean
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
If you have only one database to connect to, the most convenient way is to add it's connection properties into property file, prefixed with spring.datasource (scroll here to check available options) and add org.postgresql dependency to pom.xml (build.grade) file and SpringBoot will do the rest.

Integrate Mongeez with Spring Boot and Spring Data MongoDB

I want to integrate Mongeez with my Spring Boot application and was wondering how to properly run Mongeez during application startup. Mongeez suggests creating a MongeezRunner bean. However, the challenge is to run Mongeez before any of the Spring Data initialization is happening, specifically, before the MongoTemplate instance is created. This is crucial because there might be changes in the database that prevent the application to start at all (e.g. changing index definitions).
My current approach is to provide the MongoTemplate bean myself, running Mongeez before creating it:
#Bean
public MongoTemplate mongoTemplate(Mongo mongo, MongoDbFactory mongoDbFactory,
MongoConverter converter) throws IOException {
// make sure that Mongeez runs before Spring Data is initialized
runMongeez(mongo);
return new MongoTemplate(mongoDbFactory, converter);
}
private void runMongeez(Mongo mongo) throws IOException {
Mongeez mongeez = new Mongeez();
mongeez.setMongo(mongo);
mongeez.setDbName(mongodbDatabaseName);
mongeez.setFile(new ClassPathResource("/db/migrations.xml"));
mongeez.process();
}
It works, but it feels like a hack. Is there any other way to do this?
After taking a look at Spring Boot's source code, it turns out that this problem isn't anything new. The FlywayAutoConfiguration for example has to make sure that Flyway (a migration tool for SQL-based databases) runs before any EntityManagerFactory beans are created. To achieve this the auto-configuration registers a BeanFactoryPostProcessor that dynamically makes every EntityManagerFactory bean depend on the Flyway bean, thus forcing Spring to create the Flyway bean first.
I solved my problem by creating a Spring Boot starter with a similar auto-configuration for Mongeez: mongeez-spring-boot-starter.

How do you use a Tomcat JNDI JDBC datasource in Spring Boot

I have a Spring boot application and want to deploy as a WAR to Tomcat 7. As part of this I need to keep configuration out of the WAR, so that I can deploy the same war to my stage and production servers and have it pickup the mysql connection via configuration.
To this end I want to configure my Spring Boot app to use a mysql connection configured as a JNDI datasource in the Tomcat instance.
Can spring boot do this and if so how?
Alternatively is this easy to do in Spring 4 without resorting to xml based configuration.
If you're using Spring Boot 1.2 or greater, this got easier. You can just add this to application.properties
spring.datasource.jndi-name=java:comp/env/jdbc/my_database
The relevant docs: http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html#boot-features-connecting-to-a-jndi-datasource
#Bean
public DataSource dataSource() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
DataSource dataSource = dataSourceLookup.getDataSource("jdbc/apolloJNDI");
return dataSource;
}
No "java:comp/env/" its needed because JndiDataSourceLookup internaly calls convertJndiName that add this part. In other clases you should set the complete path.
Here's what I had done.
Add the following to to Application.java
#Bean
public DataSource dataSource() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
DataSource dataSource = dataSourceLookup.getDataSource("java:comp/env/jdbc/mysqldb");
return dataSource;
}
Then follow the example in https://spring.io/guides/gs/accessing-data-jpa/ to set up the TransactionManager and Hibernate specific properties.
A hint for all of you using Spring Boot with an external Tomcat. Please ensure your war doesn't contain any tomcat jars. Multiple versions of same jar will produce hidden ClassCastException manifested by javax.naming.NamingException.

Resources