I need your help please. I integrated Ehcache 3 with springboot 2. everything works perfectly in production. integration tests also work if i execute them manualy ( I'm using Intellij IDE ).
but when i run "mvn install", i get this error :
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'ehCacheManager' defined in class path
resource [com/afklm/belem/payment/config/EhCacheConfiguration.class]:
Bean instantiation via factory method failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [org.springframework.cache.CacheManager]: Factory method
'ehCacheManager' threw exception; nested exception is
javax.cache.CacheException: A Cache named [currenciesCache] already
exists
CurrencyRepository interface :
#Repository
public interface CurrencyRepository extends JpaRepository<Currency, String> {
/**
* Gets currencies from Cache.
* The real call to the DataBase will be performed if the response is not in cache
*
* #return list of {#link Currency}
*/
#Cacheable(cacheNames = "currenciesCache", key ="#root.methodName", unless = "#result==null or #result.size()==0")
default List<Currency> getCachedCurrencies() {
return findAll();
}
Cache configuration class
import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.ExpiryPolicyBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.jsr107.Eh107Configuration;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.jcache.JCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cache.CacheManager;
import javax.cache.Caching;
import java.time.Duration;
import java.util.List;
#EnableCaching
#Configuration
public class EhCacheConfiguration extends CachingConfigurerSupport {
#Bean
public CacheManager ehCacheManager() {
//-> currencies cache configuration
CacheConfiguration<String, List> currenciesCacheConfig =
CacheConfigurationBuilder
.newCacheConfigurationBuilder(String.class, List.class, ResourcePoolsBuilder.heap(1000))
.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofDays(30)))
.withDefaultEventListenersThreadPool()
.build();
javax.cache.CacheManager cacheManager = Caching.getCachingProvider().getCacheManager();
cacheManager.createCache("currenciesCache", Eh107Configuration.fromEhcacheCacheConfiguration(currenciesCacheConfig));
return new JCacheCacheManager(cacheManager);
}
Thanks for your help; i'm stuck
I think I faced this before when at least one of my tests had the #DirtiesContext annotation which re-initializes the Spring context. I got around it by making a call to the cacheManager.destroyCache method before attempting to create the cache. Can you try adding the statement cacheManager.destroyCache("currenciesCache"); before the cacheManager.createCache statement? Alternatively, you could try initializing the cache manager without the explicit call to the createCache method like it has been done in this Stack Overflow answer
Related
I'm building my first Spring project, I have very little experience in Java and I'm overwhelmed by the amount of boiler plate. This issue seems to be really simple and I found a lot of related answers. However, none of them seems to address this issue specifically.
I haven't done any special configurations, I only built this with Spring Boot and created 3 classes.
When I run the project I get the following message:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.demo.Student.StudentController required a bean of type 'com.example.demo.Student.StudentService' that could not be found.
Action:
Consider defining a bean of type 'com.example.demo.Student.StudentService' in your configuration.
I renamed the class "StudentService", and maybe this is the source of the issue.
This is my project structure:
And this is StudentService.java:
package com.example.demo.Student;
import java.time.LocalDate;
import java.time.Month;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
public class StudentService {
#GetMapping
public List<Student> getStudents() {
return List.of(
new Student(
1L,
"George",
"george.email#gmail.com",
LocalDate.of(2000, Month.JANUARY, 5),
22)
);
}
}
There is no bean defined for the StudentService class.
try defining the class with the following :
#Service - If the StudentService class need to defined as a service class
#Component
either of the way will work for you.
Several ways to resolve this !
Annotate your StudentService class with #Component, during start up of application, Spring will identify this and create a bean in IOC container for use. ( Don't forget to use #ComponentScan(basePackages={com.example.demo.Stude...}) on top of your DemoApplication class )
Create a Configuration class with #Configuration and define your own bean with #Bean returning instance of StudentService
Eventually, use #Autowired on top of your StudentService instance in Controller. Like below
<pre>public class Controller
{
#Autowired
StudentService service;
// so on
} </pre>
I'm using #TestConfiguration annotation to define bean provider for the JUnit5 test class.
A test class is annotated with:
#Import(MyTestConfiguration.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT).
package com.example;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
#Import(MyTestConfiguration.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class MyTest {
...
}
A configuration class is annotated with
#TestConfiguration.
package com.example;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.annotation.Bean;
#TestConfiguration
public class MyTestConfiguration {
#LocalServerPort
private int port;
...
}
I'm trying to inject local server port inside the configuration class with #LocalServerPort annotation, but get a Failed to load ApplicationContext error Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.example.MyTestConfiguration': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'local.server.port' in value "${local.server.port}".
I was using #LocalServerPort successfully in the test class, but decided to move it along with other objects which use it to the MyTestConfiguration class to make test class more clear.
Add #Lazy annotation to the test configuration class. More info here.
From the documentation:
If this annotation is not present on a #Component or #Bean definition,
eager initialization will occur. If present and set to true, the #Bean
or #Component will not be initialized until referenced by another bean
or explicitly retrieved from the enclosing BeanFactory. If present and
set to false, the bean will be instantiated on startup by bean
factories that perform eager initialization of singletons.
I am configuring a spring boot application. So I created a property bean class like this:
import javax.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
#Configuration
#EnableConfigurationProperties
#PropertySource("classpath:/application.properties")
public class APPStaticProperties {
#NotNull
#Value("${dblog.system.name}")
String db_logsystem_name;
/**
* #return the db_logsystem_name
*/
public String getDb_logsystem_name() {
return db_logsystem_name;
}
/**
* #param db_logsystem_name the db_logsystem_name to set
*/
public void setDb_logsystem_name(String db_logsystem_name) {
this.db_logsystem_name = db_logsystem_name;
}
}
And I am creating a object by in the controller class:
#Autowired
APPStaticProperties appStaticProperties;
But I wanted to know how do I pass the this object for use in other projects? Because my code flow goes from the controller to a JSP and then to a class in another project. I need the object available for use in that class. Well to be honest, in many other projects as well! I am not able to figure it out how to do it. Neither are there too many examples out there for reference.
You wouldn't normally inject an #Configuration bean into other Spring managed beans, because it sets up configuration to be used by other Spring managed beans.
For example, because you have declared an #PropertySource, to access your properties in other Spring managed means you can just inject properties into your code elsewhere using #Value. You don't need to inject your APPStaticProperties bean to do this.
I have clientDAO interface and clientDaoImpl class; I declared method in clientDAO and define method in clientDaoImpl. I also define mysql database connection in spring-servlet.xml ( which is spring-config file) as data source.
import java.util.Date;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.bind.annotation.RequestMapping;
#SessionAttributes
#Controller
public class clientRegistrationController {
#Autowired
private clientDAO clientdao;
#SessionAttributes
#Controller
public class ClientRegistrationController {
#RequestMapping( value="/registration",method = RequestMethod.POST)
public #ResponseBody
String client_registration(#RequestParam(value = "date_of_registration") Date date_of_registration)
// here i want to get pojo object and call method insert method which is
// defined in DAO implement class.
return " Registered successfully";
}
#RequestMapping("/registration")
public ModelAndView showContacts() {
String message = "Hello World, Spring MVC # Javatpoint";
return new ModelAndView("client_registration", "message",message);
}
}
I got following error:
SEVERE: Servlet [spring] in web application [/SpringTiles] threw load() exception
java.lang.Error: Unresolved compilation problems:
Autowired cannot be resolved to a type
clientDAO cannot be resolved to a type
I used /SpringTiles code available in javatpoint.com
this is my clientdao:
package dao;
import com.javatpoint.form.Client_Registration;
public interface clientDAO {
void insertData(Client_Registration patient);
}
Hope you have added #Repository on your clientDAO class. Spring is not able to find it at the load time.
Check your configurations (xml or java) whichever you have used for bean creation.
sharing Full error logs along with relevant snippet of code( here clientDAO and configuration) helps in faster error resolution.
You should inject you DAO like that :
<bean id="dao" class="com.elgarnaoui.ma.dao.AgentDao"></bean>
<bean id="metier" class="com.elgarnaoui.ma.metier.MetierAgent">
<property name="dao" ref="dao"></property>
</bean>
This exception comes when there is no any bean created of mentioned type.
Make sure you have added context:component-scan tag in your spring-servlet.xml file.
e.g.
and also check whether you have added #Repository annotation on Dao
I'm learning Spring as it seems to be a very powerful framework. I've already did many getting started guides and now I'm trying with this tutorial. In it, all classes are put in the same package, but to make it more interesting I tried using different packages according to the class (entity, controller, etc.). I was about to test it before the Testing a REST Service section but got an error building the application. This is how my project is structured:
The only difference with the classes in the tutorial is the marked ServletInitializer which comes with the initializr utility (actually I used the one that comes with STS, but it's the same). As far as I understand, it has nothing to do with the problem so the content of this class is irrelevant.
Another minor difference with the tutorial is that the Application class here is called RestServicesApplication but the content is the same.
When I try to build the application (using Gradle's bootRun instead of Maven) I got the following error message:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method init in com.example.restservices.RestServicesApplication required a bean of type 'com.example.repository.AccountRepository' that could not be found.
Action:
Consider defining a bean of type 'com.example.repository.AccountRepository' in your configuration.
:bootRun FAILED
So I tried to annotate AccountRepository with #Bean but it gives me a compilation error saying that the annotation is disallowed for that location. Next I tried with the #Component annotation (also on BookmarkRepository) and adding #ComponentScan("com.example") in RestServicesApplication. After that the error remains but the message changed to
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.controller.BookmarkRestController required a bean of type 'com.example.repository.BookmarkRepository' that could not be found.
Action:
Consider defining a bean of type 'com.example.repository.BookmarkRepository' in your configuration.
:bootRun FAILED
I added #Component annotation to BookmarkRestController but the same error message remains. What am I missing here?
Thanks in advance for your answers.
Edit #1
The classes involved in the problem are the following (copied from my project, not the ones in the tutorial, although the differences are minimal):
RestServicesApplication
package com.example.restservices;
import java.util.Arrays;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import com.example.entity.Account;
import com.example.entity.Bookmark;
import com.example.repository.AccountRepository;
import com.example.repository.BookmarkRepository;
#SpringBootApplication
#ComponentScan("com.example")
public class RestServicesApplication {
public static void main(final String[] args) {
SpringApplication.run(RestServicesApplication.class, args);
}
#Bean
CommandLineRunner init(final AccountRepository accountRepository,
final BookmarkRepository bookmarkRepository) {
return (evt) -> Arrays.asList(
"jhoeller,dsyer,pwebb,ogierke,rwinch,mfisher,mpollack,jlong".split(","))
.forEach(
a -> {
final Account account = accountRepository.save(new Account(a,
"password"));
bookmarkRepository.save(new Bookmark(account,
"http://bookmark.com/1/" + a, "A description"));
bookmarkRepository.save(new Bookmark(account,
"http://bookmark.com/2/" + a, "A description"));
});
}
}
BookmarkRestController
package com.example.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.repository.AccountRepository;
import com.example.repository.BookmarkRepository;
#RestController
#RequestMapping("/{userId}/bookmarks")
public class BookmarkRestController {
private final BookmarkRepository bookmarkRepository;
private final AccountRepository accountRepository;
#Autowired
public BookmarkRestController(final BookmarkRepository bookmarkRepository,
final AccountRepository accountRepository) {
this.bookmarkRepository = bookmarkRepository;
this.accountRepository = accountRepository;
}
// #RequestMapping methods...
}
AccountRepository
package com.example.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import com.example.entity.Account;
#Component
public interface AccountRepository extends JpaRepository<Account, Long> {
Optional<Account> findByUsername(String username);
}
BookmarkRepository
package com.example.repository;
import java.util.Collection;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import com.example.entity.Bookmark;
#Component
public interface BookmarkRepository extends JpaRepository<Bookmark, Long> {
Collection<Bookmark> findByAccountUsername(String username);
}
Note: I added the imports so you can see where the classes and annotations come from
Edit #2
I tried another thing: I refactored my Project to fit the tutorial and I put everithing in the same package (com.example.bookmarks) and removed the extra annotations. The Project compiles but when I run the Project I get a 404 HTTP status when trying to accesss a REST service. I'm still interested in make it run with my original structure but I want to let you know that this refactoring makes the Project work.
To have Spring create a bean that implements JpaRepository interface, you need to use Spring JPA namespace and activate the repository support using the appropriate element. In xml:
<jpa:repositories base-package="com.example.repository" />
In annotation:
#EnableJpaRepositories
See this docs
This scans all packages below com.example.repository for interfaces extending JpaRepository and creates a Spring bean for it that is backed by an implementation of SimpleJpaRepository.
I think you have to create package again. You packing looking not right. Recreate your package