Elasticsearch config with Repository end up with Exception on Spring Boot - java

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!

Related

How to store hateoas structure in elasticsearch

I have the following problem that I need to save a Hateos structure in Elasticsearch using the save method in the Springboot application, but I get the error message "stackoverflowerror null": Could some body please check my code to see where I am making mistakes ? It really took me a long time to demonstrate this example.
Config.java
#Configuration
#EnableElasticsearchRepositories(basePackages = "com.example.demo.elsticsearch")
public class Config {
#Bean
public RestHighLevelClient client() {
ClientConfiguration clientConfiguration
= ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
#Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchRestTemplate(client());
}
}
UserResourceAssembler.java
#Service
public class UserResourseAssembler extends RepresentationModelAssemblerSupport<User, UserResourse> {
public UserResourseAssembler() {
super(JsController.class, UserResourse.class);
}
#Override
public UserResourse toModel(User user) {
UserResourse resource = UserResourse.builder().email("jjj").firstName("hii").lastName("hoo").loginId("123").build();
resource.add(linkTo(methodOn(JsController.class).getByLoginId(user.getLoginId())).withRel("self"));
return resource;
}
}
Repo.java
#Repository
public interface Repo extends ElasticsearchRepository<UserResourse, String> {
List<UserResourse> findByLoginId(String loginId);
}
User.java
#Data
#NoArgsConstructor
#AllArgsConstructor
public class User {
private String loginId;
private String firstName;
private String lastName;
private String email;
}
UserResourse.java
#Mapping(mappingPath = "/files.json")
#Document(indexName = "files", type = "file")
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class UserResourse extends RepresentationModel<UserResourse> {
#Id
private String loginId;
private String firstName;
private String lastName;
private String email;
}
JsController.java
#RestController
#RequestMapping("/user")
#AllArgsConstructor
public class JsController {
private final Repo repository;
private final UserResourseAssembler userResourseAssembler;
#GetMapping("/check")
public ResponseEntity<UserResourse> uploadData() {
User user = new User(UUID.randomUUID().toString(), "hi", "hello", "jj");
UserResourse userResourse = userResourseAssembler.toModel(user);
repository.save(userResourse);
return new ResponseEntity<>(userResourse, HttpStatus.OK);
}
#GetMapping("/jobId")
public List<UserResourse> getByLoginId(#PathVariable String loginId) {
return repository.findByLoginId(loginId);
}
}
I am getting the following error:
2020-09-18 10:02:35.939 ERROR 16184 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.elasticsearch.ElasticsearchException: Cannot render document to JSON] with root cause
java.lang.StackOverflowError: null
at java.base/java.lang.ClassLoader.defineClass1(Native Method) ~[na:na]

Posting data in a Spring Boot 2 Application with Spring Data JPA

I am trying to post data from postman via my Spring Boot 2 Application with Spring Data JPA into a MySQL Database. All I get is a 404 Error.
Main
#SpringBootApplication
public class ProfileApplication {
public static void main(String[] args) {
SpringApplication.run(ProfileApplication.class, args);
}
}
Entity
#Entity
public #Data class Profile {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String profileText;
}
Controller
#RestController
#RequestMapping(value = "/profile", produces = { MediaType.APPLICATION_JSON_VALUE })
public class ProfileController {
#Autowired
private ProfileRepository profileRepository;
public ProfileRepository getRepository() {
return profileRepository;
}
#GetMapping("/profile/{id}")
Profile getProfileById(#PathVariable Long id) {
return profileRepository.findById(id).get();
}
#PostMapping("/profile")
Profile createOrSaveProfile(#RequestBody Profile newProfile) {
return profileRepository.save(newProfile);
}
}
Repository
public interface ProfileRepository extends CrudRepository<Profile, Long> {
}
application.propterties
server.port = 8080
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/profiledb
spring.datasource.username=root
spring.datasource.password=
server.servlet.context-path=/service
It seems that in your ProfileController, you have defined twice the profile endpoint (first at the class level, and second on the methods). The solution would be to remove one of them:
#RestController
#RequestMapping(value = "/profile", produces = { MediaType.APPLICATION_JSON_VALUE })
public class ProfileController {
#Autowired
private ProfileRepository profileRepository;
public ProfileRepository getRepository() {
return profileRepository;
}
// Notice that I've removed the 'profile' from here. It's enough to have it at class level
#GetMapping("/{id}")
Profile getProfileById(#PathVariable Long id) {
return profileRepository.findById(id).get();
}
// Notice that I've removed the 'profile' from here. It's enough to have it at class level
#PostMapping
Profile createOrSaveProfile(#RequestBody Profile newProfile) {
return profileRepository.save(newProfile);
}
}
Which url? Valid url must look like:
GET: http://localhost:8080/service/profile/profile/1
POST: http://localhost:8080/service/profile/profile

How to update the data in Spring Boot MVC

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 {

how to import data from H2 database to elasticsearch?

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.

Dependency injection fails with #SpringBootTest

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" />

Categories