crnk-framework icon indicating copy to clipboard operation
crnk-framework copied to clipboard

Convert an entity object to document, in the document filter

Open goldyliang opened this issue 4 years ago • 3 comments

I have a need to convert an entity object to a Document object so it can be returned to user directly, but can not find out the obvious way.

The code I am targeting is like below:

@Component
public class MyDocumentFilter implements DocumentFilter {
 ...
 ...
  @Override
  public Response filter(DocumentFilterContext filterRequestContext, DocumentFilterChain chain) {
       ...
      if (filterRequestContext.getMethod().equals("POST") && 
         // other conditions ) {
       ...
            // MyService.handleRequest is legacy code, which I don't want to re-factor it to fit the way 
           // how DocumentFilter works.
           // The method is called as it was, returning a persisted entity object.
           MyEntity entity = MyService.handleRequest(...);

          // How can I convert entity to a document, so it can be returned as a result?
          //  Document document = Some_Convert_Method (entity);
          //  return new Response(document, HttpStatus.OK.value());
      }
  }
}

The only way I can find (which is ugly), is like below:

    ResourceGetController controller  = crnkBoot
                    .getControllerRegistry()
                    .getControllers()
                    .stream()
                    .filter(c -> c instanceof ResourceGetController)
                    .findFirst()
                    .get();

   JsonPath path =
            new ResourcePath(
                filterRequestContext.getJsonPath().getRootEntry(),
                Arrays.asList(element.getUuid()));

   QuerySpec querySpec = new QuerySpec(MyEntity.class, "type-name");
   QueryAdapter adapter =
            new QuerySpecAdapter(
                querySpec,
                filterRequestContext.getQueryAdapter().getResourceRegistry(),
                filterRequestContext.getQueryAdapter().getQueryContext());

  return controller.handleAsync(artifactPath, adapter, null);

goldyliang avatar Feb 13 '20 07:02 goldyliang

You can get an instance of DocumentMapper (which behind the scenes makes use of ResourceMapper from CrnkBoot/ModuleRegistry. This gives a Document object that can easily be translated to JSON with Jackson.

remmeier avatar Feb 17 '20 06:02 remmeier

Thanks @remmeier . So following your suggestion, my code would be something like below.

I verified that it works fine.

        DocumentMapper mapper = crnkBoot.getDocumentMapper();

        QuerySpec querySpec = new QuerySpec(MyEntity.class, "type-name");
        QueryAdapter adapter =
                new QuerySpecAdapter(
                        querySpec,
                        filterRequestContext.getQueryAdapter().getResourceRegistry(),
                        filterRequestContext.getQueryAdapter().getQueryContext());

        Document result = mapper.toDocument( new JsonApiResponse() {{
          setEntity(entity);
                           }}, adapter, crnkBoot.getModuleRegistry().getDocumentMappingConfig()).get();

        return new Response(result, HttpStatus.CREATED.value());

goldyliang avatar Feb 18 '20 14:02 goldyliang

But the next question is, what is the correct way to get CrnkBoot instance? I tried auto-wired it in the document filter, but the application does not start, seems like due to some initialization order issue.

Now I had to create a component to extend CrnkBootConfigurer so as to get the instance and remember it.

goldyliang avatar Feb 18 '20 14:02 goldyliang