Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[Android] Expose ArgumentExtractor to BaseJavaModule subclasses #9931

Closed
wants to merge 9 commits into from
Closed

[Android] Expose ArgumentExtractor to BaseJavaModule subclasses #9931

wants to merge 9 commits into from

Conversation

felipecsl
Copy link
Contributor

Summary

This change allows subclasses of BaseJavaModule to provide a list of ArgumentExtractor factories.
ArgumentExtractor.Factory is a new interface that allows returning a custom ArgumentExtractor for a given type. By doing this, we allow @ReactMethod annotated methods to take arguments of arbitrary types (not just primitives, ReadableMap and ReadableArray).

Motivation

For any non-trivial use of java modules, you'll quickly need to start sending complex objects through the bridge and it becomes very cumbersome and error prone to manually parse them out of a ReadableMap or ReadableArray every time.
This allows for more flexibility and more powerful java modules with little overhead.

Test Plan

I'm still working on the unit test for this, but opening the PR for early feedback.

@ghost
Copy link

ghost commented Sep 15, 2016

By analyzing the blame information on this pull request, we identified @bestander and @astreet to be potential reviewers.

@ghost ghost added GH Review: review-needed CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. labels Sep 15, 2016
@felipecsl felipecsl changed the title Expose argument extractor [Android] Expose argument extractor to BaseJavaModule subclasses Sep 15, 2016
@felipecsl felipecsl changed the title [Android] Expose argument extractor to BaseJavaModule subclasses [Android] Expose ArgumentExtractor to BaseJavaModule subclasses Sep 15, 2016
@ghost
Copy link

ghost commented Sep 15, 2016

@felipecsl updated the pull request - view changes

@ghost ghost added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 15, 2016
@bestander
Copy link
Contributor

Maybe an instrumentation test would be required

@facebook-github-bot
Copy link
Contributor

@felipecsl updated the pull request - view changes

@ghost ghost added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 25, 2016
@ghost
Copy link

ghost commented Sep 26, 2016

@felipecsl updated the pull request - view changes

1 similar comment
@ghost
Copy link

ghost commented Sep 26, 2016

@felipecsl updated the pull request - view changes

@ghost ghost added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 26, 2016
@felipecsl
Copy link
Contributor Author

alright test added, @bestander PTAL

@ghost ghost added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 26, 2016
@bestander
Copy link
Contributor

bestander commented Sep 26, 2016

I'll send a note to android people.
Ping me if it takes long.

@felipecsl
Copy link
Contributor Author

friendly ping again 😄

@ghost
Copy link

ghost commented Sep 28, 2016

@felipecsl updated the pull request - view changes

@ghost ghost added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 28, 2016
@lexs
Copy link
Contributor

lexs commented Sep 28, 2016

I kinda like this idea but it's a change of how we see the bridge if it can send complex objects, however as you noted we already do this today just not in a graceful way.

Do you have plans to support this on iOS too?

static final public String METHOD_TYPE_ASYNC = "async";
static final public String METHOD_TYPE_PROMISE= "promise";
private static final String METHOD_TYPE_ASYNC = "async";
private static final String METHOD_TYPE_PROMISE= "promise";
static final public String METHOD_TYPE_SYNC = "sync";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you change this one too? or at least move the public to be at the beginning

* to {@link ReactMethod} annotated methods with the given {@code Type}. Return {@code null} if
* this factory can't handle the provided type.
*/
public interface Factory {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you use a factory instead of just having a list of ArgumentExtractors?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows you to "plug-in" the logic that associates a specific ArgumentExtractor with a Type. This way you wouldn't need the big if/else/else if... chain in buildArgumentExtractors() and could delegate it to the Factories to provide or not an extractor for the provided Type.


private static abstract class ArgumentExtractor<T> {
public BaseJavaModule(List<? extends ArgumentExtractor.Factory> argumentExtractorFactories) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd prefer having this be provided with from a method instead?
Like: List<ArgumentExtractor> getCustomExtractors()

Also define an extra class so we can tell the type from the extractor, something like:

abstract class CustomArgumentExtractor<T> extends ArgumentExtractor {
  Class<T> getSupportedType();
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I though about doing this way but I'm really not a fan of having this "inheritance party" behavior. Using constructor arguments is a much more explicit way of letting subclasses know about that functionality and having a hook point for defining that.
I understand if you're not a fan of that style though and I'd be happy to change it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's go ahead and change to using the method instead. I realize I feel strongly about this for a few reasons; even if I agree on that inheritance is not always a good solution, however in this case it's really implementing an interface (even if we provide a simplifying base class). The method also gives us more lazy behavior which is something were trying hard to move to, it also matches how this class already works.

@facebook-github-bot
Copy link
Contributor

@felipecsl updated the pull request - view changes

@felipecsl
Copy link
Contributor Author

I can look into making this change for iOS too!

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 3, 2016
@astreet
Copy link
Contributor

astreet commented Nov 2, 2016

I'm ok with this change, @javache are you ok with something similar on iOS?

Nits: we haven't been adding <?> throughout the codebase so lets not just do it in this file.

@facebook-github-bot
Copy link
Contributor

It's been a while since the last commit was reviewed and the labels show this pull request needs review. Based on the blame information for the files in this pull request we identified @bestander as a potential reviewer. Could you take a look please or cc someone with more context?

@felipecsl
Copy link
Contributor Author

BTW I don't think I'll have time to make these changes on iOS as well, at least not for now

@hramos
Copy link
Contributor

hramos commented Nov 11, 2016

@lexs any further comments?

@felipecsl there's some conflicts that need to be addressed in CatalystNativeJSToJavaParametersTestCase.java

@lexs
Copy link
Contributor

lexs commented Nov 11, 2016

Added a comment about using a method instead of inheritance, rebase, and I'll happily merge it (or somebody else can go ahead and do it).

@felipecsl
Copy link
Contributor Author

@lexs ok thanks for your review, I'll rebase it and update later tonight

@felipecsl
Copy link
Contributor Author

@lexs and @astreet PR rebased and updated based on your comments, PTAL

@astreet
Copy link
Contributor

astreet commented Nov 22, 2016

Sorry for the delay -- seems reasonable to me!

@facebook-github-bot shipit

@facebook-github-bot facebook-github-bot added GH Review: accepted Import Started This pull request has been imported. This does not imply the PR has been approved. and removed GH Review: review-needed labels Nov 22, 2016
@facebook-github-bot
Copy link
Contributor

@astreet has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@facebook-github-bot
Copy link
Contributor

I tried to merge this pull request into the Facebook internal repo but some checks failed. To unblock yourself please check the following: Does this pull request pass all open source tests on GitHub? If not please fix those. Does the code still apply cleanly on top of GitHub master? If not can please rebase. In all other cases this means some internal test failed, for example a part of a fb app won't work with this pull request. I've added the Import Failed label to this pull request so it is easy for someone at fb to find the pull request and check what failed. If you don't see anyone comment in a few days feel free to comment mentioning one of the core contributors to the project so they get a notification.

@facebook-github-bot facebook-github-bot added Import Failed and removed Import Started This pull request has been imported. This does not imply the PR has been approved. labels Nov 23, 2016
@@ -299,9 +305,28 @@ public void testGetTypeFromArray() {
assertEquals(ReadableType.Null, array.getType(6));
}

public void testCustomTypeViaArgumentExtractor() {
mCatalystInstance.getJSModule(TestJSToJavaParametersModule.class).returnCustomType();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Land failed as tests don't compile since TestJSToJavaParametersModule#returnCustomType isn't defined. Make sure to run the integration tests first: ./scripts/run-android-local-integration-tests.sh

@hramos
Copy link
Contributor

hramos commented Jan 19, 2017

Ping @felipecsl

@mkonicek
Copy link
Contributor

mkonicek commented Feb 2, 2017

Closing this because of no response for two weeks. But it was accepted, just needs some minor tweaks and rebase. @felipecsl feel free to send a new PR mentioning this one so people know it should be merged.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants