We should mark the jsonapi.serializer_do_not_use_removal_imminent service as private.

The challenge with doing this is that the service is used in RequestHandler, which is only instantiated at runtime (making it impossible to get the service if it's marked as private).

This is currently blocked by #2883086: [PP-1] Port RequestHandler + ResourceResponseSubscriber improvements from REST module to JSON API

Comments

gabesullice created an issue. See original summary.

wim leers’s picture

Title: Mark the JSON API serializer service as private » [PP-1] Mark the JSON API serializer service as private
wim leers’s picture

wim leers’s picture

Status: Postponed » Needs review
StatusFileSize
new1.63 KB

This ports the relevant changes from #2920536: Force all serializer encoders + normalizers services to be private. Even just this change is causing lots of fails because for example JsonApiDocumentTopLevelNormalizerTest is retrieving the normalizer from the container.

This does NOT yet mark the jsonapi.serializer_do_not_use_removal_imminent service itself as private.

Status: Needs review » Needs work

The last submitted patch, 4: 2935370-4.patch, failed testing. View results

wim leers’s picture

Status: Needs work » Postponed
wim leers’s picture

StatusFileSize
new13.44 KB
new15.02 KB

@gabesullice pointed out that the problem here is that the RequestHandler needs to get the serializer service. But that can be solved by injecting it. Attached interdiff fixes that, and makes all services be injected into the request handler.

This should pass more tests.

gabesullice’s picture

  1. +++ b/jsonapi.services.yml
    @@ -137,6 +137,19 @@ services:
    +    arguments:
    +      - '@jsonapi.serializer_do_not_use_removal_imminent'
    +      - '@jsonapi.current_context'
    +      - '@renderer'
    +      - '@jsonapi.resource_type.repository'
    +      - '@entity_type.manager'
    +      - '@entity_field.manager'
    +      - '@plugin.manager.field.field_type'
    +      - '@jsonapi.link_manager'
    

    What?! How did I never realize this syntax was possible before?!

  2. +++ b/src/Controller/RequestHandler.php
    @@ -21,17 +28,75 @@ use Symfony\Component\Serializer\SerializerInterface;
    -class RequestHandler implements ContainerAwareInterface, ContainerInjectionInterface {
    ...
    -  use ContainerAwareTrait;
    

    XD

  3. +++ b/src/Controller/RequestHandler.php
    @@ -21,17 +28,75 @@ use Symfony\Component\Serializer\SerializerInterface;
    -    return new static();
    ...
    +  public function __construct($serializer, CurrentContext $current_context, RendererInterface $renderer, ResourceTypeRepositoryInterface $resource_type_repository, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $field_manager, FieldTypePluginManagerInterface $field_type_manager, LinkManager $link_manager) {
    

    :O)

  4. +++ b/src/Controller/RequestHandler.php
    @@ -21,17 +28,75 @@ use Symfony\Component\Serializer\SerializerInterface;
    +  protected static $requiredCacheContexts = ['user.permissions'];
    

    Nit: can we keep this near the top of the class?

wim leers’s picture

#8 :)
#8.4: that's dead code… I should just remove it.

wim leers’s picture

Status: Postponed » Needs review
StatusFileSize
new2.57 KB
new17.52 KB

Fix RequestHandlerTest's mocks.

Status: Needs review » Needs work

The last submitted patch, 10: 2935370-10.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

wim leers’s picture

Status: Needs work » Needs review
StatusFileSize
new18.96 KB
new3.4 KB

Fix remaining failures in JsonApiDocumentTopLevelNormalizerTest.

wim leers’s picture

StatusFileSize
new1.16 KB
new20.05 KB

#12 was incomplete.

The last submitted patch, 12: 2935370-12.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Status: Needs review » Needs work

The last submitted patch, 13: 2935370-13.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

wim leers’s picture

Status: Needs work » Needs review
StatusFileSize
new1.33 KB
new21.34 KB

The remaining failures were hard to debug. They happen because \Drupal\jsonapi\Normalizer\RelationshipItemNormalizer::__construct() gets \Drupal\jsonapi\Normalizer\JsonApiDocumentTopLevelNormalizer injected. But because it's injected, setSerializer() has not yet been called on it, which \Drupal\jsonapi\Serializer\Serializer::__construct() does.

But we haven't changed any logic, so why is this happening?

Well, it's been happening since #4. #4 is marking all normalizer services private. Marking a service private also makes it non-shared. And it's impossible to mark it shared explicitly when it's marked private. So simply doing setShared(TRUE) or shared: true doesn't fix the problem.

The real problem here is that RelationshipItemNormalizer is doing something it shouldn't. And we even added

 @todo Remove the dependency on \Drupal\jsonapi\Normalizer\JsonApiDocumentTopLevelNormalizer

for that in issue comment #2831185-5: Rename DocumentWrapper to JsonApiDocumentTopLevel and DocumentRootNormalizer to JsonApiDocumentTopLevelNormalizer (commit b064a203) in Dec 2016. Fixing that is out of scope here, so just making sure that the setSerializer() calls cascades.


WHEW! That was a hard one to debug!

wim leers’s picture

StatusFileSize
new439 bytes
new21.57 KB

GREEN! Green for the first time!

So now let's do the final step: mark the serializer service as private too.

wim leers’s picture

StatusFileSize
new2.02 KB
new21.86 KB

YAY! ALSO GREEN!

Let's fix CS violations.

wim leers’s picture

StatusFileSize
new2.42 KB
new22.75 KB

Self-review:

  1. +++ b/src/Controller/RequestHandler.php
    @@ -2,36 +2,95 @@
    +  public function __construct($serializer, CurrentContext $current_context, RendererInterface $renderer, ResourceTypeRepositoryInterface $resource_type_repository, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $field_manager, FieldTypePluginManagerInterface $field_type_manager, LinkManager $link_manager) {
    

    Missing docs.

  2. +++ b/tests/modules/jsonapi_test_normalizers_kernel/jsonapi_test_normalizers_kernel.info.yml
    @@ -0,0 +1,5 @@
    +name: 'JSON API test normalizers in Kernel tests'
    

    Needs better description.

Fixed both.

e0ipso’s picture

Self-review:

I love your self-reviews, they are so helpful when reviewing!

gabesullice’s picture

  1. +++ b/jsonapi.services.yml
    @@ -137,6 +138,19 @@ services:
    +  # Controllers.
    +  jsonapi.request_handler:
    +    class: \Drupal\jsonapi\Controller\RequestHandler
    

    ❤️

  2. +++ b/src/Controller/RequestHandler.php
    @@ -2,36 +2,115 @@
    -class RequestHandler implements ContainerAwareInterface, ContainerInjectionInterface {
    +class RequestHandler {
    

    <3

  3. +++ b/src/DependencyInjection/Compiler/RegisterSerializationClassesCompilerPass.php
    @@ -59,6 +59,9 @@ class RegisterSerializationClassesCompilerPass extends DrupalRegisterSerializati
    +      // The 'serializer' service is the public API: mark normalizers private.
    
    @@ -69,6 +72,9 @@ class RegisterSerializationClassesCompilerPass extends DrupalRegisterSerializati
    +      // The 'serializer' service is the public API: mark encoders private.
    

    There is no public API for even the serializer.

  4. +++ b/src/Routing/Routes.php
    @@ -26,7 +26,7 @@ class Routes implements ContainerInjectionInterface {
    -  const FRONT_CONTROLLER = '\Drupal\jsonapi\Controller\RequestHandler::handle';
    +  const FRONT_CONTROLLER = 'jsonapi.request_handler:handle';
    

    <3

gabesullice’s picture

Status: Needs review » Needs work

Just needs the one comment change.

wim leers’s picture

Status: Needs work » Needs review
StatusFileSize
new1.53 KB
new22.7 KB
I will not copy/paste <em>any</em> comment without re-assessing it.
I will not copy/paste <em>any</em> comment without re-assessing it.
I will not copy/paste <em>any</em> comment without re-assessing it.
I will not copy/paste <em>any</em> comment without re-assessing it.
I will not copy/paste <em>any</em> comment without re-assessing it.
I will not copy/paste <em>any</em> comment without re-assessing it.
I will not copy/paste <em>any</em> comment without re-assessing it.
I will not copy/paste <em>any</em> comment without re-assessing it.
I will not copy/paste <em>any</em> comment without re-assessing it.
I will not copy/paste <em>any</em> comment without re-assessing it.
I will not copy/paste <em>any</em> comment without re-assessing it.

Fixed :)

wim leers’s picture

Also:

I love your self-reviews, they are so helpful when reviewing!

❤️

gabesullice’s picture

Status: Needs review » Reviewed & tested by the community
wim leers’s picture

Title: [PP-1] Mark the JSON API serializer service as private » Mark the JSON API serializer service as private

This was marked postponed/[PP-1] in #6 by me:

Still postponed on #2883086: [PP-1] Port RequestHandler + ResourceResponseSubscriber improvements from REST module to JSON API. Just wanted to post an initial patch.

… but in fact I see no reason to block this on that. In fact, this issue makes #2883086 simpler! This patch makes zero functional changes to RequestHandler. The only thing this changes, is how it gets the services it needs injected. #2883086 will change much more, and this makes that slightly easier.

Removing the [PP-1].

wim leers’s picture

Title: Mark the JSON API serializer service as private » Mark the JSON API serializer, normalizer and encoder services as private
Priority: Normal » Major
wim leers’s picture

wim leers’s picture

wim leers’s picture

e0ipso’s picture

Status: Reviewed & tested by the community » Fixed
  1. +++ b/tests/modules/jsonapi_test_normalizers_kernel/jsonapi_test_normalizers_kernel.services.yml
    @@ -0,0 +1,4 @@
    +services:
    +  jsonapi_test_normalizers_kernel.jsonapi_document_toplevel:
    +    alias: serializer.normalizer.jsonapi_document_toplevel.jsonapi
    +    public: true
    

    Nifty!

  2. +++ b/tests/src/Kernel/Normalizer/JsonApiDocumentTopLevelNormalizerTest.php
    @@ -358,7 +358,7 @@ class JsonApiDocumentTopLevelNormalizerTest extends JsonapiKernelTestBase {
    -      ->get('serializer.normalizer.jsonapi_document_toplevel.jsonapi')
    +      ->get('jsonapi.serializer_do_not_use_removal_imminent')
    

    I'm not a fan of using the serializer (that calls the normalizers) to kernel-test the normalizers. However I see the convenience of it and I support that.

💥

  • e0ipso committed 3c81d9e on 8.x-1.x authored by Wim Leers
    Issue #2935370 by Wim Leers, gabesullice, e0ipso: Mark the JSON API...
wim leers’s picture

Status: Fixed » Reviewed & tested by the community
StatusFileSize
new1.55 KB

I'm not a fan of using the serializer (that calls the normalizers) to kernel-test the normalizers. However I see the convenience of it and I support that.

This was accidental! Attached is a patch that fixes both places where that happened, and actually updates even one more pre-existing one!

  • e0ipso committed cb46fc9 on 8.x-1.x authored by Wim Leers
    Issue #2935370 by Wim Leers, gabesullice, e0ipso: Mark the JSON API...
e0ipso’s picture

Status: Reviewed & tested by the community » Fixed

Committed! Thanks again. You rock, I will not get tired of telling you both.

wim leers’s picture

❤️

Status: Fixed » Closed (fixed)

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