Not able to register spring boot service with eureka on external tomcat - spring

I am trying to deploy two spring boot application services on external tomcat.
Eureka service
Client service
When I deployed these two services on external tomcat, I am able to deploy and I am able to access these two services separately but my client service is not able register with Eureka service and I can't see it on eureka console.
My Eureka service properties file:
#EureakaService.properties#
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
spring.application.name=EurekaServiceApplication
logging.level.com.netflix.eureka=OFF
logging.level.com.netflix.discovery=OFF
Below is my Client service properties file
#ClientService.properties#
spring.application.name=CBEApplication
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka-server-1.8.0
I am not sure what is wrong with my configuration settings.

EurekaService class as below# #EnableEurekaServer
#SpringBootApplication
public class EurekaServiceApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(EurekaServiceApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(EurekaServiceApplication.class, args);
} #Client Class code as below# #SpringBootApplication
#EnableDiscoveryClient
public class CBEApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(CBEApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(CBEApplication.class, args);
}
}

Related

Can we implement Spring batch application without Spring Boot?

Can we implement Spring batch application without Spring Boot ?
Instead of an executable JAR you can also deploy a Spring Boot application as a WAR to JBoss.
The SpringBootApplication class will look a bit different:
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And you have to use
<packaging>war</packaging>
Please find more information in the official documentation: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file

How prevent Spring boot war file load component twice in separated context?

I have a spring boot application, packaged as a war file and deployed on tomcat server. I noticed that some component load twice in startaup:
when application is started
when ServletInitializer is started.
It caused me some problem because one of my components is EnableAsync and should do some scheduled task frequently. when it load twice in tow separated context each task is done twice and make duplicated rows in database.
Is there a way that force some component just load in single context in Spring boot? it means prevent bean to be initialized in ServletInitializer for example.
That's my SpringBootServletInitializer code:
#SpringBootApplication
#EnableScheduling
#EnableAsync
public class TestApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
#Bean
public PasswordEncoder getPasswordEncoder(){
return new BCryptPasswordEncoder();
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(TestApplication.class);
}
}
Thanks to M. Deinum I found out there is an extra SpringBootServletInitializer in my code! I deleted it and Every thing is Ok now!

#Async annotation does not works when war is deployed on JBoss

I have an application that contains an API Rest implemented as a Spring Boot application (1.5.18.RELEASE version)
This API contains a controller that executes a service method asynchronous. The method is marked with #Async annotation
The #EnableAsync annotation is set on my configuration class.
When i execute the application like a typical Spring Boot application, the method is executed asynchronous. if i generate a war (using maven) and this war is deployed on JBoss (6.4 Version), the same service is executed synchronous.
Could someone explain me this behavior? Should i add any type of configuration?
The source code is below:
The Spring Boot configuration
#SpringBootApplication
#EnableCustomConfiguration
#EnableCaching
#EnableScheduling
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
}
My custom annotation:
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Import({CustomServicesConfiguration.class})
#Documented
public #interface EnableCustomConfiguration {
}
My configuration class:
#Configuration
#ComponentScan("com.bs.custom.api")
#EntityScan(basePackages = "com.bs.custom.api.domain", basePackageClasses = Jsr310JpaConverters.class)
#EnableJpaRepositories(basePackages = "com.bs.custom.api.repository")
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
#EnableAsync
public class CustomServicesConfiguration {
static {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
}
I've modified my WebApplication class to extends from SpringBootServletInitializer, as is defined on Spring Boot reference guide (thanks M.Deinum)
The final WebApplication class source code is below:
#SpringBootApplication
#EnableCustomConfiguration
#EnableCaching
#EnableScheduling
#EnableAsync
public class WebApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(WebApplication.class);
}
}
Now, asynchronous methods run correctly on JBoss

how to package the springboot application with dynamic end points on application.properties file

I have 1 spring boot application. In this application i have configured 1 eCommerce system as elastic path(Configure the end point url of elastic path in application.properties file). Now i have to give my spring boot application to some other guys. which will be deploy on tomcat server. I don't want to give the source code. So i can make the war file but now problem is that they have their own elastic path eCommerce and they wants to configure their own eCommerce.
I want to externalize some properties which will override the existing property.
My springboot application have 2 modules :
1) elasticpath module which is having elasticpath-application.properties
2) salesforce - salesforce-application.properties
Now i have to externalize "C:\apache-tomcat-8.5.29\conf\ep-external.properties" file which will override the existing property. Now problem is that #PropertySource is loading in last position. So my external file is not able to override the property.
#SpringBootApplication
#PropertySource(value = {"classpath:application.properties", "classpath:elasticpath-application.properties", "classpath:salesforce-application.properties")
public class SpringBootDemo extends SpringBootServletInitializer implements CommandLineRunner {
private static final Logger LOG = LoggerFactory.getLogger(SpringBootDemo.class);
private ServletContext servletContext;
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
//application = application.properties("file:C:\\apache-tomcat-8.5.29\\conf\\ep-external.properties");
return application.sources(SpringBootDemo.class);
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
this.servletContext = servletContext;
super.onStartup(servletContext);
}
public static void main(String[] args) {
SpringApplication.run(SpringBootDemo.class, args);
}
#Override
public void run(String... args) throws Exception {
}
}
Yes absolutely possible. Basically what you need is changing the property value as needed without changing jar/war
Passing command line args for jar
Package your spring boot application as jar and put the external application.properties file at any location and pass on the same location as command line argument as below :
java -jar app.jar --spring.config.location=file:<property_file_location>
This will pick up the external properties.
Passing command-line/dynamic args for war
1. Extend the SpringBootServletInitializer as below
#SpringBootApplication
class DemoApp extends SpringBootServletInitializer {
private ServletContext servletContext;
public static void main(String[] args){SpringApplication.run(DemoApp.class,args);}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
builder = builder.properties("test.property:${test_property:defaultValue}");
return builder.sources(DemoApp.class)
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
this.servletContext = servletContext;
super.onStartup(servletContext);
}
}
Access the property as usual like below anywhere you want :
#Value("${test.property}")
Before starting tomcat set the env variable named test_property. that's it
Additionally:
You can pass on the property like below as well if you want to supply complete file as external file.
.properties("spring.config.location:${config:null}")
Further reading about externalized configuration : https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Why do I need main method if I develop web app as war using Spring Boot?

I am developing web app using Spring Boot. My typical deployment is generating war and place it in webapps folder in Tomcat directory.
I noticed with SpringBoot, I will need a main method. I am wondering why this is needed. If there is a way to avoid it, what would that be?
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Main method is not required for the typical deployment scenario of building a war and placing it in webapps folder of Tomcat. All you need is:
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
However, if you want to be able to launch the app from within an IDE (e.g. with Eclipse's Run As -> Java Application) while developing or build an executable jar or a war that can run standalone with Spring Boot's embedded tomcat by just java -jar myapp.war command, an entry point class with a main method might be helpful.
To run in a separate web container
You don't need the main method, all you need is to do is to extend SpringBootServletInitializer as Kryger mentioned.
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
....
....
To run in the command line as a standalone application
Here you need the main method, so that you can run it using java -jar from the command line.
public class Application {
public static void main(String[] args){
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
}
....
....
Source: https://spring.io/guides/gs/convert-jar-to-war/
In Spring Boot one will basically need three things :
1) use the #SpringBootApplication annotation
2) extend SpringBootServletInitializer
3) overwrite the configure method as shown above
and that's it !

Resources