Reading database properties from property source not working - java

I want to read my database property values from the application.property file but not being able to.
I tried reading the properties from custom properties file but it didnt work. I don't want to hard code the properties as it will will be different in different servers.
#Configuration
#PropertySource("application.properties")
public class DatabaseUtils {
#Value("${mysql.drive}")
private static String MY_SQL_DRIVER;
#Value("${mysql.url}")
private static String MY_SQL_URL;
#Value("${mysql.username}")
private static String DATABASE_USERNAME;
#Value("${mysql.password}")
private static String DATABASE_PASSWORD;
public DatabaseUtils () {
}
#Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
public static ResultSet executeDBQuery(String query) {
try {
Class.forName(MY_SQL_DRIVER);
Connection connection = DriverManager.getConnection(MY_SQL_URL, DATABASE_USERNAME, DATABASE_PASSWORD);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(query);
return resultSet;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
(properties file)
# database
databaseDriver=com.mysql.jdbc.Driver
databaseUrl=jdbc:mysql://localhost:3306/school
databaseUsername=root
databasePassword=root
I am new to spring-boot so getting a little confused as to why its not working, read a lot of online sources and tried them but didnt work, not sure what I am missing. Any help will be appreciated.

The properties in your property file is different from what you are giving in #Value.for eg. your property key is databaseDriver but you are giving mysql.drive in your code.
#Value("${mysql.drive}")
private static String MY_SQL_DRIVER;
But it should be
#Value("${databaseDriver}")
private static String MY_SQL_DRIVER;

basically what properties you define in the properties file should be referred in the application right. Here you are defining property as databaseDriver.
databaseDriver=com.mysql.jdbc.Driver
Then in code also you should ask for "databaseDriver"
#Value("${databaseDriver}")
private static String MY_SQL_DRIVER;

Related

How to know underlying DB type in static constructor

I have an issue where I need to use a different type for UUID depending on whether the database used is MSSQL (production) or H2 (tests).
To accomplish this, I created a custom type as below (adapted from here):
private static final long serialVersionUID = 902830399800029445L;
private static final SqlTypeDescriptor SQL_DESCRIPTOR;
private static final JavaTypeDescriptor TYPE_DESCRIPTOR;
static {
String dialect = ???; //<-- how can this be known?
if(dialect.equals("org.hibernate.dialect.PostgreSQLDialect")) {
SQL_DESCRIPTOR = null;//UUIDCharType.INSTANCE;
} else if(dialect.equals("org.hibernate.dialect.H2Dialect")) {
SQL_DESCRIPTOR = BinaryTypeDescriptor.INSTANCE;
} else {
throw new UnsupportedOperationException("Unsupported database!");
}
TYPE_DESCRIPTOR = UUIDTypeDescriptor.INSTANCE;
}
public UUIDCustomType() {
super(SQL_DESCRIPTOR, TYPE_DESCRIPTOR);
}
#Override
public String getName() {
return "uuid-custom";
}
}
I then register the type as:
#TypeDefs({
#TypeDef(
name="uuidmapper",
defaultForType = UUID.class,
typeClass = UUIDCustomType.class
)
})
The trouble I am having how can I check whether the application is using H2 or MSSQL in deciding what UUID type descriptor to use.
Note this is a Spring Boot application with JPA. I thought to use the url in the application.yml file but this does not seem possible from the static constructor (or at least I cannot make it work).
I thought perhaps I could dynamically see what class was loaded at runtime. I am not sure if there is a better way to do this. Another idea I had was to instead use two separate custom Dialects - one for H2 and one for MSSQL.

Accessing injected properties results in NullPointerException

This is the first time for me working with Quarkus and CDI and I think I'm getting it wrong.
In my application users can download some files. I'd like to control how many files are being downloaded simultaneously. I thought I could do this by creating a bean with #ApplicationScoped annotation, forcing instantiation at startup, and then injecting it wherever I need to know how many files are currently downloading.
This is what I managed to do:
#ApplicationScoped
public class DownloadState {
private int downloadingFiles;
void startup(#Observes StartupEvent event) {
setDownloadingFiles(0);
System.out.println("downloading files: " + downloadingFiles);
}
public int getDownloadingFiles() {
return downloadingFiles;
}
public void setDownloadingFiles(int downloadingFiles) {
this.downloadingFiles = downloadingFiles;
}
public void incrementDownloadingFiles() {
downloadingFiles++;
}
public void decrementDownloadingFiles() {
downloadingFiles--;
}
}
Doing this I can see the log at startup saying "downloading files: 0", so I know the class has been instantiated.
I try to access the number of downloading files here:
public class Downloader {
private static final Logger LOG = Logger.getLogger(Downloader.class);
#Inject
DownloadState downloadState;
private Dotenv dotenv = Dotenv.configure()
.directory("../")
.filename(".env.local")
.load();
private String fileName = dotenv.get("DOWNLOAD_PATH");
private String url;
public Downloader(String url, String fileName) {
this.url = url;
this.fileName += fileName;
}
public void downloadProduct() {
LOG.info("Downloading Files: " + downloadState.getDownloadingFiles());
//...
}
}
Whenever downloadProduct is called a NullPointerException is thrown on the line LOG.info("Downloading Files: " + downloadState.getDownloadingFiles());
Am I getting CDI totally wrong? Any help is really appreciated, thank you in advance.
I assume you're calling the Downloader constructor directly -- in which case, indeed no injection will happen and your downloadState will be null. Dependency injection is "contagious" -- you have to use it everywhere.
In your case, I'd probably just make Downloader also #ApplicationScoped, inject it everywhere you use it, and probably move the url and fileName parameters from constructor to downloadProduct. Actually at that point, the number of downloadingFiles could also be in Downloader. (Also note that it can be accessed from multiple threads -- so I'd probably use an AtomicInteger for downloadingFiles.)
All in all, something like this:
#ApplicationScoped
public class Downloader {
private static final Logger LOG = Logger.getLogger(Downloader.class);
private final AtomicInteger downloadingFiles = new AtomicInteger(0);
private final String downloadPath = Dotenv.configure()
.directory("../")
.filename(".env.local")
.load()
.get("DOWNLOAD_PATH");
public void downloadProduct(String url, String fileName) {
String path = downloadPath + fileName;
int current = downloadingFiles.incrementAndGet();
LOG.info("Downloading Files: " + current);
//...
}
}

Connection class with #value properties [duplicate]

This question already has answers here:
Spring: How to inject a value to static field?
(5 answers)
Closed 4 years ago.
I am a beginner with Spring and I am working on a spring-boot project with Jooq.
I created an application properties
which loads the database access settings,
it's working, but I need a connection class that returns a connection object for me to use when needed.
It would be better if this class had a static getConnection method. I wrote the class as #Component and I put my
#Value but all these attributes are null when I try to use them.
Is there another way to do this?
Thank you so much.
#Component
public class ConnectionFactory {
#Value("${bws.codigo.escola}")
static private String codigoEscola;
#Value("${bws.driver.connection}")
static private String driver;
#Value("${bws.database.name}")
static private String nameDb;
#Value("${bws.database.user}")
static private String user;
#Value("${bws.database.password}")
static private String password;
#Value("${bws.database.server}")
static private String server;
#Value("${bws.string.connection}")
static private String firstUrlPart;
#Value("${bws.string.connectionLast}")
static private String lastPartUrl;
#Value("${bws.database.port}")
static private String port;
static String strConnection = firstUrlPart+server+":"+port+"/"+nameDb+lastPartUrl;
public static Connection getConnection() throws SQLException {
try {
Class.forName(driver);
return DriverManager.getConnection(strConnection,
user,password);
} catch (ClassNotFoundException e) {
throw new SQLException(e.getMessage());
}
}
}
that way I would use it in other classes
try (Connection con = ConnectionFactory.getConnection()) {
DSLContext ctx = DSL.using(con, SQLDialect.MYSQL);
int count = ctx.selectCount()
.from(ALUNO)
.fetchOne(0, int.class);
return count;
}
You could, of course, go ahead and inject all the values required to create a JDBC connection for each of your query on an ad-hoc basis. Or, much better, you inject a pre-configured DSLContext singleton instance that wraps the JDBC connection through a DataSource (ideally implemented by a connection pool).
The Spring Boot manual illustrates how this can be done:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html#boot-features-jooq
A more complete example can be seen here:
https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-spring-boot-example
The goal would be to have:
class SomeClass {
#Autowired
DSLContext ctx;
public int countAluno() {
return ctx.selectCount()
.from(ALUNO)
.fetchOne(0, int.class);
}
}

.properties as final static variable

I've got a .properties in my java project, that is updated by shell script.
I want to get this properties values and use it as final static variable. Here is my .properties code
WEBURL=http://popgom.fr
NODEURL=http://192.168.2.30:5555/wd/hub
I know I can get and use my .properties using this :
Properties prop = new Properties();
InputStream input = new FileInputStream("config.properties");
// load a properties file
prop.load(input);
String urlnode = prop.getProperty("NODEURL");
What I want to do is to get this String in every class of my project, without adding the code bellow in every classes.
How can I do this ? I've try to do an Interface, without success.
Any of you have an idea ?
Thanks for help
you can do it using Singleton pattern:
Example:
public class MyProperties{
private static MyProperties instance = null;
private Properties prop;
private MyProperties() {
InputStream input = new FileInputStream("config.properties");
// load a properties file
prop.load(input);
}
public static MyProperties getInstance() {
if(instance == null) {
instance = new MyProperties();
}
return instance;
}
public Properties getProperty() {
return prop;
}
}
You can invoke this code everywhere:
....
....
MyProperties.getInstance().getProperty();
....
....

Servlet init and Class

I actually have a programm with a servlet :
#WebServlet("/Controler")
public class Controler extends HttpServlet {
}
I need to use a property file : file.properties in my program. To load it, I have a class :
public class PropLoader {
private final static String m_propertyFileName = "file.properties";
public static String getProperty(String a_key){
String l_value = "";
Properties l_properties = new Properties();
FileInputStream l_input;
try {
l_input = new FileInputStream(m_propertyFileName); // File not found exception
l_properties.load(l_input);
l_value = l_properties.getProperty(a_key);
l_input.close();
} catch (Exception e) {
e.printStackTrace();
}
return l_value;
}
}
My property file is in the WebContent folder, and I can access it with :
String path = getServletContext().getRealPath("/file.properties");
But I can't call theses methods in another class than the servlet...
How can I access to my property file in the PropLoader class ?
If you want to read the file from within the webapp structure, then you should use ServletContext.getResourceAsStream(). And of course, since you load it from the webapp, you need a reference to the object representing the webapp: ServletContext. You can get such a reference by overriding init() in your servlet, calling getServletConfig().getServletContext(), and pass the servlet context to the method loading the file:
#WebServlet("/Controler")
public class Controler extends HttpServlet {
private Properties properties;
#Override
public void init() {
properties = PropLoader.load(getServletConfig().getServletContext());
}
}
public class PropLoader {
private final static String FILE_PATH = "/file.properties";
public static Properties load(ServletContext context) {
Properties properties = new Properties();
properties.load(context.getResourceAsStream(FILE_PATH));
return properties;
}
}
Note that some exceptions must be handled.
Another solution would be to put the file under WEB-INF/classes in the deployed webapp, and use the ClassLoader to load the file: getClass().getResourceAsStream("/file.properties"). This way, you don't need a reference to ServletContext.
I would recommend to use the getResourceAsStream method (example below). It would need that the properties file be at the WAR classpath.
InputStream in = YourServlet.class.getClassLoader().getResourceAsStream(path_and_name);
Regards
Luan

Categories

Resources