0

I want to create a service in order to populate dropdown from database. I tried this:

Merchant Class:

export class Merchant {
  constructor(
    public id: string,
    public name: string,
    public state_raw: string,
    public users: string,
  ) {}
}

Merchant Service:

 getList(): Observable<Merchant> {
    return this.http.get<Merchant>(environment.api.urls.merchants.base, {});
  }

SQL query:

@Override
    public Iterable<Merchants> findAll() {
        String hql = "select e from " + Merchants.class.getName() + " e";
        TypedQuery<Merchants> query = entityManager.createQuery(hql, Merchants.class);
        List<Merchants> merchants = query.getResultList();
        return merchants;
    }

Working example:

    @GetMapping("/list")
public Iterable<Merchants> getMerchantsList() {
    return merchantRepository
            .findAll();
}

I tried this:

@GetMapping("/list")
public ResponseEntity<?> getMerchantsList() {
    return StreamSupport.stream(merchantRepository.findAll().spliterator(), false)
            .map(mapper::toDTO)
            .map(ResponseEntity::ok)
            .findFirst()
            .orElseGet(() -> notFound().build());
}

I want to use mapper before I send the response. Currently the list in Angular is empty. Probably I should return Iterable<Merchants> not ResponseEntity<MerchantDTO>?

I use Java 10.

4
  • Your rest serice return an Iterable of merchants. Your angular service returns an Observable emitting a single merchant. That doesn't match. You need an array to populate a dropdon, don't you? Commented Nov 3, 2018 at 9:43
  • Yes, How I can implement this? Commented Nov 3, 2018 at 9:44
  • Well, by changing the type to Array<Merchant>. Also, why does your getMerchantsList() method return void instead of... a merchants list? Why does it use findFirst()? You want to return all the merchants, not just the first one. You want collect(Collectors.toList()), not findFirst().orElseGet(). And you want to return that list, not ignore it. Commented Nov 3, 2018 at 9:46
  • My mistake. Sorry. Post is updated. Commented Nov 3, 2018 at 9:51

1 Answer 1

2

There are several problems, on both sides. Let's start by the server-side. You want to return a list of merchants to populate a dropdown list, so you correctly named your method getMerchantsList(). But instead of returning a list as its name indicates, it returns void. void is nothing, nada, hence the empty response.

So you need to return a List<Merchant>, or, if you really want to (but it's unnecessary here since you don't want to set anything other than the response body), a ResponseEntity<List<Merchant>>. Calling findFirst() is counter-productive. You don't want the first merchant of the list. You want the whole list:

@GetMapping("/list")
public List<MerchantDTO> getMerchantsList() {
    return StreamSupport.stream(merchantRepository.findAll().spliterator(), false)
            .map(mapper::toDTO)
            .collect(Collectors.toList());
}

or

@GetMapping("/list")
public ResponseEntity<List<MerchantDTO>> getMerchantsList() {
    List<MerchantDTO> list = StreamSupport.stream(merchantRepository.findAll().spliterator(), false)
            .map(mapper::toDTO)
            .collect(Collectors.toList());
    return ResponseEntity.ok(list);
}

Note that the code would be simpler if your findAll() method returned a List instead of an Iterable. You could just use findAll().stream() to get a stream.

At the client-side, you're doing the same mistake. You want the response body to be an array of merchants, to populate the dropdown list. But you're using an Observable<Merchant>. You need an Observable<Array<Merchant>>. And passing an empty options object to get() is useless:

getList(): Observable<Array<Merchant>> {
  return this.http.get<Array<Merchant>>(environment.api.urls.merchants.base);
}

Finally, you're lying to yourself by creating a class. HttpClient will never create an instance of your class. It doesn't know about it, and simply parsed the JSON it receives to plain old JavaScript objects. So you should really define an interface, not a class:

export interface Merchant {
  id: string;
  name: string;
  state_raw: string;
  users: string;
}

You should really use Spring-data-jpa, too. It would simplify your repositories a lot.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.