Start Dropwizard with config.yaml from resources - java

I have a dropwizard question. I use Dropwizard with SBT (which works pretty fine).
If I run my application i package it with:
$ sbt clean assembly
And than run the application with:
$ java -jar APPLICATION.jar server
The problem is with this command Dropwizard doesnt load my config file (config.yaml), which is in the resources located.
Regarding the Dropwizard Docs I always have to give the config file as parameter like:
$ java -jar APPLICATION.jar server config.yaml
This works fine and it loads the application but is there any possibility to tell Dropwizard to load directly the config.yaml file, because my configuration in the config.yaml file is static and it is always the same. Settings like Database etc which are changing from Server Stage to Server Stage are made as Enviroment Variable which I load with EnvironmentVariableSubstitutor.
Thanks

Use class ResourceConfigurationSourceProvider:
#Override
public void initialize(final Bootstrap<ExampleConfiguration> bootstrap) {
bootstrap.setConfigurationSourceProvider(new ResourceConfigurationSourceProvider());
// The rest of initialize...
}
And then invoke the application like:
java -jar APPLICATION.jar server /resource-config.yaml
(note the initial /)

While this answer is very late, just thought I'd put this here. There is a dirty little hack to make it work so that you don't have to provide config.yaml in your application arguments.
Basically, you can submit a new String[] args to the run() method in the dropwizard application.
public class ApplicationServer extends Application<Config> {
public static void main(String[] args) {
String[] appArgs = new String[2];
appArgs[0] = args[0]; // This will be the usual server argument
appArgs[1] = "config.yaml";
new ApplicationServer().run(appArgs);
}
#Override
public void run(Config configuration, Environment environment) {
// Configure your resources and other application related things
}
}
I used this little trick to specify which config file I wanted to run with. So instead of specifying config.yaml, I would give my second argument as DEV/UAT/STAGE/PROD and pass on the appropriate config file to the run method.

Also interesting to have a look at:
earlye/dropwizard-multi-config
<dependency>
<groupId>com.thenewentity</groupId>
<artifactId>dropwizard-multi-config</artifactId>
<version>{version}</version>
</dependency>
It allows overriding and merging multiple config-files passed on the java command-line like:
java -jar sample.jar server -- sample.yaml override.yaml
Here you pass (1) sample.yaml as the primary configuration (e.g. having default values) and (2) override.yaml as the override. The effective config is a result from merging both in order of appearance: (1) defaults will be overwritten and merged with (2).

Related

Spring Boot: can't get API key into the docker container

I created an spring boot application that makes API calls. I have been given an API key that I added to my system environment variables as API_KEY
At first, I had my urls as
String uri = "http://api-site.com/.../key="+System.getenv("API_KEY")+"&..."
and this works just fine when I run it locally.
However, when I build and run the image, I get 403 error.
My Dockerfile looks like:
FROM maven:3.5.4-jdk-8-alpine AS builder
COPY pom.xml pom.xml
COPY src/ src/
RUN mvn clean package
FROM openjdk:11 AS runner
**ENV API_KEY $API_KEY**
EXPOSE 8080
COPY --from=builder target/app-0.0.1.jar app.jar
ENTRYPOINT [ "java", "-jar", "app.jar" ]
I'm guessing System.getenv("API_KEY") does not work in containers.
Is there a way to get it to work?
I've tried the other syntax for the environment variable in the Dockerfile: ENV API_KEY=${API_KEY}
I have also tried using application.properties but I have not been able to get that to work (this might need to be a whole other question). I can't even get test variables to print.
I have test.name=testname in applications.properties
In a class I have:
#Component
#PropertySource("classpath:application.properties")
public class AC {
#Value("${test.name}")
public String test;
public static void main(String[] args){
System.out.println(test);
}
}
This just prints out null every time.
Thank you in advance!

Java application not reading environment variables from .env file

I am creating a Slack bot using Bolt framework in Java + Maven following this tutorial on their official website. My bot requires some keys that should be present as environment variables.
The application works just fine when I export those variables in the terminal prior to executing the application like this.
export SLACK_BOT_TOKEN=xoxb-...your-own-valid-one
export SLACK_SIGNING_SECRET=123abc...your-own-valid-one
mvn compile exec:java -Dexec.mainClass="hello.MyApp"
But when I don't, and instead save them in a .env file, the App constructor apparently doesn't get those keys even though I have loaded them in the main method from .env file.
Here is my main method:
package hello;
import com.slack.api.bolt.App;
import com.slack.api.bolt.jetty.SlackAppServer;
import io.github.cdimascio.dotenv.Dotenv;
public class MyApp {
public static void main(String[] args) throws Exception
{
Dotenv dotenv = Dotenv.configure().directory("./").load();
System.out.println(dotenv.get("SLACK_BOT_TOKEN"));
System.out.println(dotenv.get("SLACK_SIGNING_SECRET"));
// CREATING THE SLACK APP
App slackApp = new App();
slackApp.command("/mytesthello", (req, ctx)-> {
return ctx.ack(":wave: Hello!");
});
SlackAppServer slackAppServer = new SlackAppServer(slackApp);
slackAppServer.start();
}
}
The console is able to show the correct output using System.out.println indicating that the variables are accessible, but most probably the App() constructor is not able to get them, since whenever I try to make POST request from my slack app, the ngrok interface as well as my terminal show unauthorized access. (again, this is the case when I don't export the environment variables)
What should I do to make sure that the environment variables are available from .env file? Otherwise it would be very cumbersome to keep exporting them whenever I run the application.

Spring Boot: Restart programtatically including VM and program arguments and classpath

We have a spring boot web application that we start with a modified, extended start command similar to this:
java -classpath "..." -Dlogging.config="..." org.springframework.boot.loader.JarLauncher --debug --spring.config.location="..."
Now, we need to restart this application programatically (e.g. via an endpoint), but we need to ensure that the "same start command is used".
I found this solution on bealdung:
#SpringBootApplication
public class Application {
private static ConfigurableApplicationContext context;
public static void main(String[] args) {
context = SpringApplication.run(Application.class, args);
}
public static void restart() {
ApplicationArguments args = context.getBean(ApplicationArguments.class);
Thread thread = new Thread(() -> {
context.close();
context = SpringApplication.run(Application.class, args.getSourceArgs());
});
thread.setDaemon(false);
thread.start();
}
}
In this case, the program arguments can be extracted with the bean ApplicationArguments.
So far I did not find a way to do the same for VM arguments and also the extension of the classpath as seen in the command above.
Is that even possible? Is there a more convenient way to restart a spring boot application with all these requirements in mind?
The way you've found in tutorial does not restart the whole JVM process, it closes the application context and re-creates it. This means that all the beans get loaded again which is logically equivalent to restart as far as all the objects are managed by Spring or course.
There as also a way of making such a restart without writing custom code - use Spring Boot's actuator that has a restart endpoint. You can invoke the endpoint and the application will be restarted in the same sense as you've described. See this tutorial for example there are many others.
In both of the ways, there will be the same JVM process (jvm does not restart), so both classpath and JVM parameters will remain just the same (do not change).
So if you want to restart the JVM you can wrap the long command into some sort of script (like bash if you're working on linux, or *.bat file for windows for example).
Other than that spring boot can't help much - from this perspective its a regular java application.

Hibernate database connection error in Maven Dropwizard

I have been trying a Dropwizard project using Maven. I can run hello world programs. When I tried to run database program using Hibernate, I got an error like below when running the program using java -jar.
default configuration has the following errors:
* database.driverClass may not be null (was null)
* database.url may not be null (was null)
* database.user may not be null (was null)
* template may not be empty (was null)
This is my hello-world.yml file
template: Hello, %s!
defaultName: Stranger
database:
driverClass: com.mysql.jdbc.Driver
user: root
password:
url: jdbc:mysql://localhost/test
Thanks in advance !!
As stated in some examples throught the Dropwizard repository, you may need to provide your template file configuration so that database properties are pulled out from there.
So have you tried running you application to set up your database with the .yml file as a command line argument? Something like the following:
java -jar your-artifact.jar db migrate your-configuration-file.yml
Then run your application as follows:
java -jar your-artifact.jar server your-configuration-file.yml
I was having the same error, but a different solution fixed it. You're supposed to pass in your yml file as an argument when you run an io.dropwizard.Application in server mode. For example
public static void main(String[] args) throws Exception {
new ApiApplication().run(new String[] {"server", "db.yaml"});
}
Adding the "db.yaml" argument to my array of strings fixed it. Or if you're passing your args from the termina/console, you'd want to add "yourconfig.yaml" or "yourconfig.yml" as the 2nd argument.
Source of the solution I found

Setting resource directory for ESAPI

Working with OWASP's ESAPI, I found myself stuck at this particular line of code.
private static String customDirectory = System.getProperty("org.owasp.esapi.resources");
The code returns null as there is no such system property "org.owasp.esapi.resources" set on my computer. Is there any way to set this property on my computer permanently?
You need to pass it into your JVM as a command line property. Most application containers use the environment variable JAVA_OPTS as a "permanent" store of options that should be passed to the JVM. You can try to do something like this:
In *nix:
export JAVA_OPTS="-Dorg.owasp.esapi.resources=/path/to/esapi/configuration"
In windows:
set JAVA_OPTS="-Dorg.owasp.esapi.resources=C:\path\to\esapi\configuration"
You can add this to windows or linux as a startup command and it will always be set if you desire, or add it to your application's startup script for a more localized solution.
If you put the ESAPI.properties and Validation.properties inside the resources folder it will recognize automatically.
In case you need to specify s specific folder or sub-folders, one possibility is adding this property in your standalone.
<system-properties>
<property name="org.owasp.esapi.resources" value="C:/.../resources/esapi"/>
<system-properties>
However, in unit tests, you have to specify before the tests.
#BeforeClass
public static void before() {
if(System.getProperty("org.owasp.esapi.resources") != null) {
System.out.println(System.getProperty("org.owasp.esapi.resources"));
} else {
System.setProperty("org.owasp.esapi.resources", "src/main/resources");
}
}

Categories