Amazon Web Services - Deploy Spring Boot Application - spring

I have a spring boot application that I am deploying onto EB (Elastic Beanstalk) AWS. The app works fine locally, however, I get a 404 on all pages I try to access on the deployed version. Also, I can't access any of the static content under the static folder either. All REST endpoints work fine.
My project structure is as follows
-- src
-- main
-- kotlin
-- resources
-- static
-- css
-- fonts
-- images
-- js
-- templates (contains html files)
I've tried defining option_settings in a .config file under a .ebextensions folder
option_settings
aws:elasticbeanstalk:container:java:staticfiles:
/public/: WEB-INF/classes/static
/static/: WEB-INF/classes/staticenter code here
I've also tried adding the following to my spring configuration class
#Configuration open class MvcConfig : WebMvcConfigurerAdapter() {
override fun addViewControllers(registry: ViewControllerRegistry) {
registry.addViewController("/").setViewName("homepage")
registry.addViewController("/index").setViewName("homepage")
registry.addViewController("/home").setViewName("homepage")
registry.addViewController("/homepage").setViewName("homepage")
registry.addViewController("/login").setViewName("login")
registry.addViewController("/products").setViewName("productsList")
registry.addViewController("/productdetail").setViewName("productDetail")
}
#Bean
open fun viewResolver(): ViewResolver {
val bean = InternalResourceViewResolver()
bean.setPrefix("/templates/")
bean.setSuffix(".html")
return bean
}
override fun addResourceHandlers(registry: ResourceHandlerRegistry?) {
// Register resource handler for all static folders
registry!!.addResourceHandler("/resources/**").addResourceLocations("classpath:/statics/")
.setCacheControl(CacheControl.maxAge(2, TimeUnit.HOURS).cachePublic())
}
#Bean
open fun errorPageFilter(): ErrorPageFilter {
return ErrorPageFilter()
}
#Bean
open fun disableSpringBootErrorFilter(filter: ErrorPageFilter): FilterRegistrationBean {
val filterRegistrationBean = FilterRegistrationBean()
filterRegistrationBean.filter = filter
filterRegistrationBean.isEnabled = false
return filterRegistrationBean
}
I am deploying onto tomcat8 that sits behind an Apache proxy server.
My EB settings are correct as I tried to deploy a simpler application onto the instance, which worked fine.
Please let me know if there are any further details I need to provide

The issue was related to the resourceHandler, the classpath it self was never added to the resource handler, even though servlet logging was indicating it was.
Spring by default maps the following paths
classpath:META-INF/resources/
classpath:resources/
classpath:static/
classpath:public/
needed to add the /** to the mapping. The solution was to modify the code to the following
override fun addResourceHandlers(registry: ResourceHandlerRegistry?) {
registry!!.addResourceHandler("/**", "/static/**")
.addResourceLocations("classpath:/templates/", "classpath:/static/").setCacheControl(CacheControl.maxAge(2,TimeUnit.HOURS).cachePublic())
}
#Bean
open fun viewResolver(): ViewResolver {
val bean = InternalResourceViewResolver()
bean.setSuffix(".html")
return bean
}

Related

Spring Batch is looking for source files during deployment

I am developing Spring batch application on Spring Boot. Batch process is based on fire and forget, which means migration process is triggered by Http GET method and doesn't wait for result. There are 6 (six) csv files which containes migration data and these data must be processed and transferred to DB. Source files path is provided by application.yml file. Batch config (template) looks like as follows:
#Configuration
public class BeginCureBtachConfig {
#Value("$batch-files.begincure-source")
private String dataSourceFilePath;
#Autowired
IteamReader<BeginCure> itemReader;
#Autowired
ItemProcessor<BeginCure, BeginCure> itemProcessor;
#Bean Job beginCureJob(JobBuilderFactory jbFactory, StepBuilderDactory stp, ItemWriter<BeginCure> begnCure {
//// code goes here
}
#Bean
public FlatFileItemReader<BeginCure> beginCureItemReader() {
FlatFileItemReader<BeginCure> ffReader = new FlatFileItemReader<>();
ffReader.setResource(new FileSystemResource(dataSourceFilePath));
ffReader.setLineMapper(lineMapper());
return ffReader;
}
#Bean
public LineMapper<BeginCure> lineMapper () {
//..
}
}
The problem is when project is deployed on openshift, batch looks for files even migratin is not triggered.
In the code, I think this part of code giving some error ffReader.setResource(new FileSystemResource(dataSourceFilePath));
Is there any workaround or solution? Did anybody have this kind of problem?
Thank you in advance^^

Share application.properties files in different project

Below showing the project structure
Core Project
|-config project
|
|-Service project
After building the core project we get Service.jar file.
While running the service.jar am passing spring.config.additional.location as command line argument.
java -jar Service-1.0.jar --spring.config.additional-location=C:/Users/Administrator/Desktop/Springboot/
above spring.config.additional.location path having application.property file and some xml files.
I can able to read application property file in service project ,following logic
Application.propertes
external.config=C:/Users/Administrator/Desktop/Springboot/config/
Mian Class
#ImportResource(locations = {
"${external.config}"+"/spring/service-config.xml",
"${external.config}"+"/spring/datasource-config.xml"
})
public class ServiceMain {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(ServiceMain.class)
.build()
.run(args);
for (String name : applicationContext.getBeanDefinitionNames()) {
}
}
}
Similar kind of logic applied in config project is given below,its not working
#Configuration
public class ConfigurationFactory
{
#Value("${external.config}")
public String extConfPath;
public String REQ_CONF = extConfPath+"/Configuration.xml";
public static final String FILTER_XML_CONF = extConfPath+"/DocFilter.xml";
}
Is there any better way to do this? How can i read external application.properties in config project
Do we have any better way to do this in spring boot
As you are cleary developing a distributed web system the best practice is to used externalised configuration used by your different services allowing you to update settings without redeployment. Take a look at Spring Cloud Config

Problem with connection to Neo4j test container using Spring boot 2 and JUnit5

Problem with connection to Neo4j test container using Spring boot 2 and JUnit5
int test context. Container started successfully but spring.data.neo4j.uri property has a wrong default port:7687, I guess this URI must be the same when I call neo4jContainer.getBoltUrl().
Everything works fine in this case:
#Testcontainers
public class ExampleTest {
#Container
private static Neo4jContainer neo4jContainer = new Neo4jContainer()
.withAdminPassword(null); // Disable password
#Test
void testSomethingUsingBolt() {
// Retrieve the Bolt URL from the container
String boltUrl = neo4jContainer.getBoltUrl();
try (
Driver driver = GraphDatabase.driver(boltUrl, AuthTokens.none());
Session session = driver.session()
) {
long one = session.run("RETURN 1",
Collections.emptyMap()).next().get(0).asLong();
assertThat(one, is(1L));
} catch (Exception e) {
fail(e.getMessage());
}
}
}
But SessionFactory is not created for the application using autoconfiguration following to these recommendations - https://www.testcontainers.org/modules/databases/neo4j/
When I try to create own primary bean - SessionFactory in test context I get the message like this - "URI cannot be returned before the container is not loaded"
But Application runs and works perfect using autoconfiguration and neo4j started in a container, the same cannot be told about the test context
You cannot rely 100% on Spring Boot's auto configuration (for production) in this case because it will read the application.properties or use the default values for the connection.
To achieve what you want to, the key part is to create a custom (Neo4j-OGM) Configuration bean. The #DataNeo4jTest annotation is provided by the spring-boot-test-autoconfigure module.
#Testcontainers
#DataNeo4jTest
public class TestClass {
#TestConfiguration
static class Config {
#Bean
public org.neo4j.ogm.config.Configuration configuration() {
return new Configuration.Builder()
.uri(databaseServer.getBoltUrl())
.credentials("neo4j", databaseServer.getAdminPassword())
.build();
}
}
// your tests
}
For a broader explanation have a look at this blog post. Esp. the section Using with Neo4j-OGM and SDN.

How to live reload without restart on additional static resources in spring boot?

I'm attempting to set a new resource location on a spring boot project that is enabled for live reloads but not for application restarts. I'm able to add additional resources, but any change made in the new directory causes the application to restart.
The documentation on this seems light. I must be misinterpreting something.
My layout looks like this:
- src
- main
- java
- resources
- static
- web
- dist
And my application class looks like this:
#Bean
WebMvcConfigurer configurer () {
return new WebMvcConfigurerAdapter() {
#Override
public void addResourceHandlers (ResourceHandlerRegistry registry) {
registry.addResourceHandler("/dist/**")
.addResourceLocations(""file:web/dist/"")
.setCachePeriod(0);
}
};
}
public static void main(String[] args)
{
SpringApplication app = new SpringApplication(Application.class);
app.addListeners(new PropertyLogger());
Properties properties = new Properties();
properties.setProperty("spring.devtools.restart.additional-paths", "web/dist/");
properties.setProperty("spring.devtools.restart.additional-exclude", "/dist/**");
app.setDefaultProperties(properties);
app.run(args);
}
I've read through several similar questions and this seems to be the best I can do. Is it possible to enable live reload on dist without a full application restart?
By the way, my IDE is IntelliJ. I'm beginning to wonder if IntelliJ needs to exclude the dist directory. I'll followup if that's the case.
I've beaten this to death and have finally found a working solution.
Properties properties = new Properties();
properties.setProperty("spring.devtools.restart.additional-paths", "web/");
properties.setProperty("spring.devtools.restart.additional-exclude", "dist/**");
app.setDefaultProperties(properties);
Defining the web directory as an additional path combined with the pattern used for additional exclude does the trick.
I won't mark this as accepted unless there are upvotes to back my conclusion.

Don't have access to Spring boot controller, but have access to index.html

I have a Spring Boot project, what I deployed on remote server. When I call http://109.206.178.66:8080/proxynator/ - I can see an index.html, but when I call rest controller by url http://109.206.178.66:8080/proxynator/countries - I have an error 404 whith
Description: The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
It's strangely, because when I start this project on my local machine, all working right. Project structure is:
Line from catalina.out file:
SEVERE [http-nio-8080-exec-19] org.apache.tomcat.util.descriptor.web.WebXmlParser.parseWebXml Parse error in application web.xml file at [file:/opt/tomcat/webapps/proxynator/WEB-INF/web.
My controller:
#RestController
class MainController(val proxyRepo: ProxyRepo, val countryRepo:
CountryRepo) {
#GetMapping("/countries")
fun findCountries(): List<Country> = countryRepo.findAll()
#GetMapping("/proxies")
#ResponseBody
fun findProxies(#RequestParam countryid: Int): List<Proxy> =
proxyRepo.findAllByCountryid(countryid)
}
UPD
I added configuration class on the root package
#Configuration
open class RestConfiguration {
#Bean
open fun mainController():MainController
= MainController()
}
But it does not working. I don't understand, why I can see index.html by irl http://109.206.178.66:8080/proxynator/, but can't get access to my controllers. When I package my project I have some files:
Any advice?
your api access url is wrong access using http://109.206.178.66:8080/countries this is the correct path for your rest mapping, not http://109.206.178.66:8080/proxynator/countries
To solve this problem I was edit my Application class.
#SpringBootApplication
#EnableAutoConfiguration
open class Application: SpringBootServletInitializer(){
#Override
override fun configure(application: SpringApplicationBuilder?):
SpringApplicationBuilder {
return super.configure(application)
}
}
fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}
I was override configure method, and all is working!
Hope it will save time for anybody!

Resources