Getting this when enabling and on just about every page request.

Using core 8.7.5, JSON:API Extras 3.8

Warning: call_user_func_array() expects parameter 1 to be a valid callback, class 'Drupal\jsonapi_cross_bundles\ResourceType\CrossBundleResourceTypeRepository' does not have a method 'setConfigFactory' in Drupal\Component\DependencyInjection\Container->createService() (line 329 of core/lib/Drupal/Component/DependencyInjection/Container.php).

Once that is resolved, two more follow:

 [warning] call_user_func_array() expects parameter 1 to be a valid callback, class 'Drupal\jsonapi_cross_bundles\ResourceType\CrossBundleResourceTypeRepository' does not have a method 'setEnhancerManager' Container.php:329
[warning] call_user_func_array() expects parameter 1 to be a valid callback, class 'Drupal\jsonapi_cross_bundles\ResourceType\CrossBundleResourceTypeRepository' does not have a method 'setEntityRepository' Container.php:329

Also, when viewing the JSON:API extras resources page at admin/config/services/jsonapi/resource_types:

TypeError: Argument 3 passed to Drupal\jsonapi_extras\JsonapiResourceConfigListBuilder::__construct() must be an instance of Drupal\jsonapi_extras\ResourceType\ConfigurableResourceTypeRepository, instance of Drupal\jsonapi_cross_bundles\ResourceType\CrossBundleResourceTypeRepository given, called in /var/www/docroot/modules/contrib/jsonapi_extras/src/JsonapiResourceConfigListBuilder.php on line 59 in Drupal\jsonapi_extras\JsonapiResourceConfigListBuilder->__construct() (line 45 of modules/contrib/jsonapi_extras/src/JsonapiResourceConfigListBuilder.php).
Drupal\jsonapi_extras\JsonapiResourceConfigListBuilder->__construct(Object, Object, Object, Object) (Line: 59)
Drupal\jsonapi_extras\JsonapiResourceConfigListBuilder::createInstance(Object, Object) (Line: 288)
Drupal\Core\Entity\EntityTypeManager->createHandlerInstance('Drupal\jsonapi_extras\JsonapiResourceConfigListBuilder', Object) (Line: 277)
Drupal\Core\Entity\EntityTypeManager->getHandler('jsonapi_resource_config', 'list_builder') (Line: 215)
Drupal\Core\Entity\EntityTypeManager->getListBuilder('jsonapi_resource_config') (Line: 23)
Drupal\Core\Entity\Controller\EntityListController->listing('jsonapi_resource_config')
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 582)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 151)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 693)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mstef created an issue. See original summary.

mstef’s picture

Issue summary: View changes
mstef’s picture

Issue summary: View changes
mstef’s picture

Resolving that runs in to:

[warning] call_user_func_array() expects parameter 1 to be a valid callback, class 'Drupal\jsonapi_cross_bundles\ResourceType\CrossBundleResourceTypeRepository' does not have a method 'setEnhancerManager' Container.php:329

And then:

[warning] call_user_func_array() expects parameter 1 to be a valid callback, class 'Drupal\jsonapi_cross_bundles\ResourceType\CrossBundleResourceTypeRepository' does not have a method 'setEntityRepository' Container.php:329

mstef’s picture

Status: Active » Needs review
StatusFileSize
new1.85 KB

This adds those missing 3 functions.

mstef’s picture

Status: Needs review » Needs work

My mistake - this is only required if JSON:API Extras is enabled..

mstef’s picture

Title: CrossBundleResourceTypeRepository does not have a method 'setConfigFactory' » Incompatible with JSON:API Extras
Issue summary: View changes
mstef’s picture

I didn't realize that both modules override the jsonapi.resource_type.repository service; each in different ways. I'm not sure what the proper path forward here is..

wim leers’s picture

@mstef #3068811: Follow-up for #3004582: make ConfigurableResourceTypeRepository a decorator already landed in JSON:API Extras. It just hasn't shipped in a new release yet. You could pin that particular commit until a new release is out.

mstef’s picture

Thanks but the only thing that does is stop the errors. The problem is that none of the cross bundle resources are available now.

dorficus’s picture

I can reproduce this issue with the most current version of JSON:API Extras. I've tried to get around it by adding decoration_priority to both modules' services.yml file and I still don't have access to the cross bundle resources. Tried with the patch in #5 and still no success.

dorficus’s picture

However, if I put the decoration priority of this module lower than JSON:API Extras, I get a new error from the original post.

The website encountered an unexpected error. Please try again later.
Error: Call to undefined method Drupal\jsonapi\ResourceType\ResourceType::getFieldEnhancer() in Drupal\jsonapi_extras\Normalizer\FieldItemNormalizer->normalize() (line 55 of modules/contrib/jsonapi_extras/src/Normalizer/FieldItemNormalizer.php).
weri’s picture

Status: Postponed » Active

I've installed jsonapi_extras 3.13 and jsonapi_cross_bundles 1.0-alpha2 on Drupal 8.8.1.

But I don't see any routes for the cross bundles entities. When I uninstall jsonapi_extras I can see it as expected.

I think this is related to the service configuration and the decorates for jsonapi.resource_type.repository, that overwrite each other. Like dorficus tried, the decorator priority does not help to solve the problem, because jsonapi_extras uses his extended implementation of the ConfigurableResourceTypeRepository.

Currently I don't know if the problem can be solved easily and I hope that someone can give a hint, how to solve it.

satiricon’s picture

Same problem here. When jsonapi_extras is enabled jsonapi_cross_bundles just doesn't work. When trying /jsonapi/node drupal just returns a 404.

I'll disable jsonapi_extras but it would be nice to have them both.

Thanks for your work!

paul121’s picture

StatusFileSize
new7.11 KB

I think I've made some progress to get this working with jsonapi_extras.

Rather than decorating the jsonapi.resource_type.repository service with an entire new class, I've decorated the service with a class that extends ConfigurableResourceTypeRepository (similar to how jsonapi_extras does this) with a priority of -1 so that it is applied before other decorators.

An important distinction: unlike jsonapi_extras, we still need to include the inner argument and use this to call methods of the parent class rather than parent::method(). I believe this is because the inner->method() will take into account other modules' service decorators, where as calling the parent method directly does not. (Without using inner, I get an error related to jsonapi_extras when visiting a page such as /jsonapi/node.)

This article was helpful in figuring how some of the differences with decorators and the inner service: https://www.phase2technology.com/blog/using-symfony-service This quote made me think that specifically using the inner service would make it so that other modules wouldn't be overridden:

Because it didn’t use the innerService argument, any additional module that also decorated the config.installer service also got the overridden protected method added by Features, as long as the decorator_priority of Features was higher than the other module.

Unfortunately the exists tests have not been updated to work in D9 so (even without my changes) they are failing. Will try running the tests on my patch to see how that goes...

leon kessler’s picture

Hi @paul121 I tried your patch. After applying it I no longer get 404's on the cross bundle routes (e.g. jsonapi/node). So this appears to fix that part.

However, I get the following fatal error when visiting the jsonapi_extras admin page: /admin/config/services/jsonapi/resource_types

TypeError: Argument 3 passed to Drupal\jsonapi_extras\JsonapiResourceConfigListBuilder::__construct() must be an instance of Drupal\jsonapi_extras\ResourceType\ConfigurableResourceTypeRepository, instance of Drupal\jsonapi_cross_bundles\ResourceType\CrossBundleResourceTypeRepository given, called in /var/www/html/docroot/modules/contrib/jsonapi_extras/src/JsonapiResourceConfigListBuilder.php on line 59 in Drupal\jsonapi_extras\JsonapiResourceConfigListBuilder->__construct() (line 45 of modules/contrib/jsonapi_extras/src/JsonapiResourceConfigListBuilder.php).

You said:

I've decorated the service with a class that extends ConfigurableResourceTypeRepository

But looking at your patch, the class you are decorating with is CrossBundleResourceTypeRepository, which extends ResourceTypeRepository (from core jsonapi) and not ConfigurableResourceTypeRepository (from jsonapi_extras).

bradjones1’s picture

I think the answer here is somewhere between this module and extras. The work that needs done here is to decorate earlier than extras; because jsonapi_extra's decorated resource type repository does not have a dependency on its decorated service, the cross bundle decorator never gets called. Specifying a decoration priority fixes that.

In addition, we should have this module additionally consider whether a resource type is enabled, in addition to being locatable.

I will be opening a corresponding issue in Extras to typehint against the resource type repository interface (and gracefully handle additional resource types which are not configurable), and link here.

bradjones1’s picture

Status: Active » Needs review
siliconvalet’s picture

Status: Needs review » Needs work
Related issues: +#3229890: Better compatibility with other decorations of resource type repository

Not sure if this should go here or jsonapi_extras (closed ticket #3229890).

Unfortunately, I'm still getting a 404 on the /jsonapi/node path in Postman.

Disabling jsonapi_extras does, indeed, "fix" the issue.

Drupal: 9.3.3
jsonapi_extras: 3.x-dev
jsonapi_cross_bundles: 1.x-dev

bradjones1’s picture

Can you be more specific about what needs work?

siliconvalet’s picture

Status: Needs work » Active

Should I have changed it to "Active"?

Sure. I'm trying to use JSON:API Extras along with this module. It was mentioned that when JSON:API Extras was enabled, this module wouldn't work as expected; making a request to /jsonapi/node didn't work as expected (404).

As suggested in the related ticket (#3229890), this issue has been resolved. However, I'm still experiencing the same issue.

I wasn't sure which thread (this one or the related one) to post to.

Cheers.

ericchew’s picture

I'm not having the issue in #23 with this patch...cross bundle resources are working. However, the issue mentioned in #16 still exists.

simonbaese’s picture

I combined the patch from #3229890 and the changes in #18.

When trying to setup JSON:API Cross Bundles in combination with JSON:API Extras, I found that there is a problem with using the module User Bundle. When clearing the cache, I get the error:

In ResourceTypeRelationship.php line 48: withRelatableResourceTypes() must be called before getting relatable resource types.

Granted - the module is not widely used, but it points to an underlying issue. Unfortunately, I could not find the problem.

In the end, I decided to skip the cross bundle resource for users. I don't want to attach a diff file here because it might cause confusion. But, one can simply add

if ($entity_type->id() == 'user') {
  continue;
}

when iterating the $grouped_by_entity_type_id in CrossBundleResourceTypeRepository::all.

simonbaese’s picture

I did a little more digging, because I also faced problems with other entities. The problem is not specific to the aforementioned User Bundle module.

The problem appears when overwriting the name of a relationship field in JSON:API Extras.

The public name of the field is not known here:
CrossBundleResourceTypeRepository - Line 211

Because when getting the field mappings prior the alias is not fetched from the configuration:
ResourceTypeRepository - Line 269

Not sure how to fix this problem though.

abdelkoddous’s picture

I am facing the same issue as #25 because of some fields with aliased names. I do not know how to solve the issue, but as a workaround, not calling `getRelatableResourceTypes()` on those fields allowed the clearing of the cache to pass without error and I got the listing of the entities cross bundles. However it was not possible to include those relationship in the jsonapi result (which is to expect since they were skipped).

Drupal\jsonapi\ResourceType::getRelatableResourceTypes

  public function getRelatableResourceTypes() {
    if (!isset($this->relatableResourceTypesByField)) {
      $this->relatableResourceTypesByField = array_reduce(array_map(function (ResourceTypeRelationship $field) {
+        if ( in_array($field->getPublicName(), array("fields those names are aliased here")))
+          return [$field->getPublicName() => array()];
        return [$field->getPublicName() => $field->getRelatableResourceTypes()];
      }, array_filter($this->fields, function (ResourceTypeField $field) {
        return $field instanceof ResourceTypeRelationship && $field->isFieldEnabled();
      })), 'array_merge', []);
    }
    return $this->relatableResourceTypesByField;
  }
giuseppe87’s picture

I've tried the patch and I don't have neither the issue described in #16 or #23.
If I go to /admin/config/services/jsonapi/resource_types I get no error; the bundles created by cross bundles are listed but not overridable.

However I think the compatibility is only partial: both this module and extra extends ResourceType, so the extra functionality provided by extras are not available to the end-points created by cross bundles.
For example, the "count" is not available right now, because CrossBundlesResourceType inherits the parent one:

  public function includeCount() {
    // By default, do not return counts in collection queries.
    return FALSE;
  }

Probably the support of other Resource should be a feature request for json api:extras.

fraserthompson’s picture

Status: Active » Needs review

The merge request in #18 wasn't actually reviewed before the issue was switched back to "Active" I don't think? For me with the latest version of both modules that merge request solve the issue: cross bundles show up in JSON API Extras resource overrides section, the paths function correctly, and I'm not seeing the error reported previously with other patches.

It would if we could get more reviewers on that MR and get it RTBC that'd be nice.