Servlet init and Class - java

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

Related

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);
//...
}
}

retrieve config data in java properties file from web service

I need your advice about the best way to retreive config data which is stored within a java properties file from jersey web services to use them in several DAO classes called by those web services.
The solution that I implement is as follow:
create a java properties file and put in it all properties that I need
all the java properties file in an application listener and put properties in servletcontext attribute
in a web service, I retreive properties by injecting an instance on servletContext using #Context annotation and I pass them to any DAO function's methodes that need them.
So is it a good approach? If not, could you suggest me another solution?
instead of putting individual property as attribute to context put property object in context and from that prop object get the properties where required.
Why not using a Singleton class in which you read your propertie file ,
and then create an applicationLister by implmenting ServletContextListener#contextInitialized method and call getInstance of your class (this step is not mandatory , so you can left it, it's just to instantiate the singleton at the start of the app container ),
Adter in your whole project just call the satic method YouClass.getInstance() and acces your Properties.
By example :
public class MyPropertieFileReader {
private static MyPropertieFileReader instance = null;
private Properties properties;
protected MyPropertieFileReader() throws IOException{
properties = new Properties();
properties.load(getClass().getResourceAsStream("path-to-property-file.properties"));
}
public static MyPropertieFileReader getInstance() {
if(instance == null) {
try {
instance = new TestDataProperties();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
return instance;
}
public String getProperty(String key) {
return properties.getProperty(key);
}
}
In your WS , just call
MyPropertieFileReader.getInstance().getProperty("property-name");
hope this will help .

.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();
....
....

Spring JUnit ApplicationContextInitializer parameters

We have implemented an extended .properties format. Such a properties file can contain an optional include property. The value of this properties is the classpaths of other properties files to load recursively.
I could configure the Spring environment for my application but I have a problem to engage this mechanism with SpringJUnit4ClassRunner.
I thought I could use the initializer property of the ContextConfiguration annotation but it looks it can only be instantiated with a no-arg constructor.
I need to give it the root file of my properties files hierarchy. It could eventually be another annotation on my test class, but again, how can I access it ?
The only think I have found so far is to set this file as a system property in my test class static initializer. ugly?:
#ActiveProfiles("qacs.controller.channels=mock")
#ContextConfiguration(initializer=ContainerTestContextInitializer.class)
public class QacsControllerTest
{
static
{
System.setProperty(ContainerTestContextInitializer.SYSTEM_PROPERTY, "classpath:com/xxx/qacs/QacsControllerTest.properties");
}
#Test
void test() {}
}
}
public class ContainerTestContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>
{
public static final String SYSTEM_PROPERTY = "icomp.test.properties";
#Override
public void initialize(ConfigurableApplicationContext pApplicationContext)
{
String path = System.getProperty(SYSTEM_PROPERTY);
if (path == null)
{
throw new IllegalStateException("Missing system property " + SYSTEM_PROPERTY);
}
final DefaultPropertiesLoader loader;
loader = new DefaultPropertiesLoader(System.getProperties());
try
{
loader.load(path);
}
catch (IOException e)
{
throw new IllegalStateException(e.getMessage(), e);
}
MutablePropertySources sources = pApplicationContext.getEnvironment().getPropertySources();
MapPropertySource mps = new MapPropertySource(Launcher.ICOMP_PROPERTY_SOURCE, (Map) loader.getProperties());
sources.addFirst(mps);
}
}

How to use config properties file throughout the classes?

I need my Java app to read the config properties from a file and use them throughout the classes. I'm thinking of a separate class, that would return a map of property_key:property_value for each of the properties in the file. Then I would read the values from this map in other classes.
Maybe there are other, more commonly used options?
My properties file is simple and has about 15 entries.
Just use java.util.Properties to load it. It implements Map already.
You can load and get hold of the properties statically. Here's an example assuming that you've a config.properties file in the com.example package:
public final class Config {
private static final Properties properties = new Properties();
static {
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
properties.load(loader.getResourceAsStream("com/example/config.properties"));
} catch (IOException e) {
throw new ExceptionInInitializerError(e);
}
}
public static String getSetting(String key) {
return properties.getProperty(key);
}
// ...
}
Which can be used as
String foo = Config.getSetting("foo");
// ...
You could if necessary abstract this implementation away by an interface and get the instance by an abstract factory.

Categories

Resources