Reputation: 67
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.
Upvotes: 2
Views: 2007
Reputation: 6607
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);
//...
}
}
Upvotes: 4