When upgrading from Drupal 8.1 to Drupal 8.2, the acquia_contenthub module breaks and is no longer able to output JSON via the altered route we wrote in Drupal 8.1. We're aware that Drupal 8.2 introduces the REST resource config entities, but our understanding is that even if older APIs get deprecated at some point in the life span of Drupal 8, they won't be removed until Drupal 9, and in other words, any code written for Drupal 8.1 should also work for Drupal 8.2. Is this a wrong assumption?

Steps to reproduce:
- Install the acquia_contenthub module on Drupal 8.2 (subscriber module is not required)
- Configure the module to export nodes of type "Article" at admin/config/services/acquia-contenthub/configuration by checking the "Publish" checkbox
- Create an Article node
- Browse to node/1?_format=acquia_contenthub_cdf

Here is the error we're seeing (full):

Error: Call to a member function getResourcePlugin() on null in Drupal\rest\RequestHandler->handle() (line 82 of /Users/stephane.corlosquet/Sites/devdesktop/d82chqa-b2-master/core/modules/rest/src/RequestHandler.php) 

and this warning (full):

Warning: array_flip(): Can only flip STRING and INTEGER values! in Drupal\Core\Entity\EntityStorageBase->loadMultiple() (line 227 of /Users/stephane.corlosquet/Sites/devdesktop/d82chqa-b2-master/core/lib/Drupal/Core/Entity/EntityStorageBase.php)

The route alter code is here, is there something we're doing wrong?

CommentFileSizeAuthor
#2 2820096-error.2.txt6.62 KBscor
#2 2820096-error.1.txt3.79 KBscor
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

scor created an issue. See original summary.

scor’s picture

Issue summary: View changes
FileSize
3.79 KB
6.62 KB
scor’s picture

Issue summary: View changes
saltednut’s picture

Why get cute with routes and misuse _format ?

You could have delivered the json on a url with your own controller like /content-hub/{entity}/{id}

I don't know if I would blame the API changing if I was misusing it to begin with.

I'd consider rewriting the solution to unblock the issue rather than point the finger at core.

Wim Leers’s picture

Status: Active » Fixed

Why get cute with routes and misuse _format ?

They're not misusing _format. They just want to expose this additional custom format. See https://www.drupal.org/docs/8/api/serialization-api/serialization-api-ov....

This makes sense: rather than defining new routes, new controllers, and so on, they just want to reuse the existing REST resource for nodes and have it support one additional format.

This is poor architecture, don't blame the API changing for your misuse.

This much is true, the complexity of this code is incredible. It's merely trying to be selective about which routes it alters: only GET routes that use this specific format. The code is terribly convoluted, poorly maintainable. And that is poor architecture indeed.

The utter lack of documentation is also astonishing. It still has the exact same documentation as \Drupal\rest\Routing\ResourceRoutes, where this was clearly copied from!


The error in 2820096-error-1.txt is not an error in your code, it is happening in core's \Drupal\rest\RequestHandler::handle(). The line that is throwing the error was last modified in #2308745: Remove rest.settings.yml, use rest_resource config entities. Only internal controller details were modified there.

I honestly don't understand how this code could even cause the error that it clearly is causing. I think some other code must also be interacting with it in some other way.

Before
    $plugin = $route_match->getRouteObject()->getDefault('_plugin');
    $method = strtolower($request->getMethod());

    $resource = $this->container
      ->get('plugin.manager.rest')
      ->createInstance($plugin);
After
    $resource_config_id = $route_match->getRouteObject()->getDefault('_rest_resource_config');
    /** @var \Drupal\rest\RestResourceConfigInterface $resource_config */
    $resource_config = $this->resourceStorage->load($resource_config_id);
    $resource = $resource_config->getResourcePlugin();

Note that it used to read _plugin from the route object, now it reads _rest_resource_config. That must be where the problem lies: some other code must be modifying the route defaults.

scor’s picture

thanks Wim and Brant! To be clear, sorry if my wording made it sound like I was blaming core, but I wasn't. I suspected it had to do with something wrong in our code, that's why I filed it as support request, and not a bug report. Thanks for you help!

Wim Leers’s picture

No worries :)

Going forward, I strongly encourage you to add defensive tests when you're altering certain things. And honestly, even the most basic integration tests would have caught this. But since https://www.drupal.org/node/2759027/qa indicates the acquia_contenthub is not running automated tests, this went unnoticed. (It automatically runs against Drupal 8 "HEAD", which was 8.2.x, and now is 8.3.x..)

Wim Leers’s picture

Oh, and more importantly: did you manage to fix it already?

scor’s picture

Issue summary: View changes

I forgot an important step in the STRs :(

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.