GroovyTemplates properties configuration - spring-boot

I'm trying to configure the properties of GroovyTemplates. I checked the reference document, but formatting options are not available through the application.properties file. So I did the following to customize some other properties.
#EnableAutoConfiguration
#Configuration
#ComponentScan
public class Application implements CommandLineRunner {
#Autowired
private GroovyTemplateAutoConfiguration.GroovyMarkupConfiguration configuration;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
public void run(String... strings) throws Exception {
this.configuration.groovyTemplateConfiguration().setUseDoubleQuotes(true);
this.configuration.groovyTemplateConfiguration().setAutoNewLine(true);
this.configuration.groovyTemplateConfiguration().setAutoIndent(true);
}
}
I can see the double quotes in the rendered HTML files. However, it is still unformatted.
So, I have two questions. The first one is, how can I set the properties properly? Most probably, the one I did is not the proper way. The second question is, why do I still get the unformatted HTML?

In the docs it says
spring.groovy.template.configuration.*= # See Groovy's TemplateConfiguration
So I assume that corresponds up the properties you set (what you are doing isn't wrong, necessarily, but it might happen too late to influence the behaviour at runtime). I would stick with the application.properties if I were you.

Related

#Autowired notation is not working as expected

#SpringBootApplication
public class MainApplication {
#Autowired
static BibliographyIndexer bi;
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
bi.reindex();
}
}
#Repository
public class BibliographyIndexer {
...
}
Whenever I access the properties of bi I get a NullPointerException. I know the #Autowired notation didn't work. But why?
Note: both classes are under the same package.
Additional question: Since I want to run a method upon the start of the spring application. Is this the best approach since #pepevalbe's answer already gave me the workaround I needed. Is there another way to run a method upon the start of the spring application?
Because you can't #Autorwire an static class. It doesn't get initialized so you get a NPE when trying to use it.
There are workarounds to wire a bean into a static class, but it is strongly discouraged.
EDIT:
If you need to execute code after initilization you could add an event listener:
#SpringBootApplication
public class MainApplication {
#Autowired
BibliographyIndexer bi;
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
#EventListener(ApplicationReadyEvent.class)
public void doAfterStartUp() {
bi.reindex();
}
}
There are several reasons #Autowired might not work.
When a new instance is created not by Spring but by for example manually calling a constructor, the instance of the class will not be registered in the Spring context and thus not available for dependency injection. Also when you use #Autowired in the class of which you created a new instance, the Spring context will not be known to it and thus most likely this will also fail.
Another reason can be that the class you want to use #Autowired in, is not picked up by the ComponentScan. This can basically be because of two reasons.
The package is outside the ComponentScan search path. Move the package to a scanned location or configure the ComponentScan to fix this.
The class in which you want to use #Autowired does not have a Spring annotation. Add one of the following annotatons to the class: #Component, #Repository, #Service, #Controller, #Configuration. They have different behaviors so choose carefully........
Your problem is that you cannot use bi in main because main is static.
Making bi static doesn't help because static fields will not be #Autowired (It is possible but does not make sense in the concepts of Dependency Injection).
Remove static and move bi.reindex() to a new method annotated with #PostConstruct. It will be executed after the MainApplication-bean is fully initialized and here you can use your injected bi.
In main method you can refer to context and from it get access to bean BibliographyIndexer. In static main spring can not creates and injects bean so this is how you can get it from context.
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(MainApplication.class, args);
BibliographyIndexer bibliographyIndexer = context.getBean(BibliographyIndexer.class);
bibliographyIndexer.reindex();
}
You can also do as in answer from pepevalbe and execute this code after initialization.

#Value for custom values is not showing up

I have a project in Spring Boot (1.5.9). I have properties in an application.properties in src/main/resources and in an external application.properties. I also can provide values through the command line.
My main class looks like this:
#SpringBootApplication
#SpringBootConfiguration
#EnableJpaRepositories
#EnableEncryptableProperties
#Import(RepositoryRestMvcAutoConfiguration.class)
public class Application {
public Application() { super(); }
public static void main(String[] args) {
final SpringApplication app = new SpringApplication(Application.class);
app.run(args);
}
}
I have a different class that looks something like this:
#Component
public class MyAuthenticationProvider extends AuthenticationProviderInterface {
#Value("${myproject.authentication.url:https://blah:8443}")
private String authenticationURL = "https://test.blah:8443";
#Override
public void afterPropertiesSet() {
System.err.println(authenticationURL);
}
..... other stuff.....
}
From the System.err, I get https://test.blah:8443.
Now, I can get all of my major variables: spring.main.banner-mode, spring.datasource.name, etc. I just do not seem to be able to get my custom variables--myproject.authentication.url or myproject.authentication.accessstring.
The spring variables are behaving as expected--I can follow precedence from the properties files to the command line. It's only the custom variables that are giving me fits.
Does anyone have any suggestions? I'm trying to give good information, but I am typing between two unconnected computers and I will occasionally have a typo.
Thank you.
Change #Comopnent to #Component.
OK. This was blatant stupidity and Eclipse "helping" me again. The Save actions added a "final" and (unsurprisingly) the values were not being updated. Sorry for wasting people's time.

Can I have two public classes in spring - boot?

In my springboot application I am needing to deploy to an existing tomcat server so I need to deploy the application as a war file. In order to do that I have to alter my main class a bit.
I currently have the following code in my main application class
#SpringBootApplication
public class Application implements CommandLineRunner {
#Autowired
private UserService userservice;
public Static void main(String[] args) {
SpringApplication.run(Application.class, args);
I need to change it to the following to be able to have maven change it to a war file instead of a jar.
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Autowired
private UserService userService;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
Problem is I need the commandlinerunner implemented as well. Can I have both? If so how would I go about doing this? I have searched and the information I have found so far has been ambiguous at best. Any assistance would be greatly appreciated as well as the documentation so I can review it as well as share it if I come across others having a similar issue.
EDIT: I did find one document that seemed to imply I could have both implimented within the same application.java and within the pom.xml file stating which one should be initialized first. Would this be a correct way of doing this? I read in another overstack that an individual that tried this ended up with two applications because of it. Unfortunately he did not provide much code to explain what he tried, only what his outcome was.
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
public class ServletInitializer extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}

Why do I need to add #Component when I have to schedule the task in spring boot

I didn't understand the proper use of #Componenet, #Configuration,#Bean annotation.
I want to run one method in every 60 seconds.Please check the below code. If I don't give #Component annotation then it doesn't run. so What is the use of #Component in this context?
#EnableScheduling
public class SchedulingProjectApplication {
private static final Logger log =
LoggerFactory.getLogger(SchedulingProjectApplication.class);
public static void main(String[] args) {
SpringApplication.run(SchedulingProjectApplication.class, args);
}
#Scheduled(fixedDelay = 6000)
public void r()
{
log.info("Start- main-job");
log.info("stop-main-job");
}
}
There are several problems with this piece of code:
Your Spring Boot application is not flagged with #SpringBootApplication (or #EnableAutoConfiguration). As a result, the auto-configuration will not kick in at all (Spring Boot will start your app but won't do anything with it besides basic stuff such as env preparation, etc). It's perfectly fine in certains cases but that isn't probably what you want
You've flagged the run task directly on your app. It's ok for demo but it would be better to move that logic in its own class
So to answer your question: SchedulingProjectApplication is the root source of your app but it's just a simple POJO. There's nothing that instructs the container to process it. Usually the app is a #Configuration (you can use one of the #EnableXYZ on it, you can define additional beans, etc.
If you add #SpringBootApplication on your class, it will scan any #Component in the same package of your app (and all the sub-packages).
More details about code structure in the documentation
One basic/simple structure for you would be:
package com.example.foo;
#SpringBootApplication
#EnableScheduling
public class SchedulingProjectApplication {
public static void main(String[] args) {
SpringApplication.run(SchedulingProjectApplication.class, args);
}
}
And
package com.example.foo;
#Component
public class SchedulingLogger {
private static final Logger log =
LoggerFactory.getLogger(SchedulingLogger.class);
#Scheduled(fixedDelay = 6000)
public void r()
{
log.info("Start- main-job");
log.info("stop-main-job");
}
}
There are other things that you should be aware with regards to configuration (such as moving decisions outside of your #SpringBootApplication if you use slicing).

Loading applicationcontext.xml when using SpringApplication

Could anyone provide an example of a SpringApplication that loads an applicationContext.xml file?
I'm attempting to move my GWT RPC application to a RESTful web service by using a Spring's Example (Gradle based). I have an applicationContext.xml but I do not see how to get SpringApplication to load it. Loading manually via
ApplicationContext context = new ClassPathXmlApplicationContext(args);
results in an empty context. ...and even if that worked it would be separate from the one returned from
SpringApplication.run(Application.class, args);
Or is there a way to get external beans into the app context created by SpringApplication.run?
If you'd like to use file from your classpath, you can always do this:
#SpringBootApplication
#ImportResource("classpath:applicationContext.xml")
public class ExampleApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(ExampleApplication.class, args);
}
}
Notice the classpath string in #ImportResource annotation.
You can use #ImportResource to import an XML configuration file into your Spring Boot application. For example:
#SpringBootApplication
#ImportResource("applicationContext.xml")
public class ExampleApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(ExampleApplication.class, args);
}
}
The annotation does not have to be (on the class) that (has the main method) that (has this below call):
SpringApplication.run(Application.class, args);
(in your case, what I am saying is that #ImportResource does NOT have to be on your class)
public class ExampleApplication {}
.........
You can have a different class
#Configuration
#ImportResource({"classpath*:applicationContext.xml"})
public class XmlConfiguration {
}
or for clarity
#Configuration
#ImportResource({"classpath*:applicationContext.xml"})
public class MyWhateverClassToProveTheImportResourceAnnotationCanBeElsewhere {
}
The above is mentioned in this article
http://www.springboottutorial.com/spring-boot-java-xml-context-configuration
.........
BONUS:
And just in case you may have thought "SpringApplication.run" was a void method.....that is NOT the case.
You can also do this:
public static void main(String[] args) {
org.springframework.context.ConfigurableApplicationContext applicationContext = SpringApplication.run(ExampleApplication.class, args);
String[] beanNames = applicationContext.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String name : beanNames) {
System.out.println(name);
}
This will also subtly clue you in to all the many, many, many (did I mention "many"?)....dependencies that spring boot is bringing in. Depending to whom you speak, this is a good thing (somebody else did all the nice figuring out for me) or an evil thing (whoah, that's a lot of dependencies that I don't control).
hashtag:sometimesLookBehindTheCurtain
Thanks Andy, that made it very concise. However, my main problem turned out to be getting applicationContext.xml into the classpath.
Apparently, putting files into src/main/resources is required to get them into the classpath (by placing them into the jar). I was attempting to set CLASSPATH which was just ignored. In my example above, the load seemed to fail silently. Using #ImportResource caused it to fail verbosely (which helped me track down the real cause).

Resources