[ 
https://issues.apache.org/jira/browse/MAPREDUCE-4762?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13491610#comment-13491610
 ] 

Ivan A. Veselovsky commented on MAPREDUCE-4762:
-----------------------------------------------

Hi, Daryn,
unfortunately there is no way to directly inject implementations into 
java.util.ServiceLoader. There is ServiceLoader#reload() method, but it also 
reloads the implementations with the *same* classloader that was cached upon 
the ServiceLoader object creation. Also ServiceLoader is declared final, so 
there is no way to subclass it. 

So, besides the way initially suggested in the suggested patch, we can consider 
2 alternative implementations:
1) Provide protected static setter 
org.apache.hadoop.security.token.Token.setTokenRenewerServiceLoader(ServiceLoader<TokenRenewer>)
 like this:
{noformat}  
  protected static void 
setTokenRenewerServiceLoader(ServiceLoader<TokenRenewer> 
newTokenRenewerServiceLoader) {
    renewers = newTokenRenewerServiceLoader;
  }
{noformat} 
  , and in the test create a new renewer service loader (with the help of our 
artificially constructed class-loader), and set it using the provided setter:
{noformat} 
  @Test
  public void testDTRenewal() throws Exception {
    final ClassLoader myCl = new 
MyRenewerClassLoader(getClass().getClassLoader());
    final ServiceLoader<TokenRenewer> newSl = 
ServiceLoader.load(TokenRenewer.class, myCl);
    MyToken.setTokenRenewerServiceLoader(newSl); // this is a static delegate 
to make the protected Token#setTokenRenewerServiceLoader() visible
    ...
{noformat} 
Main drawback of this option is that it requires the protected static setter 
that can be mistakely used somewhere in non-test code, what is dangerous.
Though, I think, this way is also spooky a little bit. :)

2) Direct injection of "renewer" non-static field into the MyToken or Token 
object (as probably suggested by you) -- this also requires a new setter, but 
what is worse, that will not correctly test the method 
org.apache.hadoop.security.token.Token.getRenewer() --  the Renewer object will 
not be searched in using 
org.apache.hadoop.security.token.TokenRenewer.handleKind(Text), but will be 
used directly. One of our goals is to improve coverage of the code by the 
tests, so it would be better if we force the test to pass through 
Token.getRenewer() in the same way as it goes in the production.

So, what implementation do you prefer?
                
> repair test 
> org.apache.hadoop.mapreduce.security.token.TestDelegationTokenRenewal
> ---------------------------------------------------------------------------------
>
>                 Key: MAPREDUCE-4762
>                 URL: https://issues.apache.org/jira/browse/MAPREDUCE-4762
>             Project: Hadoop Map/Reduce
>          Issue Type: Improvement
>            Reporter: Ivan A. Veselovsky
>         Attachments: MAPREDUCE-4762-trunk.patch
>
>
> The test 
> org.apache.hadoop.mapreduce.security.token.TestDelegationTokenRenewal is 
> @Ignor-ed. 
> Due to that several classes in package 
> org.apache.hadoop.mapreduce.security.token have zero unit-test coverage.
> The problem is that the test assumed that class 
> org.apache.hadoop.mapreduce.security.token.TestDelegationTokenRenewal.Renewer 
> is used as a custom implementation of the 
> org.apache.hadoop.security.token.TokenRenewer service, but that did not 
> happen, because this custom service implementation was not registered. 
> We solved this problem by using special classloader that is invoked to find 
> the resource META-INF/services/org.apache.hadoop.security.token.TokenRenewer 
> , and supplies some custom content for it. This way the custom service 
> implementation gets instantiated.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to