I am using spring boot with thymeleaf. This is my project structure:
And this is my App start class:
#EnableAutoConfiguration
#Configuration
#ComponentScan
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class);
}
}
I have this on my home.leaf.html: <p th:text = "#{username}"></p>
But when I run this application this is what I get: ??username_en_US??
I have tried various things on how to resolve this configuration issue. Please, can anyone help?
Refer the official documentation for spring boot
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-convert-an-existing-application-to-spring-boot
It says
Static resources can be moved to /public (or /static or /resources or
/META-INF/resources) in the classpath root. Same for
messages.properties (Spring Boot detects this automatically in the
root of the classpath).
So you should create ur internationalization file as messages.properties and place in the root classpath.
Or you can also edit the default location to a more proper location by adding this entry in the application.properties file
#messages
spring.messages.basename=locale/messages
so you can store your files in the locale folder inside resources folder, with the name messages.properties or in any specific language.
Related
I have a config folder of xml files that my spring boot app needs , its located on the same level of src folder ... Now i now to locate it in Resources Folder on the same level of application.properties.. There is any way to be able to do that ?
There many way to read your file .properties:
You can read with plain java like this:
Properties properties = new Properties();
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName));
you can use the #PropertySource annotation in a Spring #Configuration class:
#Configuration
#PropertySource("db.properties")
public class ApplicationConfig {
// more config ...
}
//Or if you your config outside of your classpath, you can use the file: prefix:
#PropertySource("file:/path/to/application.properties")
Using Multiple file :
#PropertySources({
#PropertySource("classpath:foo.properties"),
#PropertySource("classpath:bar.properties")
})
public class PropertiesWithJavaConfig {
//...
}
And so on ...
I have a Spring Boot application which copies external JAR files to a folder, depending on certain conditions. These JARs can contain many Spring components (i.e. classes annotated or meta-annotated with #Component) and the Spring application should be able scan and instantiate for these beans. Is it possible, based on certain conditions, to dynamically load the contents of the JAR files and make them available to the Spring application context? I am fully aware of the security implications this has.
I have read about the different types of Launchers which Spring provides for its executable JAR format, such as JarLauncher and PropertiesLauncher, but it looks like that these launchers do not detect changes to the classpath, but instead only scan the directories once for JAR files.
The following simple application demonstrates the problem:
// .../Application.java
#SpringBootApplication
public class Application {
public static void main(String[] args) {
System.out.println("Please copy JAR files and press Enter ...");
System.in.read();
SpringApplication.run(Application.class, args);
}
}
Replace the default JarLauncher with PropertiesLauncher:
// build.gradle
tasks.named('bootJar') {
manifest {
attributes 'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher',
'Start-Class': 'com.example.customlauncher.Application'
}
}
Specify the location to the external JARs in the properties file of the PropertiesLauncher:
# .../resources/loader.properties
loader.path=file:/path/to/dir
The application is a Spring Initializer Gradle application and packaged by running the bootJar task: ./gradlew bootJar.
It is then started with the following command:
java -jar build/libs/customlauncher-0.0.1-SNAPSHOT.jar
This works if the JAR file is already present at the specified location (/path/to/dir), but it does not work if the java command is executed while the directory is empty and the JAR file is then copied while the app waits for the user to copy the files and press Enter ↲.
There are a couple of related questions, but it looks like they all assume that the JAR files already exist at the time of starting the JVM:
How to put a directory first on the classpath with Spring Boot?
Spring Boot Executable Jar with Classpath
SpringBoot external jar not load
Is there a way to achieve this without too many awkard hacks? Or is recommended to utilize something like OSGi? Am I looking at this completely wrong and there is a better way to have JARs on the classpath that do not need always need loading (if the JAR is "disabled", it should not be loaded/compiled by the JVM, should not be picked up by Spring, etc.)?
It looks like this is possible if the JAR files are copied before starting the Spring application. It feels hackish, but it works. Use at your own risk!
You need two classes, one for bootstrapping the external JARs, which will then start the second via a manually created PropertiesLauncher. The bootstrapping class can be a plain old regular Java class (but it can be a Spring Boot Application too) and only the second class needs to be a SpringBootApplication.
// BootstrapApplication.java
public class BootstrapApplication {
public static void main(String[] args) {
System.out.println("Please copy JAR files and press Enter ...");
System.in.read();
PropertiesLauncher.main(args);
}
}
// Application.java
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
In the gradle file, we can switch back to the default JarLauncher, by removing the bootJar task manifest configuration and applying settings via the springBoot configuration block. mainClass will end up as Start-Class in the MANIFEST.MF file.
// build.gradle
springBoot {
mainClass = 'com.example.customlauncher.BootstrapApplication'
}
In the properties file for the loader, a new property needs to be set, which points to the real application class. The settings in this file are only picked up by PropertiesLauncher and ignored by JarLauncher. In other words: JarLauncher delegates to Start-Class from the manifest file and PropertiesLauncher delegates to loader.main from its properties file.
# .../resources/loader.properties
loader.path=file:/path/to/dir
loader.main=com.example.customlauncher.Application
Spring (Boot) will first call the main method of BootstrapApplication, as specified in the MANIFEST.MF file (controlled via springBoot configuration block in the build.gradle file). In the implementation of this main method, a new PropertiesLauncher is created with the main class set to the "real" application (i.e. Application).
Executing the application is still done via the same invocation:
java -jar build/libs/customlauncher-0.0.1-SNAPSHOT.jar
Any JAR files added to /path/to/dir after the JVM has started, but before calling PropertiesLauncher#main in BootstrapApplication are then available in the classpath and application context as seen from Application.
I have some library jar lib.jar (made using spring boot but packaged as normal jar without spring boot plugin) which is made of spring boot and contains spring.components file generated by spring-context-indexer.
Now, I'm using this jar in my application which also has spring-context-indexer and its own spring.components file and uses some of the bean defined in lib.jar.
When I start my application, spring should register all beans defined in spring.components of lib.jar and spring.components of application. But spring isn't registering any of bean of lib.jar.
I tried using basePackages property of #SpringBootApplication but no results.
I even copied all entries of spring.components of lib.jar into spring.components of my application but no result.
Can anyone please help me?
TL;DR
If you're using Spring Data, #SpringBootApplication.scanBasePackages is not enough, you also need #EnableJdbcRepositories (or *Jpa* or whatsoever).
package application;
// without this annotation all Repository classes
// from library will be missing
#EnableJdbcRepositories({
"application",
"library"
})
#SpringBootApplication(
scanBasePackages = {
"application",
"library"
}
)
public class Application {
public static void main(final String[] args) {
SpringApplication.run(Application.class, args);
}
}
Some more info
Okay, maybe I'm a bit late, but I decided to investigate this case a bit.
That's what I've found as of 2 Feb 2022:
All META-INF/spring.components files are loaded in CandidateComponentsIndexLoader.doLoadIndex. You can use debug to check whether it sees file from lib or not
CandidateComponentsIndexLoader then creates CandidateComponentsIndex, which is then stored in the component scanner, for me it is AnnotationConfigServletWebServerApplicationContext.scanner.componentsIndex
Then in ClassPathScanningCandidateComponentProvider findCandidateComponents is called, which, if componentsIndex is not null, just gets components from that index by provided basePackage.
That's why missing basePackage is crucial.
I haven't dug into the Spring Data algorithms, but in my case Spring hadn't been generating library Repositories until I added the #EnableJdbcRepositories with packages.
P.S. All links represent files at the 5.3.15 tag, latest atm.
This is how I have set up external configuration file:
/** for .yaml file
#Configuration
#PropertySource("classpath:waterlvl.yaml")
#ConfigurationProperties("Alerts")
public class WaterLvlAlertConfig {
/** for .properties file
#Component
#PropertySource("classpath:waterlvl.properties")
public class WaterLvlConfig {
Properties are not being picked up, and my files are inside the resources file. I think the path I'm providing is wrong. What am I doing wrong?
In spring boot #PropertySource cannot be used when using .yaml configuration. Refer to point 24.6.4 YAML shortcomings in externalized configuration documents. Also, a similar question is answered earlier, refer - Spring boot external configuration of property file
I'm trying to link a HTML page to my Spring boot application.
I've connected a SQL DB to it, and have set up the needed controllers, but cannot map the HTML page to the local host.
Here is the GIT for the project.
https://github.com/ThierryLucDenichaud/SpringBoot_SQL_SPRING_HTML.git
Create a configuration file that look like the following:
#Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("indexPage.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}
This will create a default controller for serving your index.html on /.
A little recommendation, change indexPage.html to index.html and also setViewName("indexPage.html") to setViewName("index.html") as index.html is usually the default in most systems and frameworks.
EDIT
I just noticed your public folder is in src/main while it should be in src/main/resources. spring boot won't handle your static files unless they are first in src/main/resources then in public as the default folder that is exposed to the outside world.
Also in Java you should place classpath resources in src/main/resources or src/test/resources for tests.