I am trying to search data from H2 database using elasticsearch. elasticsearch work fine in my project.I added elasticsearch externally.when i add data using constructor it adds to elasticsearch.but if try to add data from H2 database to elasticsearch I am getting this error.
-Error creating bean with name 'itemMigrator' defined in file.
-Error creating bean with name 'userJpaRepository': Invocation of init method failed;
-No property findAll found for type User!
spring-boot-starter-parent 2.0.6.RELEASE
elasticsearch version-5.6.12
I am following this example https://www.hameister.org/SpringBootElasticsearch.html
http://techprimers.com/spring-data-elastic-search-example-3-using-spring-jpa/
User.java
#Entity
#Document(indexName = "user", type = "user", shards = 1)
#Table(name = "user_detail")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#NotBlank
#Column(name = "first_name")
private String firstName;
#NotBlank
#Column(name = "last_name")
private String lastName;
SearchQueryBuilder.java
#Component
public class SearchQueryBuilder {
private ElasticsearchTemplate elasticsearchTemplate;
#Autowired
public SearchQueryBuilder(ElasticsearchTemplate elasticsearchTemplate) {
this.elasticsearchTemplate = elasticsearchTemplate;
}
public List<User> getAll(String text) {
QueryBuilder query = QueryBuilders.boolQuery()
.should(
QueryBuilders.queryStringQuery(text)
.lenient(true)
.field("firstName")
.field("role")
).should(QueryBuilders.queryStringQuery("*" + text + "*")
.lenient(true)
.field("firstName")
.field("role"));
NativeSearchQuery build = new NativeSearchQueryBuilder()
.withQuery(query)
.build();
List<User> userses = elasticsearchTemplate.queryForList(build, User.class);
return userses;
}
}
ItemMigrator.java
#Autowired
ElasticsearchOperations operations;
#Autowired
UsersRepository UsersRepository;
#Autowired
UserJpaRepository jpaRepository;
#Autowired
public ItemMigrator(UserJpaRepository jpaRepository, ElasticsearchTemplate operations, UsersRepository UsersRepository) {
this.jpaRepository = jpaRepository;
this.operations = operations;
this.UsersRepository = UsersRepository;
}
#PostConstruct
#Transactional
public void loadAll() {
Iterable<User> items = jpaRepository.findAll();
operations.putMapping(User.class);
UsersRepository.saveAll(items);
}
}
UserJpaRepository.java
public interface UserJpaRepository extends JpaRepository<User, Long>
UsersRepository.java
public interface UsersRepository extends ElasticsearchRepository<User, Long>{
List<User> findByFirstName(String text);
List<User> findByRole(String text);
ManualSearchResource.java
#RestController
#RequestMapping("/rest/manual/search")
public class ManualSearchResource {
#Autowired
private SearchQueryBuilder searchQueryBuilder;
#GetMapping(value = "/{text}")
public List<User> getAll(#PathVariable final String text) {
return searchQueryBuilder.getAll(text);
}
}
Config.java
#Configuration
#EnableJpaRepositories(basePackages = "net.kzn.shoppingbackend")
#EnableElasticsearchRepositories(basePackages = "net.kzn.shoppingbackend")
#ComponentScan(basePackages = { "net.kzn.shoppingbackend" })
public class Config {
#Bean
public Client client() throws UnknownHostException {
Settings settings = Settings.builder()
.put("client.transport.sniff", true)
.put("cluster.name", "elasticsearch").build();
#SuppressWarnings("resource")
TransportClient client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
return client;
}
#Bean
public ElasticsearchOperations elasticsearchTemplate() throws UnknownHostException {
return new ElasticsearchTemplate(client());
}
}
This is my stacktrace https://www.dropbox.com/s/nxf2a3m961dx7a7/elastic_error.txt?dl=0
Is it correct to add both #Entity and #Document is same class?Please tell me what am i doing wrong here.
Related
I have some trouble to get the right config for jpa repository for elasticsearch.
The configuration is for aws elasticsearch
#Component
public class AmazonElasticSearchConnector implements AmazonElasticSearchClient {
#Value("${elasticsearch.endpoint}")
private String elasticSearchEndpoint;
#Bean
public RestHighLevelClient createClient() {
return createClient(elasticSearchEndpoint);
}
}
and then i have another config
#Configuration
public class ESConfig {
#Autowired
private RestHighLevelClient client;
#Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchRestTemplate(client);
}
}
Here my Entity
#Entity
#Document(indexName = "item")
public class SupplierItemFilterResponseEntity {
#ElementCollection
private List<String> searchCollect;
#Id
private int id;
....
and my nested Entity
#Entity
#Document(indexName = "item")
public class TechnologyFilterEntity {
public int getTechnologyID() {
return technologyID;
}
public void setTechnologyID(int technologyID) {
this.technologyID = technologyID;
}
....
and I have a repository
public interface SupplierItemFilterESRepository extends
ElasticsearchRepository<SupplierItemFilterResponseEntity, Integer> {
}
And then the service that encountered an error
#Autowired
private RestHighLevelClient client;
#Autowired
private SupplierItemFilterESRepository supplierItemFilterESRepository;
public Page<SupplierItemFilterResponseEntity> getSupplierWithGivenFiltersPagination(Pageable pageable) {
return supplierItemFilterESRepository.findAll(pageable);
}
....
and the Error i get is following
No property indexWithoutRefresh found for type SupplierItemFilterResponseEntity!
Im on it for 2 days now, and my expertise is over. Maybe someone has the same problem.
Cheers and thank you if you can help!
I am trying to build an simple CRM spring app with a security layer.
My use case is simple : login page which allows the access the customer list and also to add new user from it.
I have created a client config class for the customer management and a security config class.
The security config file defined it own data source, transactional manager and session factory to access a dedicated db which manage the users :
#Configuration
#EnableWebSecurity
#PropertySource("classpath:security-persistence-mysql.properties")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
Environment env;
private Logger logger = Logger.getLogger(getClass().getName());
#Autowired
private UserDetailsService userService;
#Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
#Bean(name = "securitySessionFactory")
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(securityDataSource());
sessionFactory.setHibernateProperties(hibernateProperties());
sessionFactory.setPackagesToScan("com.luv2code.springdemo");
return sessionFactory;
}
#Bean(name = "securityDataSource")
public DataSource securityDataSource() {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
try {
dataSource.setDriverClass(env.getProperty("jdbc.driver"));
} catch (PropertyVetoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
dataSource.setUser(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.password"));
dataSource.setJdbcUrl(env.getProperty("jdbc.security.url"));
logger.info("URL security config : " + env.getProperty("jdbc.url"));
dataSource.setInitialPoolSize(
getPropertyAsInt("connection.pool.initialPoolSize"));
dataSource.setMinPoolSize(
getPropertyAsInt("connection.pool.minPoolSize"));
dataSource.setMaxPoolSize(
getPropertyAsInt("connection.pool.maxPoolSize"));
dataSource.setMaxIdleTime(
getPropertyAsInt("connection.pool.maxIdleTime"));
return dataSource;
}
private int getPropertyAsInt(String key) {
return Integer.parseInt(env.getProperty(key));
}
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(authenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/customer/**").hasRole("EMPLOYE")
.antMatchers("/leaders/**").hasRole("MANAGER")
.antMatchers("/systems/**").hasRole("ADMIN")
.antMatchers("/", "/home", "/createUser").permitAll()
.anyRequest().authenticated().and().formLogin()
.loginPage("/showMyLoginPage")
.loginProcessingUrl("/authentificateTheUser")
.successHandler(customAuthenticationSuccessHandler).permitAll()
.and().logout().permitAll().and().exceptionHandling()
.accessDeniedPage("/access-denied");
}
private Properties hibernateProperties() {
Properties hibernatePpt = new Properties();
hibernatePpt.setProperty("hibernate.dialect",
env.getProperty("hibernate.dialect"));
hibernatePpt.setProperty("hibernate.show_sql",
env.getProperty("hibernate.show_sql"));
hibernatePpt.setProperty("hibernate.packagesToScan",
env.getProperty("hibernate.packagesToScan"));
return hibernatePpt;
}
#Bean(name = "securtiyTransactionManager")
#Autowired
#Qualifier("securitySessionFactory")
public HibernateTransactionManager transactionManager(
SessionFactory sessionFactory) {
// setup transaction manager based on session factory
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userService);
auth.setPasswordEncoder(passwordEncoder());
return auth;
}
}
For the security and login I am not using the default user management but a custom one with a Role and User entity with a join table :
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "username")
private String userName;
#Column(name = "password")
private String password;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "email")
private String email;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "users_roles", joinColumns = #JoinColumn(name = "user_id"), inverseJoinColumns = #JoinColumn(name = "role_id"))
private Collection<Role> roles;
//constructors, getter,setter
}
Role :
#Entity
#Table(name = "role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
//.....
}
I use a service and dao layer to access the user with hibernate.
My issue is that when I try to loggin or add a user I have an exception : Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
The thing is use the transactional annotation.
First I go through the controller :
#Controller
public class LoginController {
#GetMapping("/showMyLoginPage")
public String showMyLoginPage() {
return "login";
}
#GetMapping("/access-denied")
public String showAccesDenied() {
return "access-denied";
}
}
Then the jsp :
<form:form method="POST" action="${pageContext.request.contextPath}/authenticateTheUser">
User name :
Password :
</form:form>
<form:form method="GET" action="${pageContext.request.contextPath}/createUser">
<input type="submit" value="Registration">
</form:form>
When the jsp is submitted it calls the user service details (Autowired in the config class) and the method loadUserByUsername which is under transaction :
public interface UserService extends UserDetailsService
#Service
#Transactional("securtiyTransactionManager")
public class UserServiceImpl implements UserService {
#Autowired
private UserDAO userDAO;
#Override
public UserDetails loadUserByUsername(String userName)
throws UsernameNotFoundException {
User user = userDAO.getUser(userName);
if (user == null) {
throw new UsernameNotFoundException(
"Invalid username or password.");
}
return new org.springframework.security.core.userdetails.User(
user.getUserName(), user.getPassword(),
mapRolesToAuthorities(user.getRoles()));
}
private Collection<? extends GrantedAuthority> mapRolesToAuthorities(
Collection<Role> roles) {
return roles.stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
}
}
Somehow the transaction is not working but I don't know why.
I parallel I have my other config file which manage the customer use cases.
Thx for any help to understand what is wrong.
For information the full project is here : https://github.com/moutyque/CRM
#Bean(name = "securtiyTransactionManager")
#Autowired
public HibernateTransactionManager transactionManager(
#Qualifier("securitySessionFactory") SessionFactory sessionFactory) {
// setup transaction manager based on session factory
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
I can only guess your error with just looking at it. You can open log level for transactions to examine issue. Qualifier can be inline in method parameter to ensure securitySessionFactory is autowired.
I have the most common project on Spring Boot MVC. and I'm trying to write update data via PUT.
#RestController
#RequestMapping(CommentController.PATH)
public class CommentController {
public final static String PATH = "/comments";
#Autowired
private CommentService service;
#PutMapping("/{id}")
public Comment update(#RequestBody Comment comment, #PathVariable Long id) {
return service.update(id, comment);
}
}
#Service
public class CommentService {
#Autowired
private CommentRepository repository;
public Comment update(Long id, Comment entity) {
Optional<Comment> optionalEntityFromDB = repository.findById(id);
return optionalEntityFromDB
.map(e -> saveAndReturnSavedEntity(entity, e))
.orElseThrow(getNotFoundExceptionSupplier("Cannot update - not exist entity by id: " + id, OBJECT_NOT_FOUND));
}
private Comment saveAndReturnSavedEntity(Comment entity, Comment entityFromDB) {
entity.setId(entityFromDB.getId());
return repository.save(entity);
}
}
#Repository
public interface CommentRepository extends JpaRepository<Comment, Long> {
}
#Entity
public class Comment {
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
#Column(name = "name")
protected String name;
}
then I write a test with the ability to check for updated data:
#SpringBootTest
#RunWith(SpringRunner.class)
#Transactional
// DBUnit config:
#DatabaseSetup("/comment.xml")
#TestExecutionListeners({
TransactionalTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
DbUnitTestExecutionListener.class
})
public class CommentControllerTest {
private MockMvc mockMvc;
private static String route = PATH + "/{id}";
#Autowired
private CommentController commentController;
#Autowired
private CommentRepository commentRepository;
#PersistenceContext
private EntityManager entityManager;
#Before
public void setup() {
mockMvc = MockMvcBuilders.standaloneSetup(commentController)
.build();
}
#Test
public void update_ShouldReturnCreated2() throws Exception {
int id = 1;
String name = "JohnNew";
Comment expectedComment = new Comment();
expectedComment.setName(name);
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(expectedComment);
this.mockMvc.perform(put(route, id)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(json))
.andDo(print());
entityManager.clear();
entityManager.flush();
Comment commentUpdated = commentRepository.findById(1L).get();
assertThat(commentUpdated.getName(), equalTo(name)); // not equals!
}
}
comment.xml:
<dataset>
<Comment id="1" name="John" />
</dataset>
but the problem is that the data is not updated.
If you enable the logging of Hibernat, then there is also no update request to the database.
What am I doing wrong?
You are missing off the #Transactional annotation from your CommentService. Whilst it can be better to add it at the per-method level, try adding it to class level to verify this fixes things:
#Service
#Transactional
public class CommentService {
I am using Spring Boot 1.5.3.RELEASE to build a new MVC application.
I have a Customer entity as follows:
#Entity
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "name", length = 100, nullable = false)
private String name;
#Column(name = "enabled", nullable = false)
private boolean enabled;
}
I have a CustomerRepository as follows:
public interface CustomerRepository extends CrudRepository<Customer, Integer> {
}
I have a CustomerService as follows:
#Service
public class CustomerService {
#Autowired
CustomerRepository customerRepository;
#Autowired
CustomerMapper customerMapper;
public CustomerDto save(CustomerDto customerDto) {
Customer customer = customerMapper.map(customerDto, Customer.class);
customerRepository.save(customer);
return customerMapper.map(customer, CustomerDto.class);
}
public CustomerDto findById(int id) {
Customer customer = customerRepository.findOne(id);
return customerMapper.map(customer, CustomerDto.class);
}
}
My application is defined as:
#SpringBootApplication
public class CoreApplication {
public static void main(String[] args) {
SpringApplication.run(CoreApplication.class, args);
}
}
My JPA configuration is:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories
public class PersistenceConfig {
}
I have written a test as follows:
#RunWith(SpringRunner.class)
#SpringBootTest
public class ServiceTests {
#Autowired
CustomerService customerService;
#Test
public void testCustomerService() {
CustomerDto customerDtoIn = new CustomerDto();
customerDtoIn.setName("Test Customer");
customerDtoIn.setEnabled(true);
customerService.save(customerDtoIn);
CustomerDto customerDtoOut = customerService.findById(customerDtoIn.getId());
assertThat(customerDtoOut).isEqualTo(customerDtoIn);
}
}
The structure I have followed is:
com.app.core <- CoreApplication lives here
com.app.core.repositories <- Repositories here
com.app.core.services <- Services here
However, when I try to run this test case I get the following:
org.springframework.beans.factory.NoSuchBeanDefinitionException
No qualifying bean of type 'com.app.core.repositories.CustomerRepository' available
Can someone tell me why the dependency injection is failing? From reading the spring-boot docs #SpringBootTest and #RunWith(SpringRunner.class) are all I need to test my service layer.
you have to add base package and repository base package into ApplicationContext.xml. yo can use below code:-
<context:component-scan annotation-config="true"
base-package="com.demo.test" />
<jpa:repositories base-package="com.demo.test.repository" />
I create a new service with spring boot and spring mvc .
UserEntity.class:
#Entity
#Table(name = "users")
public class UserEntity {
private long id;
private String username;
private String password;
private boolean active;
private boolean login;
public UserEntity(UserDto dto) {
this.id = dto.getId();
this.username = dto.getUsername();
this.password = dto.getPassword();
this.active = dto.isActive();
}
// getters&setters...
}
UserDto.class:
public class UserDto {
private long id;
private String username;
private String password;
private boolean active;
public UserDto(long id, String username, String password, boolean active) {
this.id = id;
this.username = username;
this.password = password;
this.active = active;
}
// getters&setters...
}
UserRepository:
#Repository
public interface UserRepository extends JpaRepository<UserEntity, Long> {
}
UserServiceImpl.class: (and UserService Interface)
#Service
#Transactional
public class UserServiceImpl implements UserService {
private final UserRepository repo;
#Autowired
public UserServiceImpl(UserRepository repo) {
this.repo = repo;
}
#Override
public boolean saveUser(UserDto dto) {
UserEntity user = new UserEntity(dto);
repo.save(user);
return true;
}
}
UserController.class:
#RestController
public class UserController {
private final UserService service;
#Autowired
public UserController(UserService service) {
this.service = service;
}
#RequestMapping(value = "/users", method = RequestMethod.POST)
public void createUser(#RequestBody UserDto userDto) {
service.saveUser(userDto);
}
}
Application.class:
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
my Spring Boot project starts correctly. But when I test my service with IntelliJ Test Restful Web Service Tool I encounter an error:
Response:
{"timestamp":1464066878392,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/users"}
What is the problem?
My suggestion would be to remove the constructors from the UserController and UserServiceImpl classes, there's no need for them. Then, assign the #Autowired annotation to the declarations instead. Also, I don't think you need to make them final.
UserServiceImpl.class:
#Service
#Transactional
public class UserServiceImpl implements UserService {
#Autowired
private UserRepository repo;
#Override
public boolean saveUser(UserDto dto) {
UserEntity user = new UserEntity(dto);
repo.save(user);
return true;
}
}
UserController.class:
#RestController
public class UserController {
#Autowired
private UserService service;
public UserController(UserService service) {
this.service = service;
}
#RequestMapping(value = "/users", method = RequestMethod.POST)
public void createUser(#RequestBody UserDto userDto) {
service.saveUser(userDto);
}
}