Java code stops running during page request

Hi all,

I have made a java component that’s used to feed models to the request.
I added dummy data to show a list of products on de page which worked nicely.

But now I’ve added a request to CommerceTools to get an access token, which I succesfully retrieve.
And afterwards I try to do a second request to CommerceTools to do a product search.
But the page is shown while de code isn’t even done, it even seems as if the request isn’t made.
It stops while calling the function that makes the request. And I don’t see the logs in that function.

It’s difficult to explain, so here is a snippet of my doBeforeRender method.

@Override
public void doBeforeRender(final HstRequest request, final HstResponse response) {
    System.out.println("ProductListComponent.doBeforeRender()");
    super.doBeforeRender(request, response);
    final HstRequestContext ctx = request.getRequestContext();
    final EssentialsListComponentInfo paramInfo = getComponentParametersInfo(request);

    // Get the requested products.
    System.out.println("doSearch");
    ProductDto[] products = this.doSearch(request);
    System.out.println("doSearchForPageable");
    ProductDocument[] productsForPageable = this.doSearchForPageable();
    System.out.println("ProductIterator: " + productsForPageable.length);
    ProductIterator productIterator = new ProductIterator(productsForPageable);

And here is the doSearch method.

protected ProductDto[] doSearch(HstRequest request) {
    String keyword = getPublicRequestParameter(request, "keyword");
    String limit = getPublicRequestParameter(request, "limit");
    if (keyword == null || keyword.length() == 0) {
        return null;
    }

    CommerceToolsApiService commerceToolsApiService = new io.commercetools.CommerceToolsApiService(
            "https://api.europe-west1.gcp.commercetools.com/", "https://auth.europe-west1.gcp.commercetools.com/",
            "xxx", "xxx", "xxx");
    String accessToken;
    try {
        accessToken = commerceToolsApiService.GetAccessToken("view_products");
        System.out.println("Access Token: "+accessToken);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        // e.printStackTrace();
        System.out.println(e.getMessage());
        return null;
    }

    System.out.println("Done getting access token.");

    Search search = new Search();
    System.out.println("1");
    search.SearchTerm = keyword;
    System.out.println("2");
    search.Limit = 10;// limit != null && limit != "" ? 10 : Integer.parseInt(limit);
    System.out.println("3");
    search.CategoryId = null;

    System.out.println("Created search object. " + search.SearchTerm + " - " + search.Limit);

    PagedQueryResult productResponse;
    try {
        System.out.println("Start search: " + search);
        productResponse = commerceToolsApiService.GetProductsBySearchTerms(accessToken, search);
        System.out.println(productResponse.Count);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        // e.printStackTrace();
        System.out.println(e.getMessage());
        return null;
    }

    System.out.println("Done getting products by search term.");

I see the logs “Done getting access token” and the 1, 2, 3 all the way to the “Start Search…”.
But no logs after that. Does someone have a suggestion why this would happen?

Thanks in advance.

Is this an async hst component? Is GetProductBySearchTerms a synchronous call?

No I haven’t made it async.
Normally I work in C#, so I’m not familiar with async in Java.

Would that even work with an HstRequest? Because I need to use the request.addModel() to add the retrieved products.

I mean, if you create a thread in which you make the request but don’t wait until it’s done then it could be that you don’t see an output. How does that part of the code look like?

I don’t exactly know which part you’re referring to.
But in the snippet below, I never get the log “GetPageableFactory” for example.
It only runs until the doSearch() method.

@Override
public void doBeforeRender(final HstRequest request, final HstResponse response) {
    System.out.println("ProductListComponent.doBeforeRender()");
    super.doBeforeRender(request, response);
    final HstRequestContext ctx = request.getRequestContext();
    final EssentialsListComponentInfo paramInfo = getComponentParametersInfo(request);

    // Get the requested products.
    System.out.println("doSearch");
    ProductDto[] products = this.doSearch(request);
    System.out.println("doSearchForPageable");
    ProductDocument[] productsForPageable = this.doSearchForPageable();
    System.out.println("ProductIterator: " + productsForPageable.length);
    ProductIterator productIterator = new ProductIterator(productsForPageable);

    // Create the pageable model.
    final int pageSize = getPageSize(request, paramInfo);
    final int page = getCurrentPage(request);
    System.out.println("GetPageableFactory");
    final PageableFactory pageableFactory = getPageableFactory();
    System.out.println("CreatePageable");
    Pageable<ProductDocument> pageable = pageableFactory.createPageable(productIterator,
            (int) productIterator.getSize(), pageSize, page);

And for the record to prevent confusion. I haven’t added anything like a thread yet.

Sorry, I meant this piece of code. How does the implementation look like? Also, can you confirm there are no other exceptions thrown? Can you change IOException to Exception ? But I suppose such an exception would be logged…

Indeed I would expect a log.

This is the in the service class that gets called:

public PagedQueryResult GetProductsBySearchTerms(String accessToken, Search search) throws IOException {
    System.out.println("CommerceToolsApiService.GetProductsBySearchTerms()");
    return this.serviceAgent.GetProductsBySearchTerms(accessToken, search);
}

Which in turn calls:

public PagedQueryResult GetProductsBySearchTerms(String accessToken, Search search) throws IOException {
    System.out.println("CommerceToolsServiceAgent.GetProductsBySearchTerms()");
    String clause = "text.nl=" + search.SearchTerm + "&published=false" + "&limit=" + search.Limit
            + (search.CategoryId > 0 ? "&filter=categories.id:" + search.CategoryId + "\"" : "");
    System.out.println("GetProductsBySearchTerms() " + clause);
    String encodedClause = this.SuperEncodeURI(clause);        
    String requestUrl = this.baseAddress + this.projectKey + "/product-projections/search?" + encodedClause;
    System.out.println("GetProductsBySearchTerms: "+requestUrl);
    
    return this.GetAsync(PagedQueryResult.class, requestUrl, accessToken);
}

And the GetAsync:

private <T> T GetAsync(Class<T> t, String requestUri, String accessToken) throws IOException {
    URL url = new URL(requestUri);
    HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
    try {            
        urlConnection.setRequestMethod("GET");
        urlConnection.setRequestProperty("Content-Type", "application/json");
        urlConnection.addRequestProperty("Authorization", "Bearer "+ accessToken);

        int status = urlConnection.getResponseCode();

        if (status != 200) {
            System.out.println(status);
        }
        
        BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
        StringBuffer content = new StringBuffer();
        try {                
            String inputLine;                
            while ((inputLine = in.readLine()) != null) {
                content.append(inputLine);
            }
        }
        finally {
            in.close();
        }

        System.out.println(content);
        System.out.println(content.toString());

        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
        T value = mapper.readValue(content.toString(), t);

        return value;
    }
    finally {
        urlConnection.disconnect();
    }
}

The GetAsync is not perfect yet. But I should at least see some of the many logs I’m throwing around.
The GetAsnyc is also used for the access token, which works fine.

Hmm nothing that stands out. How about with a debugger? Can you not step into getAsync?

I managed to fix it. I added the whole doSearch() in the doBeforeRender() in a thread.
Which managed to show the exception in the logger. Which was a NullPointerException.

This was in the GetProductsBySearchTerms() at the line with "String clause = ", it couldn’t use the CategoryId correctly. So after I fixed that I could continue.

A lot of other fixes later the product search now works and is retrieved correctly.

Thanks for the help!

1 Like