Spring Boot static resources html - spring

I created a spring starter project, but i can't access the static resource
Path
Application
package com.example.demo;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application10_4 extends ResourceConfig{
public Application10_4(){
register(new BookService10_4());
}
public static void main(String[] args){
SpringApplication.run(Application10_4.class, args);
}
}
Dependencies in pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
test
when I use the self-generated application I can access static resources
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Demo1Application {
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
}
}

What is it register(new BookService10_4()); ?
Spring Boot will automatically add static web resources located within any of the following directories:
/META-INF/resources/
/resources/
/static/
/public/
So you can create a public/ directory under resources/ directory and put your static contents there. And they will be reached by: http://localhost:3000/koo.htm. (assuming the server.port is 3000)
You can customize these directories using spring.resources.static-locations in the application.properties.
You can continue read in https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot

Related

Modular #Configuration/#Bean in Spring Boot

I'm making a MicroServices based project so I have more the one Spring Boot projects in my workspace. I need to configure restOperations in some of then but I want to configure once for all the project that needs. So I'm trying to add my #Configuration class to a jar and import in each MS projects.
The problem is, when I execute the MS project in my server, I receive this error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field restOperations in com.epavanellio.base.business.controller.BusinessController required a bean of type 'org.springframework.web.client.RestOperations' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'org.springframework.web.client.RestOperations' in your configuration.
Here I have my Rest configuration class:
package com.epavanellio.base.restConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
//#Component
#Configuration
public class SimpleRestConfiguration {
final CloseableHttpClient httpClient = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy())
.build();
#Bean
public RestOperations createRestTemplate(final ClientHttpRequestFactory clientHttpRequestFactory){
return new RestTemplate(clientHttpRequestFactory);
}
#Bean
public ClientHttpRequestFactory createHttpRequestFactory (#Value("${rest.connect.timeout}") final int connectTimeout,
#Value("${rest.read.timeout}") final int readTimeout) {
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setConnectTimeout(connectTimeout);
clientHttpRequestFactory.setReadTimeout(readTimeout);
clientHttpRequestFactory.setHttpClient(httpClient);
return clientHttpRequestFactory;
}
}
I imported the .jar (dpdc-rest) with has the SimpleRestConfiguration class in my MS project POM:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.epavanellio.base</groupId>
<artifactId>ms-manager-business</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ms-manager-business</name>
<description>Validate business logic. A microservice based project. </description>
<packaging>war</packaging>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.epavanellio.base</groupId>
<artifactId>domain</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.epavanellio.base</groupId>
<artifactId>dpdc-rest</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.epavanellio.base</groupId>
<artifactId>dpdc-custom-exception-handler</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<finalName>ms-manager-business</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
and in my MS application class is like this:
package com.epavanellio.base.business;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import com.epavanellio.base.restConfig.SimpleRestConfiguration;
//#SpringBootApplication(scanBasePackages={"com.epavanellio.base", "com.epavanellio.base.restConfig"})
//#Import(SimpleRestConfiguration.class)
//#ComponentScan({"com.epavanellio.base", "com.epavanellio.base.restConfig"})
#ComponentScan("com.epavanellio.base")
#EntityScan("com.epavanellio.base.domain")
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
#SpringBootApplication
public class BusinessApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(BusinessApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(BusinessApplication.class);
}
}
as you can see commented, I already tried to my make my runtime "see" my configuration class in diffrent ways:
First I tried to add (scanBasePackages={"com.epavanellio.base", "com.epavanellio.base.restConfig"}) after my annotation #SpringBootApplication, but the same error occurs. Then I tried to add specifically the SimpleRestConfiguration class package to the #ComponentScan annotation(for this, I uncommented the #Component annotation in SimpleRestConfiguration class), but the same error occurs. At least I tried to use #Import, but in this case I receive the error:
java.io.FileNotFoundException: class path resource [com/epavanellio/base/restConfig/SimpleRestConfiguration.class] cannot be opened because it does not exist
does any one know how can I make my application class to "see" my
#Configuration class?
The problem was Maven, for some reason maven was no recognizing my jar.
so I made a new dependency project, with a new name but same same SimpleRestConfiguration class. I imported the new .Jar to my MS and then works fine.
My application become like this:
#ComponentScan("com.epavanellio.base")
#EntityScan("com.epavanellio.base.domain")
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
#SpringBootApplication
public class UserApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(UserApplication.class);
}
}

Unit Testing Freemarker templates in SpringBoot - unable to initialize freemarker configuration

we are using Freemarker for generating the HTML code for the emails our application is going to be sending.
Our usage and configuration is based off of https://github.com/hdineth/SpringBoot-freemaker-email-send
Particularly:
package com.example.techmagister.sendingemail.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader;
import org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean;
import java.io.IOException;
#Configuration
public class FreemarkerConfig {
#Bean(name="emailConfigBean")
public FreeMarkerConfigurationFactoryBean getFreeMarkerConfiguration(ResourceLoader resourceLoader) {
FreeMarkerConfigurationFactoryBean bean = new FreeMarkerConfigurationFactoryBean();
bean.setTemplateLoaderPath("classpath:/templates/");
return bean;
}
}
However, there is absolutely no information or documentation anywhere, about how to run Unit Tests for this using JUnit 5.
When I added the relevant dependencies
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
versions:
<junit.jupiter.version>5.3.1</junit.jupiter.version>
<mockito.version>2.23.0</mockito.version>
And made a test class:
package com.example.techmagister.sendingemail;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.io.IOException;
#ExtendWith({SpringExtension.class, MockitoExtension.class})
#Import(com.example.techmagister.sendingemail.config.FreemarkerConfig.class)
public class EmailTestTest {
private static final Logger LOGGER = LogManager.getLogger(EmailTestTest.class);
#Autowired
#Qualifier("emailConfigBean")
private Configuration emailConfig;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception {
try {
Template template = emailConfig.getTemplate("email.ftl");
} catch (IOException e) {
e.printStackTrace();
}
}
}
When I run that in debug mode, emailConfig is null.
Why is that?
Their test example https://github.com/hdineth/SpringBoot-freemaker-email-send/blob/master/src/test/java/com/example/techmagister/sendingemail/SendingemailApplicationTests.java
works if I add the same autowired property, but it is a full SprintBoot context that is slow to boot, and I need to test just template usage, without actually sending out the email.
In our actual code (which is large, multi module project), I have another error org.springframework.beans.factory.UnsatisfiedDependencyException
caused by:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'freemarker.template.Configuration' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=emailConfigBean)}
But that is just for context, first I want to get it working in the simple, sample project then worry about getting it working in our complex one.
You cannot autowire your emailConfigBean directly as a freemarker.template.Configuration
FreeMarkerConfigurationFactoryBean is a factorybean.
To get the Confuguration you need to call factorybean.getObject()
so instead of
#Autowired
#Qualifier("emailConfigBean")
private Configuration emailConfig;
just autowire your factorybean FreeMarkerConfigurationFactoryBean and load your template with emailConfig.getObject().getTemplate("email.ftl")
#Autowired
#Qualifier("emailConfigBean")
private FreeMarkerConfigurationFactoryBean emailConfig;
#Test
void testFreemarkerTemplate(){
Assertions.assertNotNull(emailConfig);
try {
Template template =
emailConfig
.getObject() // <-- get the configuration
.getTemplate("email.ftl"); // <-- load the template
Assertions.assertNotNull(template);
} catch (Exception e) {
e.printStackTrace();
}
working test on github
On the other hand...
In a Spring Boot application the Freemarker configuration can be simplified by using the spring-boot-starter-freemarker dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
<version>1.5.6.RELEASE</version>
</dependency>
This starter for building MVC web applications using FreeMarker views adds the necessary auto-configuration. All you need to do is placing your template files in the resources/templates folder.
Then you just can autowire the freemarkerConfig (or use constructor injection):
#Autowired
private Configuration freemarkerConfig;
There is a nice example here, in the attached github code. I was able to use it as a starting point to test my freeMarker code: https://cleantestcode.wordpress.com/2014/06/01/unit-testing-freemarker-templates/

What's the difference from Spring boot 2.0.0 to 2.2.1 about javax.servlet.* library dependency

I am doing Spring boot mvc project with JSP.
When I use version 2.0.0.RELEASE, everything is ok!
Here is part of my pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
...
And this is my startup class:
package com.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
#SpringBootApplication
public class TestApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(TestApplication .class);
}
public static void main(String[] args) {
SpringApplication.run(TestApplication .class, args);
}
}
But when I change my spring-boot-starter-parent to 2.2.1.RELEASE
Eclipse report error in my startup class:
Multiple markers at this line
- The type javax.servlet.ServletContext cannot be resolved. It is indirectly referenced from
required .class files
- The type javax.servlet.ServletException cannot be resolved. It is indirectly referenced from
required .class files
I know that I can add some other dependencies to solve this, but I don't want to.
Could anybody guide me to the difference in spring boot versions? Thanks in advance!

java.lang.IllegalArgumentException: Sources must not be empty

What is the problem? It was working as well while I updated Ubuntu's software
Main.class
package okt.springbootstarter.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class CourseApiApp {
public static void main(String[] args) {
SpringApplication.run(CourseApiApp.class, args);
}
}
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
I don't know where is the problem?
I was facing the same issue.
Try this out, it looks like you are running a wrong class file.
Go to Java file which contains #SpringBootApplication annotation.
e.g (default content):
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
I fix it.
>echo $HOSTNAME
xyz
>sudo gedit /etc/hosts
and
127.0.0.1 localhost
changed
127.0.0.1 xyz
it fixed it.
Change this import :
<artifactId>spring-boot-starter-parent</artifactId>
to this :
<artifactId>spring-boot-starter</artifactId>
And after clean and re build maven

How to enable basic caching with Spring Data JPA

I am trying to enable basic caching with Spring Data JPA. But I cannot understand why the DAO methods are still querying the database instead of using the cache.
Given the following Spring Boot 1.5.1 application
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
#SpringBootApplication
#EnableCaching
public class Server{
public static void main(String[] args) {
SpringApplication.run(Server.class, args);
}
}
Controller
#Controller
public class PasswordsController {
#Autowired
private PasswordService service;
#SuppressWarnings("unchecked")
#RequestMapping("/passwords.htm")
public void passwords(Map model,
HttpServletRequest request) {
model.put("passwords", service.getPasswords(request));
}
...
Service
#Service
#Transactional
public class PasswordService extends BaseService {
#Autowired
private PasswordJpaDao passwordDao;
public Collection<Password> getPasswords(HttpServletRequest request) {
Collection<Password> passwords = passwordDao.getPasswords(params);
return passwords;
}
...
Interface
#Transactional
public interface PasswordJpaDaoCustom {
public Collection<Password> getPasswords(PasswordSearchParameters params);
}
and implementation
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;
import com.crm.entity.Password;
import com.crm.search.PasswordSearchParameters;
#Transactional
#Repository
public class PasswordJpaDaoImpl implements PasswordJpaDaoCustom {
#PersistenceContext
private EntityManager em;
#Override
#Cacheable("passwords")
public Collection<Password> getPasswords(PasswordSearchParameters params) {
System.err.println("got here");
return em.createQuery(hql, Password.class);
}
...
Maven Dependencies
<!-- Spring Boot start -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Spring Boot end -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
</dependency>
I understand that Spring Boot will implicitly use ConcurrentHashMap for caching without any specific configuration necessary?
But the getPasswords() dao method is always called instead of using the cache. Why is this?
Yes, spring boot by default uses ConcurrentHashMap for caching and the issue with your code is that you did not set any key for your passwords cache, so it is calling the database every time for fetching the data.
So you need to the key (any unique identifier) using the params object variables as shown below:
#Cacheable(value="passwords", key="#params.id")//any unique identifier
public Collection<Password> getPasswords(PasswordSearchParameters params) {
System.err.println("got here");
return em.createQuery(hql, Password.class);
}

Resources