How to separate my spring boot's static resource from build - maven

I am new in spring boot,
I have a multimodule spring boot maven project
core,
admin,
rest
I purchase an admin template which has more than 25000 static files(css and js).
my admin project is like
admin
-src
-main
-resources
-static
But my problem is to build admin it is taking too much time.
How can I separate these resource files from the build process?

You can set the property spring.resources.staticLocations in your application.propertes to configure a custom resource directory. IE spring.resources.staticLocations=file:/foo/bar/static/.
You can also configure it programmatically by extending WebMvcConfigurerAdapter
#Configuration
public class Config extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("file:/foo/bar/");
}
}

Related

Can I get another #Configuration only through #ComponentScan

I am using spring-boot 2.0.4; I have a bunch of services and they have a common configuration class marked with #Configuration.
I want to move this to a common dependency which will have this #Configuration, and based on the need, any micro-service can use #ComponentScan to activate this configuration from dependency.
I have done this for #Component classes, and it's working fine. I activate any particular component I need by adding it into #ComponentScan. How can I activate the configuration in a similar manner(based on need).
Here are the code examples:
Common Configuration:
package abc.department.common.configs.mongo
#Component
public class AbcMongo {
#Bean
public MongoTemplate mongoTemplate() {
// ... create MongoTemplate.
return createdMongoTemplate;
}
}
Here is a class which uses the above dependency:
#Configuration
#ComponentScan("abc.department.common.configs.mongo")
public class MyServiceConfigs {
}
Similarly, I want to do something like this:
package abc.department.common.configs.security.web
#Configuration
#EnableWebSecurity
public class AbcWebSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// ... do common configs;
}
}
and now, if a service would need web-security config, it could get like:
#Configuration
#ComponentScan({"abc.department.common.configs.mongo","abc.department.common.configs.security.web"})
public class MyServiceConfigs {
}
#Configuration is meant to specify the beans, for example:
#Configuration
public class MyMongoConfiguration {
#Bean
public MongoTemplate mongoTemplate() {
return new ...
}
#Bean
public MySampleBean mySampleBean(MongoTemplate tpl) {
return new MySampleBean(tpl);
}
}
But if so why do you need to work with #Component at all (at least for the beans you create)?
Configuration is a special bean used by Spring framework to load other beans and it can be viewed as a "substitution"/alternative technique to component scanning.
I believe that, if you have some infrastructure configuration that loads a bunch of "infrastructure beans" (shared jar if I get you right), then the services that use this jar should only say "Hey, I want to load this configuration" and not to scan inside the packaging structure of that jar. Why do I think so?
What if you decide to add new beans into a new package in the infra, should external services change their code and define an additional folder to scan? - Probably no.
What if you decide to move the infra to another package?
Now in Spring there are two simple ways to do this that come to mind:
Way 1: Use #Import Annotation
#Configuration // this is from "shared artifact"
class MyInfraConfiguration {
}
#Configuration // this is from an "applicative service" that uses the infra jar in dependencies
#Import(MyInfraConfiguration.class)
class ServiceAConfiguration {
}
Way 2: Use Spring Factories mechanism
The first way has a drawback: You need to know in a Service what infra configuration exactly is. If you see it as a drawback, consider using spring factories.
Spring factories allow registering the infra configuration in some file so that spring boot will load it in service one automatically, you won't even need to mention MyInfraConfiguration in the Service Configuration, just add a dependency to the infra jar and it will work.
In the infra component create:
META-INF/spring.factories
And add there:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycompany.myinfra.whatever.InfraConfiguration
That's it.
Now if you want to customize the loading of beans in the infra configuration, like, a creation of Mongo related templates only if some properties are available, you might want to use #Conditional. Now, although this is kind of out of scope for this question, I mention this because in conjunction with spring factories this can create a very flexible way to manage your configurations

spring boot application deployed as war on weblogic- not working

i am new to weblogic, struggling to deploy war. I have a spring boot application running on embedded tomcat.I changed main class as follows.
#SpringBootApplication
#Configuration
#ComponentScan("com.fmc.*")
#EnableAutoConfiguration
public class ApplicationBoot extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(
ApplicationBoot.class, args);
}
#Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder application) {
return application.sources(ApplicationBoot.class);
}
}
i changed packaging as war and excluded the tomcat jars and deployed. But when a submit request, I am getting 404.
I don't see anything in logs in the diagnostics in admin console. Is there aythere place to see the logs. In the weblogic admin console,I can see the application as active and health as ok.
I changed the same application spring web application, it's running successfully, but not spring boot application.
Thanks for your help.
public class ApplicationBoot extends SpringBootServletInitializer implements WebApplicationInitializer
main class has to implement WebApplicationInitializer, thought of useful for some one

Serving single html page with Spring Boot

I'm developing a simple Spring Boot app that uses Spring Boot Web. I placed my index.html into the templates subdirectory of the resources directory as per the Spring Boot docs. I've defined inside the application.properties file:
spring.mvc.view.prefix=classpath:/templates/
spring.mvc.view.suffix=.html
My WebMvcConfigurerAdapter looks like this:
#Configuration
#EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter{
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
super.addViewControllers(registry);
}
}
My problem is I cant seem to serve index.html at http://localhost:8080.
I get the following error:
"javax.servlet.ServletException: Could not resolve view with name 'index' in servlet with name 'dispatcherServlet'".
How can I fix this without the use of a controller?
Kind regards,
Dave
In order to serve static content from Spring Boot application you just need to place them in src/main/resources/static - no other configuration needed.
put index.html to src/main/resources/static/index.html
delete properties from application.properties
delete addViewControllers method and #EnableWebMvc annotation - you can actually delete whole class
access index by going to http://localhost:8080/

Spring Boot application war in a standalone servlet container

A general question about building a war from a spring boot application and running it in a standalone servlet container. The documentation I've seems seems at odds with examples on Stack Overflow.
The answer here shows the way I read of doing this a couple of months ago. I read this here, but the guide seems to have changed losing the actual example app.
Here the "configure" method references the main spring boot Application.class.
public class WebInitializer extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
There are also these posts here and here that show the "configure" method referring to the SpringBootServletInitializer sub class itself.
public class BootStrap extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(BootStrap.class, args);
}
#Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder application) {
return application.sources(BootStrap.class);
}
}
and also there is a main method.
Also the spring-boot-sample-traditional  example app at https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples, which shows "WAR packaging"
does it differently
public class WebConfig extends WebMvcConfigurerAdapter {.........
I was wondering is there are issues with choosing over these different ways of seemingly achieving the same thing in spring boot? Or do they all work equally as well and are interchangeable?
Having your main application class extend SpringBootServletInitializer (Bootstrap in your question) or using a separate class (WebInitializer in your question) is down to personal taste. My preference is to take the Bootstrap approach but they both work in the same way; pick which ever you prefer.
If you are only going to deploy your application to a standalone servlet container then you don't need a main method. The main method is used if you want to run the application as an executable war (java -jar my-app.war), or you want to be able to run it directly in your IDE, i.e. without having your IDE deploy it to a servlet container.
spring-boot-sample-traditional illustrates the use of web.xml to Bootstrap a Spring Boot application. Generally speaking, this isn't a recommended approach unless you're stuck on a Servlet 2.5 container. The use of WebMvcConfigurerAdapter has nothing to do with WAR packaging. Take a look at its web.xml to see the relevant pieces of configuration.
Use Spring Initializr
http://start.spring.io/
Choose your project type (Gradle or Maven) and Packaging as war.
Add Web as dependency and Generate the project.
This will bootstrap your app with the "correct" way.

Production equivalent to Spring Boot EmbeddedServletContainerCustomizer

My question relates to Spring Boot and how to configure error pages in a production web app running in cloudfoundry.
In the Spring IO Sagan reference application, I noticed in the MvcConfig, the following code:
#Configuration
public static class ErrorConfig implements EmbeddedServletContainerCustomizer {
#Override
public void customize(ConfigurableEmbeddedServletContainer factory) {
factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404"));
factory.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500"));
}
}
Is this configuration used in the cloud too? If so why is it named: EmbeddedServletContainerCustomizer? If not what is the equivalent for the cloud?
Yes, you can use EmbeddedServletContainerCustomizer when deploying to the cloud. Sagan itself is doing exactly that on CloudFoundry for the spring.io website.
The "embedded" in the name of EmbeddedServletContainerCustomizer refers to the fact that the servlet container is embedded in your application's executable jar file. It's the recommended approach for cloud deployment.

Resources