How to store hateoas structure in elasticsearch - java

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]

Related

How can accept both JSON and XML?

I saw similar question, and added to consumes parameters both MediaType. But it can't help me :(
I want to accept requests in json and xml formats.
There is my controller:
#RequestMapping(value = "/api/client", produces = "application/json;charset=UTF-8",
consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public class ClientController {
#Autowired
private ClientService clientService;
#PostMapping("/create")
public String createClient(#Valid #RequestBody ClientDto clientDto) {
return clientService.createUser(clientDto);
}
}
Dto class:
import javax.validation.constraints.NotNull;
public class ClientDto {
private long client_id;
#NotNull
private String first_name;
#NotNull
private String last_name;
private List<AccountDto> accounts;
getter//setters//constructor//
}
I sending requests from Postman. I haven't problems with json.
But I can't accept xml format.
2021-08-15 20:08:43.600 WARN 15820 --- [nio-8081-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/xml;charset=UTF-8' not supported]
My problem was solved by #XmlRootElement annotation
#XmlRootElement
public class ClientDto {
private long client_id;
private String first_name;
private String last_name;
private List<AccountDto> accounts;
...
}
and
#XmlRootElement
public class AccountDto {
...
}

Elasticsearch config with Repository end up with Exception on Spring Boot

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!

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.

Cannot find why jUnit test return NullPointerException

I have simple Spring boot Rest application what returns Users list from database.
Application works as expected but test scenario fail with error. After long googling cannot figure out why?
It seems that test class cannot access userRepository and instead of calling userRepository.getAllUsers it calls AppController.getAllUsers.
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
……………………………
Caused by: java.lang.NullPointerException
at com.loan.demo.controller.AppController.getAllUsers(AppController.java:43)
…………………………………………..
These are my classes:
LoanAppApplication
#SpringBootApplication
public class LoanAppApplication {
public static void main(String[] args) {
SpringApplication.run(LoanAppApplication.class, args);
}
}
Class User.java
#Entity
#Table(name="USERTABLE")
public class User {
private int id;
#NotNull
private String firstName;
#NotNull
private String lastName;
#NotNull
private String persID;
private int blocked;
private Set<Loan> loans;
public User() {
}
public User(String firstName, String lastName, String persID) {
this.firstName = firstName;
this.lastName = lastName;
this.persID = persID;
}
UserRepository:
#Repository
public interface UserRepository extends JpaRepository<User, Integer>{
public User findById(int Id);
public User findByPersID(String userId);
}
And Rest Controller:
#RestController
public class AppController {
#Autowired
UserRepository userRepository;
#GetMapping("/doit")
public String doIt() {
return "Do It";
}
//list all users
#GetMapping("/users")
public List<User> getAllUsers() {
return userRepository.findAll(); // this is line 43 from debuging error log
}
}
And test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {LoanAppApplication.class})
public class LoanAppApplicationTests {
private MockMvc mockMvc;
#InjectMocks
private AppController appController;
#Before
public void addData() {
mockMvc = MockMvcBuilders.standaloneSetup(appController)
.build();
}
//First test scenario that return only string works perfectly
#Test
public void testData() throws Exception {
mockMvc.perform(get("/doit")
)
.andExpect(status().isOk())
.andExpect(content().string("Do It"));
}
//but second that should return empty json string fails with exception
#Test
public void testGet() throws Exception {
mockMvc.perform(get("/users")
)
.andExpect(status().isOk())
.andExpect(content().string("Do It")); //this test should fail but not return exception
}
}
You need to mock your userRepository
#Mock
UserRepository userRepository;
so after #Mock you need to initialize Mock`s in #Before, add this:
MockitoAnnotations.initMocks(this);
then in code setup what users you want to get
User user = new User();
when(userRepository.getUsers()).thenReturn(Collections.singletonList(user));
and then check
verify(userRepository, times(1)).getUsers();
verifyNoMoreInteractions(userRepository);
this is because you application context is not working

I have an error in testing my simple spring mvc service

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);
}
}

Categories