The obj
variable is null because you have not expanded the reference. Unless you explicitly request it, all references will be empty to improve performance. In order to expand it, you can use this code:
// Query products
final ProductProjectionQuery query = ProductProjectionQuery.ofCurrent()
.withExpansionPaths(product -> product.categories()) // Request to expand categories
.withLimit(450);
final List<ProductProjection> products = client.execute(query).toCompletableFuture().join().getResults();
for (ProductProjection product : products) {
final List<LocalizedString> categoryLocalizedNames = product.getCategories().stream()
.map(categoryRef -> categoryRef.getObj().getName())
.collect(toList());
// Do something with categoryLocalizedNames
}
But I strongly recommend you to cache the categories in a CategoryTree
instance and grab the name from it, because otherwise the performance will be quite affected by expanding all categories of each product. Here is the code:
// Query all categories and put them in a CategoryTree
final CategoryQuery queryAllCategories = CategoryQuery.of().withLimit(500);
final List<Category> allCategories = client.execute(queryAllCategories).toCompletableFuture().join().getResults();
final CategoryTree categoryTree = CategoryTree.of(allCategories);
// Query products
final ProductProjectionQuery query = ProductProjectionQuery.ofCurrent().withLimit(500);
final List<ProductProjection> products = client.execute(query).toCompletableFuture().join().getResults();
for (ProductProjection product : products) {
final List<LocalizedString> categoryLocalizedNames = new ArrayList<>();
product.getCategories().forEach(categoryRef -> {
final Optional<Category> categoryOpt = categoryTree.findById(categoryRef.getId());
if (categoryOpt.isPresent()) {
categoryLocalizedNames.add(categoryOpt.get().getName());
}
});
// Do something with categoryLocalizedNames
}
Of course that means you also have to find a solution to invalidate the cached categories when they change.