How to handle nested json with Spring Webflux and Webclient - spring-webflux

I'm trying to consume the moviedb api with spring webclient but i dont know how to handle nested json.
these are my models:
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class MovieDbResponse {
private String page;
private List<Movie> results;
private String total_pages;
private String total_results;
}
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class Movie {
private boolean adult;
private String backdrop_path;
private int[] genre_ids;
private int id;
private String original_language;
private String original_title;
private String overview;
private float popularity;
private String poster_path;
private String release_date;
private String title;
private boolean video;
private float vote_average;
private int vote_count;
}
and this is my webclient:
public class MovieDbClient {
#Value("${moviedb.apiKey}")
private String apiKey;
#Autowired
WebClient webclient;
public Mono<MovieDbResponse> searchMovie(String movieName){
Mono<MovieDbResponse> movieDbResponse = webclient.get()
.uri(uriBuilder -> uriBuilder
.path("/search/movie")
.queryParam("page","1")
.queryParam("query",movieName)
.queryParam("api_key", apiKey)
.queryParam("include_adult","false")
.queryParam("language","en-US")
.build()
)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.retrieve()
.bodyToMono(MovieDbResponse.class);
return movieDbResponse;
}
}
I have the problem that i get my page, total_page and total_results but not the results array

Related

Join the result of several microservice in a Mono

I try to develop a api with spring-cloud-gateway but it's not easy for me
My "microservice A" return an Mono. This Object contains a List of id "Object B"
My "microservice B" return an Flux
In my api-gateway, how can i aggregate in a Mono the result of the microservices ?
#Service
public class ServiceAClient {
private final WebClient webClient;
public ServiceAClient(WebClient.Builder builder) {
this.webClient = builder.baseUrl("lb://microservice-A/A/").build();
}
public Mono<ObjectA> getObjectA(String id){
return webClient
.get()
.uri("{id}" , id)
.retrieve()
.bodyToMono(ObjectA.class)
.onErrorResume(ex->Mono.empty());
}
}
#Service
public class ServiceBClient {
private final WebClient webClient;
public ServiceAClient(WebClient.Builder builder) {
this.webClient = builder.baseUrl("lb://microservice-B/B/").build();
}
public Flux<ObjectB> getListObjectB(List<Long> ids){
return webClient
.get()
.uri("{ids}" , ids)
.retrieve()
.bodyToFlux(ObjectB.class);
}
}
#Data
public class ObjectA {
private UUID id;
private String name;
private String description;
private Date start;
private Date end;
private List<Long> listIdObjectB;
}
#Data
public class ObjectB {
private Long id;
private String name;
private String localisation;
}
#Data
public class MyDto {
private UUID id;
private String name;
private String description;
private Date start;
private Date end;
private List<ObjectB> listObjectB;
}
#Service
#AllArgsConstructor
public class CombinedService {
private final ServiceAClient serviceAClient;
private final ServiceBClient serviceBClient;
public Mono<MyDto> getDetails(String id){
// return MyDto who join a Mono Service A an Flux service B
}
}
The desired result
{
"id": "2355e7eb-edf7-428c-b51b-ac06c146ed3c",
"name": "toto",
"description": "lorem ipsum",
"debut": 01/06/2022,
"fin": 10/06/2022,
"ListObjectB": [
{
"id": 1,
"name": "foo",
"localisation": "here"
},
{
"id": 2,
"name": "bar",
"localisation": "here"
}
]
}
Thank you in advance for your help
You can take it as a start point to understand a possible solution.
I highly recommend you to read about reactive streams(https://www.reactive-streams.org/) and spring-webflux(https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html).
Your CombinedService should looks like:
#Service
#AllArgsConstructor
public class CombinedService {
private final ServiceAClient serviceAClient;
private final ServiceBClient serviceBClient;
public Mono<MyDto> getDetails(String id) {
return serviceAClient.getObjectA(id)
.map(objectA -> {
final Flux<ObjectB> fluxB = serviceBClient.getListObjectB(objectA.getListIdObjectB());
final List<ObjectB> listObjectB = fluxB.toStream().collect(Collectors.toList());
final MyDto myDto = new MyDto();
myDto.setName(objectA.getDescription());
myDto.setDescription(objectA.getDescription());
myDto.setListObjectB(listObjectB);
//More setters, etc
return myDto;
});
}
}

No property 'birthDate' found for type 'person'! Did you mean ''birthdate''? in srping boot

I am developing and rest api and i want to filter a data by birthday. I create birthday variable as birthday in every where and when i compile my code i get an error that " No property 'birthDate' found for type 'person'! Did you mean ''birthdate''?". But i haven't make a variable as birthDate
entity
public class person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY )
private long id;
#Column(name="Name")
private String name ;
#Column(name="surname")
private String surname;
#Column(name="Birthdate")
#JsonFormat(pattern = "yyyy-MM-dd")
private Date birthdate;
#OneToMany(targetEntity = address.class, cascade = CascadeType.ALL)
#JoinColumn(name ="per_id", referencedColumnName = "id")
private List<address> address = new ArrayList<>();
}
repository
public interface personRepository extends JpaRepository<person,Long> {
public List<person> findByName(String Name);
public List<person> findByBirthDate(Date birthdate);
}
controller
#GetMapping()
public List filterall(#RequestParam(required = false) String name, #RequestParam(required = false) Date birthdate){
//return null;
var personsByName = repository.findByName(name);
var personsByBday= repository.findByBirthDate(birthdate);
return personsByBday;
}
error!

Spring-data-solr config

i met a problem in Studying with Spring data solr,this is my Configuration Class:
#Configuration
#EnableSolrRepositories(basePackages={"cn.likefund.solr.repository"}, multicoreSupport=true)
public class SolrContext {
static final String SOLR_HOST = "http://192.168.11.157:8080/solr";
#Bean
public SolrClient solrClient() {
return new HttpSolrClient(SOLR_HOST);
}
}
and this is my Repository:
package cn.likefund.solr.repository;
import java.util.List;
import org.springframework.data.solr.repository.SolrCrudRepository;
import cn.likefund.solr.model.Activity;
public interface ActivityRepository extends SolrCrudRepository<Activity, String>{
List<Activity> findByName(String name);
}
when I start the application,the message in console is this
error
When I delete the method findByName in the repository,the application start with no problem, i just want to the method findByName worked,anybody know what should i do with this problem?
here is the Activity Class:
#Entity
#SolrDocument(solrCoreName ="core_activity")
public class Activity implements Serializable{
private static final long serialVersionUID = 1566434582540525979L;
#Id
#Field(value = "id")
private String id;
#Field(value = "CREATEDT")
private String createdt;
#Indexed
#Field(value = "NAME")
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCreatedt() {
return createdt;
}
public void setCreatedt(String createdt) {
this.createdt = createdt;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
So, obviously the CrudRepository is not created .
when you delete the findByName, can you manually query your repo ? (just to be sure the problem comes from the method, and not the SOLR schema)
have you tried to annotate annotate the method to explicitly set the query ? Something like
#Query("NAME:?0")
List findByName(String name);

Jackson: Serialize only 10 Properties out of 100

Jackson by default includes all public getters. But if I have hundreds of getters and I want to serialize just few of them, how can I achieve this?
I don't want to use #JsonIgnore annotation to specify all others hundred properties.
You can use Jackson's views or filters to select the serialization form of your object. Here is an example using the filter which picks up the properties with the given names:
public class JacksonFilter {
#JsonFilter("filter")
public static class Bean {
private final String field1;
private final String field12;
private final String field10;
private final String field100;
public Bean(String field1, String field12, String field10, String field100) {
this.field1 = field1;
this.field12 = field12;
this.field10 = field10;
this.field100 = field100;
}
public String getField1() {
return field1;
}
public String getField12() {
return field12;
}
public String getField10() {
return field10;
}
public String getField100() {
return field100;
}
}
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
SimpleFilterProvider filters = new SimpleFilterProvider();
filters.addFilter("filter",
SimpleBeanPropertyFilter.serializeAllExcept("field12", "field100"));
mapper.setFilters(filters);
Bean bean = new Bean("A", "B", "C", "D");
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(bean));
}
}
Output:
{
"field1" : "A",
"field10" : "C"
}

Apache Wicket: Attempted to set property value on a null object. Property expression: metaCarrier Value: SearchFormSelectOption [key=367, value=KPN]

I am trying with following code.
I am getting error
Attempted to set property value on a null object. Property expression: metaCarrier Value: SearchFormSelectOption [key=367, value=KPN]
on Ajax call
any idea what might be wrong?,
code is as follows
final DropDownChoice<SearchFormSelectOption> metaCarrier = new DropDownChoice<SearchFormSelectOption>("metaCarrier", carrierChoices, new ChoiceRenderer<SearchFormSelectOption>("value")
{
#Override
public Object getDisplayValue(SearchFormSelectOption option)
{
LOG.error("check display object ....." + option.getValue());
return option.getValue();
}
#Override
public String getIdValue(SearchFormSelectOption option, int index)
{
return option.getKey();
}
});
metaCarrier.setNullValid(true);
metaCarrier.setOutputMarkupId(true);
ruleCreationListView.add(metaCarrier);
metaCarrier.add(new AjaxFormComponentUpdatingBehavior("onchange")
{
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate(AjaxRequestTarget target)
{
LOG.info("Carrier===============" + (getModelObject()).getMetaComSelectCarrier());
}});
public class SearchFormSelectOption implements Serializable
{
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;
/** The key. */
private String key;
/** The value. */
private String value;
//getter and setters
Please have a look at below sample code directly from Customizing the display of choices. Find more samples here.
public class SelectOption {
private String key;
private String value;
public SelectOption(String key, String value) {
this.key = key;
this.value = value;
}
//...[getters and setters]...
}
//create an instance of DropDownChoice with appropriate ChoiceRenderer.
SelectOption[] options = new SelectOption[] { new SelectOption("&", "AND"),
new SelectOption("|", "OR") };
ChoiceRenderer choiceRenderer = new ChoiceRenderer("value", "key");
DropDownChoice dropDownChoice = new DropDownChoice("connective", model, Arrays.asList(options), choiceRenderer);