I have written a custom spring cloud stream sink application that starts up when I run it as a spring boot project in eclipse. When I deploy my application I need to pass in some system proeprties. See below.
#ComponentScan
#EnableConfigurationProperties(MyProperties.class)
#SpringBootApplication
public class MyApplication {//extends SpringBootServletInitializer{
public static final String COMPONENT_NAME = "my-application";
#Autowired
private MyProperties properties;
public static void main(String[] args) {
System.setProperty("server.env", "DEVT1");
System.setProperty("some.other.var", "foo");
SpringApplication.run(MyApplication.class, args);
}
I am trying to pass these system properties into dataflow using the Deployment Properties screen, picture below. I am wondering if I pass one of these if it is working. It seems like my application starts up but is looking for the other property. When I try passing both I get this weird error saying the main class can not be found. So when I pass one my application seems to get farther. Am I close to being on the right track? Do I need to separate the arguments some way? I tried with commas but it didn't seem to make a difference.
Error when passing two arguments -
Error: Could not find or load main class
LURzZXJ2ZXIuZW52PVBEMDYsLURBbWljYV9RdWV1ZV9NYW5hZ2Vycz1HV0QwNiwtRGNmZ21nci5jbGFzcy5wYXRoPVxhbWljYS5jb20MaWxlcxtudmNvbmZpZwdwcHJlc291cmNlcw==
So the picture in my post above is actually correct for setting jvm arguments. My error stemmed from one of my jvm arguments being a file path that was not exposed through docker. Make sure use-spring-application-json is unchecked if you specify your jvm args this way. So this is valid for passing jvm arguments...
through docker /res/ maps to a folder on my c drive.
Related
i'm currently working on a little application with springBoot and got a configuration class like this :
#Configuration
public class ConfigurationExample {
#Value("${some.property}")
private String myProperty;
}
I'm not passing this value with the application.properties file but directly while launching the app
java -jar myApp.jar --some.property="Hello"
if i don't call the '--some.property="Hello"' it result on a big java error
I wanted to know if there is a way to catch this? In order to be able to print a clearer message
Thank you
The value binding happening at the run time(When Application start). If you forget pass then Application context initialization will fail.
This is application start issue
Better to use as below.
environment.gerProperty("key");
And add global exception handler and throw customized exception of value null.
if property does not exists and you still want to load application context
then you can do something like this
#Value("${some.property=: #{null}}")
private String some;
We have converted an existing web app over to Spring Boot.
All I want to to do is be able to use #Profile("production"). We store that in myProps.properties in the resources folder.
I can access the .properties file all over the app just fine using #Value, but it seems in order to get the #Profile to work, you have to set the active profiles before the ServletContext is set/final which seems to happen during the main() method.
I've tried dozens of things and failed. I've found you can't set a static field with #Value in the main application class. I've tried making a class that implements WebApplicationInitializer like https://www.baeldung.com/spring-profiles but my onStartup() method that I override doesn't ever get run.. I put in a break point and it never gets hit. The only way I can get a break point to hit is if I #Autowire the servletContext on that method, but then the context is already set and cannot be altered.
I've tried AnnotationConfigWebApplicationContext, I've tried ServletContainerInitializer, I've tried ConfigurableEnvironment, etc. I feel like I'm going in circles.
I feel like there is a big piece I'm missing here in order to do things the "Spring way". Can anyone offer Java annotation-configured way for me to get a property and set the active profiles for using later in the product? Thanks.
Why do you need it before main? Why don't you just create multiple properties files and define the profile in the top-level property file?
(parent) application.properties
spring.profiles.active = development-application.properties
(profile) development-application.properties
my.value = foo
Based on your comments, I suggest something like the following as a solution:
Define your tasks as beans with #Components and annotate them with #Profile to divide them up by the environment you want them to be used in (I prefer setting profiles as environment variables).
#Component
#Profile("production")
public class TaskA implements Task {
public void doWork(){}
}
#Component
#Profile("staging")
public class TaskB implements Task {
public void doWork(){}
}
Marking these classes with #Component means Spring will manage them and they can be injected, perhaps into a #Component that executes the tasks:
#Component
public class TaskDoer {
private List<Task> tasksToDo;
#Inject
public TaskDoer(List<Task> tasksToDo) {
this.tasksToDo = tasksToDo;
}
}
When deploying your app, set the profile to use in the environment variables in whatever way is appropriate for your setup:
SPRING_PROFILES_ACTIVE = production, someOtherProfile
Now, when the application starts, Spring will see that the active profiles are "production" and "someOtherProfile" (multiple profiles can be set) and will not load any beans with an #Profile that aren't for that profile.
This question already has answers here:
Running code after Spring Boot starts
(18 answers)
Closed 4 years ago.
I am building an application using Java Spring where I would like to run some environment setup code before my application starts handling requests. In this particular example, I'm using PayPal Rest SDK and I would like to set up some notification webhooks for my application. For obvious reasons I don't want to have an endpoint to call to set up the webhooks after the application is started, so putting it in my controller is probably not a good idea, and I need some Spring configuration information to set it up so I can't put it in main(). I'm ok with (in fact I'd even prefer) the application crashing if the webhooks fail to be created, if that's a constraint that needs to be considered.
What's a good way to do this?
Thanks.
and I need some Spring configuration information to set it up so I can't put it in main()
The above statement is not true. You can access your Spring configuration in a main. Consider the following example.
#SpringBootApplication
public class Main {
#Autowire
private MyService service;
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(InterviewHqApplication.class, args);
ctx.getBean(Main.class).setup();
}
private void setup() {
service.doStuff();
}
}
In this example, the setup() method is called after the application context has loaded.
There are actually several ways to do what you are attempting. Spring boot also supports using ApplicationRunner and CommandLineRunner, which both call a run method after the application context has been loaded an alternative to what I have shown above. You can also listen for an ApplicationReadyEvent and you could call #PostConstruct do perform some specific configuration on a bean after it's initialized.
I want to integrate Spring Shell within a spring boot application. I am able to execute the examples from the official git-repo. But when migrating the example code to my own project that is very very similar to this code, my individual shell is not shown or usable. Instead the default Spring Shell splash is shown is usable:
<SpringShell ASCII-Art>
1.1.0.RELEASE
Welcome to Spring Shell. For assistance press or type "hint" then hit ENTER
spring-shell>
Compilation gives no errors, but the individual sample #component marked classes are not used. All annotations are properly set. A standard loader outside is existent. I am not executing the code in an IDE.
Although the documentation (chapter 3.5) tells, that the components are automatically collected as far as i understood.
So my question is more or less how to setup the usage better than
this:
public class Main {
public static void main(String[] args) throws Exception {
Bootstrap.main(args);
}
}
And to defeat the default splash!
That comment in the documentation is a bit misleading (I'll change it).
For your components to be picked up, they need to be on the classpath AND you'll need to scan for them somehow.
See for example how in the Spring XD project, there is a scan for the org.springframework.xd.shell package. You need to do something similar for your own package.
SOLUTION:
ebottard's answer brought me to the point of creating a "spring-shell-plugin.xml" under resources\META-INF\spring\... Although the component scan was set externally already, this seems to be necessary. The following code shows how to start it up within an Spring Boot Application where CommandLineRunner is implemented. This should bridge starting problems.
#Component
public class CLIBean implements CommandLineRunner {
#Override
public void run(String... args) throws Exception {
Bootstrap bootstrap = new Bootstrap();
bootstrap.run();
}
}
I have a simple spring boot webapp running on an embedded jetty server, i.e. the main application class:
#Configuration
#EnableAutoConfiguration
#EnableConfigurationProperties
#ComponentScan
public class SampleActuatorApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleActuatorApplication.class, args);
}
}
I have a bunch of static files and directories in one of the auto-configured locations (/static) where static content will be served from. When I hit the base URI I want to be able to view a directory index of the static content so that I can browse through it.
I have read containers including jetty usually come with a default handler that will expose this, however my app just returns 404 so I assume there is some additional steps needed when doing this via spring-boot. Can anyone suggest what I need to do / is my understanding correct?
Somehow you'll have to set the dirAllowed to true. This is done in JettyEmbeddedServletContainerFactory
Take a look at addDefaultServlet
https://github.com/spring-projects/spring-boot/blob/master/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java
There is a line holder.setInitParameter("dirAllowed", "false");