I am creating a simple Spring WebMVC app with thymeleaf and now I want to add a service which provides a connection to a couchbase server.
I tried to create the couchbase service on basis of the following tutorial Couchbase with Spring-Boot and Spring Data
I have the following project structure:
src/main/java
com.project
config
MvcWebApplicationInitializer
MvcWebConfig
controller
IndexController
model
Area
Building
BuildingRepository
BuildingService
BuildingServiceImpl
When trying to autowire the service I get the exception that there is no bean named couchbaseRepositoryOperationsMapping which happens because my repository class extends CouchbasePagingAndSortingRepository which throws the exception.
I get the following exception:
[main] INFO org.springframework.web.servlet.DispatcherServlet -
Initializing Servlet 'dispatcher' [main] INFO
org.springframework.data.repository.config.RepositoryConfigurationDelegate
- Multiple Spring Data modules found, entering strict repository configuration mode! [main] INFO
org.springframework.data.repository.config.RepositoryConfigurationDelegate
- Bootstrapping Spring Data repositories in DEFAULT mode. [main] INFO org.springframework.data.repository.config.RepositoryConfigurationDelegate
- Finished Spring Data repository scanning in 64ms. Found 1 repository interfaces. [main] WARN
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
- Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'buildingServiceImpl': Unsatisfied
dependency expressed through field 'buildingRepository'; nested
exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'buildingRepository':
'buildingRepository' depends on missing bean
'couchbaseRepositoryOperationsMapping'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
bean named 'couchbaseRepositoryOperationsMapping' available [main]
ERROR org.springframework.web.servlet.DispatcherServlet - Context
initialization failed
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'buildingServiceImpl': Unsatisfied
dependency expressed through field 'buildingRepository'; nested
exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'buildingRepository':
'buildingRepository' depends on missing bean
'couchbaseRepositoryOperationsMapping'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
bean named 'couchbaseRepositoryOperationsMapping' available
As far as I understand it is not working because there is no bean
named couchbaseRepositoryOperationsMapping.
My MvcWebConfig:
#Configuration
#EnableWebMvc
#ComponentScan("com.xplorg.controller")
#EnableCouchbaseRepositories(basePackages = {"com.xplorg.model"})
public class MvcWebConfig implements WebMvcConfigurer {
#Autowired
private ApplicationContext applicationContext;
#Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
return templateResolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
public void configureViewResolvers(ViewResolverRegistry registry) {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
registry.viewResolver(viewResolver);
}
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
My pom.xml:
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.project</groupId>
<artifactId>xplorg</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>Project</name>
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7-1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-couchbase</artifactId>
<version>3.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.18.v20190429</version>
</plugin>
</plugins>
</build>
</project>
****Update****
Adding a CouchbaseConfig class fixed the problem with the couchbaseRepositoryOperationsMapping but I get now another error, that there is now named bean buildingRepository. All classes are based on the tutorial Couchbase with Spring-Boot and Spring Data. Do I miss an annotations and therefore spring can not autowire the class?
My repository class:
#N1qlPrimaryIndexed
#ViewIndexed(designDoc = "building")
public interface BuildingRepository extends CouchbasePagingAndSortingRepository<Building, String> {
List<Building> findByCompanyId(String companyId);
Page<Building> findByCompanyIdAndNameLikeOrderByName(String companyId, String name, Pageable pageable);
#Query("#{#n1ql.selectEntity} where #{#n1ql.filter} and companyId = $1 and $2 within #{#n1ql.bucket}")
Building findByCompanyAndAreaId(String companyId, String areaId);
#Query("#{#n1ql.selectEntity} where #{#n1ql.filter} AND ANY phone IN phoneNumbers SATISFIES phone = $1 END")
List<Building> findByPhoneNumber(String telephoneNumber);
#Query("SELECT COUNT(*) AS count FROM #{#n1ql.bucket} WHERE #{#n1ql.filter} and companyId = $1")
Long countBuildings(String companyId);
}
My service class:
#Service
public class BuildingServiceImpl implements BuildingService {
#Autowired
private BuildingRepository buildingRepository;
#Override
public List<Building> findByCompanyId(String companyId) {
return buildingRepository.findByCompanyId(companyId);
}
public List<Building> findByCompanyIdAndNameLike(String companyId, String name, int page) {
return buildingRepository.findByCompanyIdAndNameLikeOrderByName(companyId, name, new PageRequest(page, 20))
.getContent();
}
#Override
public Building findByCompanyAndAreaId(String companyId, String areaId) {
return buildingRepository.findByCompanyAndAreaId(companyId, areaId);
}
#Override
public List<Building> findByPhoneNumber(String telephoneNumber) {
return buildingRepository.findByPhoneNumber(telephoneNumber);
}
#Override
public Building findById(String buildingId) {
return buildingRepository.findById(buildingId).get();
}
#Override
public Building save(Building building) {
return buildingRepository.save(building);
}
#Override
public Long countBuildings(String companyId) {
return buildingRepository.countBuildings(companyId);
}
}
You missed the config class couchebase server
Create a dedicate config class extending the AbstractCouchbaseConfiguration for your couhcebase as below ( server # , user , pwd )
#Configuration
#EnableCouchbaseRepositories(basePackages = {"com.xplorg.model"})
public class CouchbaseConfig extends AbstractCouchbaseConfiguration {
#Override
protected List<String> getBootstrapHosts() {
return Arrays.asList("your server ip (like localhost in local)");
}
#Override
protected String getBucketName() {
return "username";
}
#Override
protected String getBucketPassword() {
return "passsword";
}
}
also change #ComponentScan("com.xplorg.controller") to #ComponentScan("com.xplorg") in your project config so your repositories interface and service should be scanned
Related
I am building a REST API using spring boot with a MYSQL database, my app installs successfully but when running the main application I receive this error
2020-06-22 15:40:30.638 WARN 8412 --- [ restartedMain] ConfigServletWebServerApplicationContext :
Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name
'itemController': Unsatisfied dependency expressed through field 'itemService'; nested exception
is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name
'itemService': Unsatisfied dependency expressed through field 'todoItemRepository'; nested exception
is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'itemRepository':
Cannot create inner bean '(inner bean)#5b270c70' of type [org.springframework.orm.jpa.SharedEntityManagerCreator]
while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name '(inner bean)#5b270c70': Cannot resolve reference to bean 'entityManagerFactory'
while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
Following are my files:
Controller:
#RestController
#RequestMapping("/todo")
public class ItemController {
#Autowired
private ItemService itemService;
//methods
}
Model:
#Entity
#Table(name = "TODO")
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "itemId")
private Long itemId;
//other variables followed by setters and getters
service:
#Service
public class ItemService {
#Autowired
private ItemRepository todoItemRepository;
public Item saveTodoItem(Item item) {
return todoItemRepository.save(item);
}
//other methods
}
Repository:
#Repository
public interface ItemRepository extends JpaRepository<Item, Long> {
Item findByItemId(Long itemId);
List<Item> findByListId(UUID listId);
}
Configuration files:
public class BasicInitialize extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] {
TnDserviceApplication.class
};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[]{
null
};
}
}
persistence config:
#Configuration
#EnableTransactionManagement
#ComponentScan("com.example.TNDservice.config")
#PropertySource({"classpath:application.properties"})
public class PersistenceConfig {
// Class which call the application properties
#Autowired
private Environment env;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean bean = new LocalSessionFactoryBean();
bean.setDataSource(dataSource());
bean.setPackagesToScan("com.example.TNDservice.Entity");
bean.setHibernateProperties(propertiesForHibernate());
return bean;
}
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getRequiredProperty("jdbc.url"));
dataSource.setUsername(env.getRequiredProperty("jdbc.username"));
dataSource.setPassword(env.getRequiredProperty("jdbc.password"));
return dataSource;
}
#Bean
Properties propertiesForHibernate() {
Properties properties = new Properties();
properties.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", env.getRequiredProperty("hibernate.format_sql"));
properties.put("hibernate.ddl-auto", env.getRequiredProperty("hibernate.ddl-auto"));
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager();
hibernateTransactionManager.setSessionFactory(sessionFactory);
return hibernateTransactionManager;
}
}
application.propoties
jdbc.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
jdbc.url=jdbc:mysql://localhost:3306/?user=root
jdbc.username=root
jdbc.password=1234
hibernate.dialect=org.hibernate.dialect.SQLServerDialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.ddl-auto=validate
pom.xml
<?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.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>TNDservice</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>TNDservice</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<pluginRepositories>
<pluginRepository>
<id>icm</id>
<name>Spring Framework Milestone Repository</name>
<url>http://maven.icm.edu.pl/artifactory/repo</url>
</pluginRepository>
</pluginRepositories>
<build>
<finalName>RESTservice</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
Appreciate any help regarding this matter! Thank you!
your dependency shows that you want to connect with mysql database.
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
But, in database properties, you have provided microsoft sql DB info.
jdbc.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
jdbc.url=jdbc:mysql://localhost:3306/?user=root
jdbc.username=root
jdbc.password=1234
There is no compatibility to connect 2 diff databases.
see the diff between mysql and microsoft sql database server.
https://www.tutorialspoint.com/difference-between-mysql-and-sql-server#:~:text=Both%20MySQL%20and%20SQL%20Server,is%20licensed%20product%20of%20Microsoft.&text=SQL%20Server%20supports%20programming%20languages,Visual%20Basic%2C%20Delphi%2C%20R.
Here are my configuration classes::
In the templateResolver() method without ServletContext parameter i get compile error so add it as a parameter and give it to ServletContextTemplateResolver(servletContext);
#Configuration
#EnableWebMvc
#ComponentScan(basePackages= {"com.packtpub.springsecurity"})
public class ThymeleafConfig {
#Bean
public ServletContextTemplateResolver templateResolver(ServletContext servletContext) {
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(servletContext);
resolver.setPrefix("/WEB-INF/templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setCacheable(false);
resolver.setOrder(1);
return resolver;
}
#Bean
public SpringTemplateEngine templateEngine(final ServletContextTemplateResolver templateResolver) {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver);
return engine;
}
#Bean
public ThymeleafViewResolver thymeleafViewResolver(final SpringTemplateEngine templateEngine) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine);
return resolver;
}
}
When i run my application i get following error:::
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method templateResolver in com.packtpub.springsecurity.web.configuration.ThymeleafConfig required a bean of type 'javax.servlet.ServletContext' 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 'javax.servlet.ServletContext' in your configuration.
What am i doing wrong?
thanks
Other config files are
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>chapter2</groupId>
<artifactId>chapter2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>chapter2</name>
<description>chapter 2 test</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Spring dependencies START-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<!-- Servlet and JSP related dependencies -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>javax.servlet.jsp.jstl-api</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!-- For datasource configuration -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
</dependency>
<!-- We will be using MySQL as our database server -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<!-- Spring dependencies END -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20170516</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
#Configuration
//#Import({SecurityConfig.class, DataSourceConfig.class})
#ComponentScan(basePackages =
{
"com.packtpub.springsecurity.dataaccess",
"com.packtpub.springsecurity.domain",
"com.packtpub.springsecurity.service"
}
)
#PropertySource(value = {"classpath:application.properties"})
public class JavaConfig {
/**
* Note: If you want to use #PropertySource, you must create a static
* PropertySourcesPlaceholderConfigurer with the #Bean as seen here.
* #return PropertySourcesPlaceholderConfigurer
* #throws java.io.IOException
*/
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() throws IOException {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setIgnoreUnresolvablePlaceholders(Boolean.TRUE);
propertySourcesPlaceholderConfigurer.setProperties(yamlPropertiesFactoryBean().getObject());
return propertySourcesPlaceholderConfigurer;
}
#Bean
public static YamlPropertiesFactoryBean yamlPropertiesFactoryBean() {
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("application.yml"));
return yaml;
}
} // The end...
#Order(1)
public class SecurityWebAppInitializer
extends AbstractSecurityWebApplicationInitializer {
/**
* Don't initialize the filter directly, the Spring WebApplicationInitializer
* parent will take care of the initialization.
*/
public SecurityWebAppInitializer() {
super();
}
} // The end...
public class WebAppInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { JavaConfig.class, SecurityConfig.class, DataSourceConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebMvcConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/*" };
}
#Override
public void onStartup(final ServletContext servletContext)
throws ServletException {
// Register DispatcherServlet
super.onStartup(servletContext);
// Register H2 Admin console:
ServletRegistration.Dynamic h2WebServlet = servletContext.addServlet("h2WebServlet",
"org.h2.server.web.WebServlet");
h2WebServlet.addMapping("/admin/h2/*");
h2WebServlet.setInitParameter("webAllowOthers", "true");
}
} // The End...
#Configuration
#EnableWebMvc
#Import({ThymeleafConfig.class})
#ComponentScan(basePackages = {
"com.packtpub.springsecurity.web.controllers",
"com.packtpub.springsecurity.web.model"
})
public class WebMvcConfig extends WebMvcConfigurerAdapter
{
#Autowired
private ThymeleafViewResolver thymeleafViewResolver;
/**
* We mention this in the book, but this helps to ensure that the intercept-url patterns prevent access to our
* controllers. For example, once security has been applied for administrators try commenting out the modifications
* to the super class and requesting <a
* href="http://localhost:800/calendar/events/.html">http://localhost:800/calendar/events/.html</a>. You will
* observe that security is bypassed since it did not match the pattern we provided. In later chapters, we discuss
* how to secure the service tier which helps mitigate bypassing of the URL based security too.
*/
// FIXME: FInd out what this is and why it is here.
#Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping result = new RequestMappingHandlerMapping();
result.setUseSuffixPatternMatch(false);
result.setUseTrailingSlashMatch(false);
return result;
}
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/")
.setCachePeriod(31_556_926)
;
}
#Override
public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
configurer
.ignoreAcceptHeader(false)
.favorPathExtension(true) // .html / .json / .ms
.defaultContentType(MediaType.TEXT_HTML) // text/html
.mediaTypes(
new HashMap<String, MediaType>(){
{
put("html", MediaType.TEXT_HTML);
put("xml", MediaType.APPLICATION_XML);
put("json", MediaType.APPLICATION_JSON);
}
})
;
}
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter());
}
/*#Bean
public ContentNegotiatingViewResolver contentNegotiatingViewResolver() {
ContentNegotiatingViewResolver result = new ContentNegotiatingViewResolver();
Map<String, String> mediaTypes = new HashMap<>();
mediaTypes.put("json", MediaType.APPLICATION_JSON_VALUE);
// result.setMediaTypes(mediaTypes);
result.setDefaultViews(Collections.singletonList(jacksonView()));
return result;
}*/
#Bean
public MappingJackson2JsonView jacksonView() {
MappingJackson2JsonView jacksonView = new MappingJackson2JsonView();
jacksonView.setExtractValueFromSingleKeyModel(true);
Set<String> modelKeys = new HashSet<String>();
modelKeys.add("events");
modelKeys.add("event");
jacksonView.setModelKeys(modelKeys);
return jacksonView;
}
#Override
public void configureViewResolvers(final ViewResolverRegistry registry) {
registry.viewResolver(thymeleafViewResolver);
}
// i18N support
#Bean
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource resource = new ReloadableResourceBundleMessageSource();
resource.setBasenames("/WEB-INF/locales/messages");
resource.setDefaultEncoding("UTF-8");
resource.setFallbackToSystemLocale(Boolean.TRUE);
return resource;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
configurer.enable();
}
}
UPDATED
I have deleted the following dependencies from the POM according to #Adina in the comment below but still get the errors
<!-- dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>javax.servlet.jsp.jstl-api</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency-->
What else can i do again
After some debugging on your code, the real problem is that you are autowiring ThymeleafViewResolver in the configuration responsible to configure servlet context.
public class WebMvcConfig implements WebMvcConfigurer{
#Autowired
private ThymeleafViewResolver thymeleafViewResolver;
The main problem is that before initializing your ServletContext, the application will try to initialize the ServletContextTemplateResolver (autowired will impose bean order initialization) and as you've noticed it depends on ServletContext.
Solution :
delete ThymeleafConfig class
don't autowire ThymeleafViewResolver in WebMvcConfig
and don't override method configureViewResolvers.
Don't worry, Thymeleaf will be set by default as the viewResolver.
Most of the config you've provided is already "taken care" by spring-boot-starter-thymeleaf.
If you want just to change default view directory resolver, you can just add in application.properties
spring.mvc.view.prefix=/WEB-INF/templates/
spring.mvc.view.suffix=.html
P.S: Take extra care when you override default definition from spring starters, as you can see these types of bugs are not easy to find.
I am trying to write an integration test for a spring boot JPA application using h2 database. Somehow TestEntityManager is not getting created. I tried look for some help on the forum but could not find any relevant information.
Appreciate if anybody can help or provide some direction.
Thanks.
My code is as follows:
Repository:
#Repository
public interface ConfigRepository extends JpaRepository<Config, Long> {
Config findByKey(ConfigKey configKey);
}
Configuration:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "testEntityManagerFactory",
transactionManagerRef = "testTransactionManager",
basePackages = "com.abc.xyz.business.repository")
public class TestPersistenceConfig {
private static final String TEST_PERSISTENCE_UNIT = "emTestPersistenceUnit";
#Bean(name = "testEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws SQLException {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPackagesToScan(new String[] { "nl.rabobank.rom.exception.manager.rom.em.business.domain" });
entityManagerFactoryBean.setPersistenceUnitName(TEST_PERSISTENCE_UNIT);
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
entityManagerFactoryBean.setJpaProperties(additionalProperties());
return entityManagerFactoryBean;
}
#Bean
#Profile("test")
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1");
dataSource.setUsername("sa");
dataSource.setPassword("sa");
return dataSource;
}
#Bean(name = "testTransactionManager")
public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
private Properties additionalProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("em.hibernate.hbm2ddl.auto", "none");
hibernateProperties.setProperty("hibernate.show_sql", "true");
hibernateProperties.setProperty("hibernate.format_sql", "true");
hibernateProperties.setProperty("em.hibernate.naming.physical-strategy", "org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl");
hibernateProperties.setProperty("em.properties.hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
return hibernateProperties;
}
}
Test:
#RunWith(SpringRunner.class)
#DataJpaTest
#ActiveProfiles("test")
#ContextConfiguration(classes = {TestPersistenceConfig.class})
public class ConfigRepositoryTest {
#Autowired
private TestEntityManager entityManagerFactory;
#Autowired
private ConfigRepository configRepository;
#Test
public void test1() {
Config config =
configRepository.findByKey(ConfigKey.PURGE_DATE_RETENTION_CALENDAR_TYPE);
assertNotNull(config);
}
}
POM.xml:
<?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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<!-- To run tests on IDE such as Eclipse, Intellij -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4-common</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc7</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Stacktrace:
java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'TestExceptionHandlerEntityManagerFactory' defined in nl.rabobank.rom.exception.manager.rom.em.business.TestPersistenceConfig: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean]: Factory method 'entityManagerFactory' threw exception; nested exception is java.lang.IllegalArgumentException: No visible constructors in class org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration$EmbeddedDataSourceFactoryBean
...
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean]: Factory method 'entityManagerFactory' threw exception; nested exception is java.lang.IllegalArgumentException: No visible constructors in class org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration$EmbeddedDataSourceFactoryBean
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:579)
... 42 more
Caused by: java.lang.IllegalArgumentException: No visible constructors in class org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration$EmbeddedDataSourceFactoryBean
at org.springframework.cglib.proxy.Enhancer.filterConstructors(Enhancer.java:666)
at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:567)
If you have a production type database in tests you must add #AutoConfigureTestDatabase(replace=Replace.NONE) to Test classes.
Just add above annotation to ConfigRepositoryTest class to resolve your problem.
#RunWith(SpringRunner.class)
#DataJpaTest
#ActiveProfiles("test")
#ContextConfiguration(classes = {TestPersistenceConfig.class})
#AutoConfigureTestDatabase(replace=Replace.NONE)
public class ConfigRepositoryTest {
...
}
I have problem with new Spring Boot version 2.0.0.
I need to create SessionFactory bean, for that I need Spring to inject EntityManager.
package cz.moravec;
import cz.moravec.provisioning.Provisioner;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceUnit;
#SpringBootApplication
#EntityScan("cz.moravec.data")
public class Main {
// #Bean
// public CountryDao countryDao() {
// return new CountryDao();
// }
//
// #Bean
// public TownDao townDao() {
// return new TownDao();
// }
#Autowired
#Bean
#Transactional
public SessionFactory sessionFactory(EntityManager entityManager) {
Session session = entityManager.unwrap(Session.class);
return session.getSessionFactory();
}
#Profile({"devel", "test"})
#Bean(initMethod = "doProvision")
public Provisioner provisioner() {
return new Provisioner();
}
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Main.class);
ApplicationContext ctx = app.run(args);
// CountryDao countryDao = ctx.getBean(CountryDao.class);
// List<Country> countries = countryDao.getCountries();
// UsersDao usersDao = ctx.getBean(UsersDao.class);
//
// List<User> users = usersDao.getAllUsers();
// System.out.println(users);
}
}
This code works when using Spring Boot 1.5.11.RELEASE. But does not with Spring Boot 2.0.0.RELEASE.
When I run code ApplicationContext is not created because of cycle dependency.
There is output from console.
19:44:31.282 [main] WARN o.s.c.a.AnnotationConfigApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sessionFactory' defined in cz.moravec.Main: Unsatisfied dependency expressed through method 'sessionFactory' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.orm.jpa.SharedEntityManagerCreator#0': Cannot resolve reference to bean 'sessionFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'sessionFactory': Requested bean is currently in creation: Is there an unresolvable circular reference?
Disconnected from the target VM, address: '127.0.0.1:11537', transport: 'socket'
19:44:31.286 [main] INFO o.s.b.a.l.ConditionEvaluationReportLoggingListener -
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
19:44:31.288 [main] ERROR o.s.b.d.LoggingFailureAnalysisReporter -
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| sessionFactory defined in cz.moravec.Main
↑ ↓
| org.springframework.orm.jpa.SharedEntityManagerCreator#0
└─────┘
Maven pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cz.moravec</groupId>
<artifactId>semester_project</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</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>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
</project>
Is is a MUST to set the SessionFactory as bean when init the SpringBoot application?
Another solution is to get the hibernate sessionFactory / session in your Dao classes.
Following is an example:
#Repository
public class CountryDao {
#Autowired
private EntityManagerFactory entityManagerFactory;
private Session getSessionFactory() {
return entityManagerFactory.unwrap(SessionFactory.class);
}
...
}
I can successfully get the SessionFactory in the Dao class.
But if your purpose is to only get the current Hibnerate Session object, following is a more cleaner way:
#Repository
public class CountryDao {
#Autowired
private EntityManager entityManager;
private Session getSession() {
return entityManager.unwrap(Session.class);
}
...
}
The SpringBoot i'm testing is 2.1.3.RELEASE
Here is my SOLR Data Model,
#SolrDocument(solrCoreName = "solrData")
public class SolrData {
#Id
#Indexed(name = "id", type = "string")
String id;
#Indexed(name = "name", type = "string")
String name;
This SOLR configuration,
#Configuration
#EnableSolrRepositories(basePackages={"com.ows.repository.solrRepository"}, multicoreSupport=true)
#ComponentScan
public class SolrConfig {
static final String SOLR_HOST = "http://localhost:8983/solr/";
#Bean
public SolrClient solrClient() {
return new HttpSolrClient.Builder(SOLR_HOST).build();
}
#Bean
public SolrTemplate solrTemplate(SolrClient solrClient) throws Exception {
return new SolrTemplate(solrClient);
}
}
The repository,
public interface SolrProductRepository extends SolrCrudRepository<SolrData, String> {
List<SolrData> findByName(String name);
}
The index controller,
#Autowired
SolrProductRepository solrProductRepository;
#RequestMapping("/solrindex")
public void solrIndex(Model model) {
SolrData solrData = new SolrData();
solrData.setName("You know Who");
solrProductRepository.save(solrData);
}
POM.xml
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-solr</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-common</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>6.6.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
With the above settings while I go for indexing using the index controller it says,
Updated complete error messages.
org.springframework.data.solr.UncategorizedSolrException: org.apache.solr.common.SolrInputDocument cannot be cast to java.util.Map; nested exception is java.lang.ClassCastException: org.apache.solr.common.SolrInputDocument cannot be cast to java.util.Map
at org.springframework.data.solr.core.SolrTemplate.execute(SolrTemplate.java:224)
at org.springframework.data.solr.core.SolrTemplate.saveBean(SolrTemplate.java:330)
at org.springframework.data.solr.core.SolrTemplate.saveBean(SolrTemplate.java:318)
at org.springframework.data.solr.core.SolrTemplate.saveBean(SolrTemplate.java:300)
at org.springframework.data.solr.repository.support.SimpleSolrRepository.save(SimpleSolrRepository.java:149)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:504)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:489)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461)
Caused by: java.lang.ClassCastException: org.apache.solr.common.SolrInputDocument cannot be cast to java.util.Map
at org.springframework.data.solr.core.convert.MappingSolrConverter.write(MappingSolrConverter.java:62)
at org.springframework.data.solr.core.SolrTemplate.convertBeanToSolrInputDocument(SolrTemplate.java:1132)
at org.springframework.data.solr.core.SolrTemplate$4.doInSolr(SolrTemplate.java:335)
at org.springframework.data.solr.core.SolrTemplate$4.doInSolr(SolrTemplate.java:330)
at org.springframework.data.solr.core.SolrTemplate.execute(SolrTemplate.java:220)
... 129 more
SOLVED
I solved the problem with below settings,
The sole configuration file is changed to below,
#Configuration
#EnableSolrRepositories(basePackages={"com.ows.rokomari.repository.solrRepository"}, multicoreSupport=true)
#ComponentScan
public class SolrConfig {
static final String SOLR_HOST = "http://localhost:8983/solr";
#Bean
public SolrClient solrClient() {
return new HttpSolrClient(SOLR_HOST);
}
#Bean
public SolrTemplate solrTemplate(SolrClient solrClient) throws Exception {
return new SolrTemplate(solrClient);
}
}
The pom.xml file is changed to below settings,
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-solr</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-common</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
Now everything is quite fine.
I included solr-common because other than this the project throws error. Since my project is spring and running on version 4 with some other old dependencies. I guess the updated Solr related dependencies conflicts with existing dependencies, which is resolved by this one.
I used spring-data-solr which is bit different from using Solrj. Solrj implemation can be found here