RxJavaPlugins, the pattern behind











up vote
0
down vote

favorite












I want to reproduce the "static" injection of RxJava using the RxJavaPlugins and i'am wondring if the design of this class is a well known pattern !?



I have a basic model class for all my events



import lombok.Getter;

public abstract class BasicEvent {

@Getter
private final String id;

@Getter
private final long timestamp;

public BasicEvent() {
this.id = IDGenerator.BY_COUNTER.generate();
this.timestamp = TimePlayer.clock().timestamp();
}
}


The main drawback of the class above is the testability. I cannot change the IDGenerator and the TimePlayer.



I think that having a third party class, designed like RxJavaPlugins could help me changing my metadata generators for tests



UPDATE .



I've followed the RxJavaPlugins solution for keeping model's creation simple, without worrying about the id and the timestamp (i called the two fields metadata), here is solution a found.



public BasicEvent() {
this.id = MetaGenerator.idGenerator().generate();
this.timestamp = MetaGenerator.timePlayer().timestamp();
}


public class MetaGenerator {

public static IDGenerator idGenerator() {
// DGenerator.BY_COUNTER is the default value
return MetaGeneratorPlugins.onIDGenerator(IDGenerator.BY_COUNTER);
}

public static TimePlayer timePlayer() {
return MetaGeneratorPlugins.onTimePlayer(TimePlayer.realtime);
}
}

public class MetaGeneratorPlugins {

private static Function<? super TimePlayer, ? extends TimePlayer> onTimePlayerHandler;
private static Function<? super IDGenerator, ? extends IDGenerator> onIDGeneratorHandler;

public static void setTimePlayerHandler(@Nullable Function<? super TimePlayer, ? extends TimePlayer> handler) {
onTimePlayerHandler = handler;
}

public static void setIDGeneratorHandler(@Nullable Function<? super IDGenerator, ? extends IDGenerator> handler) {
onIDGeneratorHandler = handler;
}

//return the default value or the value returned by the handler
public static TimePlayer onTimePlayer(@Nonnull TimePlayer defaultScheduler) {
if (onTimePlayerHandler == null) {
return defaultScheduler;
}
return apply(onTimePlayerHandler, defaultScheduler);
}

public static IDGenerator onIDGenerator(@Nonnull IDGenerator defaultScheduler) {
if (onIDGeneratorHandler == null) {
return defaultScheduler;
}
return apply(onIDGeneratorHandler, defaultScheduler);
}

private static <T, R> R apply(@Nonnull Function<T, R> f, @Nonnull T t) {
return f.apply(t);
}
}


In my tests now i can change this MetaGenerator's implementation by calling MetaGeneratorPlugins



MetaGeneratorPlugins.setIDGeneratorHandler(IDGenerator.INCREMENTAL);
MetaGeneratorPlugins.setTimePlayerHandler(TimePlayer.simulated);


This is how RxJavaPlugins works, i have been inspired by they solution,



Now the creation of my models are simple and it works for production and tests.










share|improve this question




























    up vote
    0
    down vote

    favorite












    I want to reproduce the "static" injection of RxJava using the RxJavaPlugins and i'am wondring if the design of this class is a well known pattern !?



    I have a basic model class for all my events



    import lombok.Getter;

    public abstract class BasicEvent {

    @Getter
    private final String id;

    @Getter
    private final long timestamp;

    public BasicEvent() {
    this.id = IDGenerator.BY_COUNTER.generate();
    this.timestamp = TimePlayer.clock().timestamp();
    }
    }


    The main drawback of the class above is the testability. I cannot change the IDGenerator and the TimePlayer.



    I think that having a third party class, designed like RxJavaPlugins could help me changing my metadata generators for tests



    UPDATE .



    I've followed the RxJavaPlugins solution for keeping model's creation simple, without worrying about the id and the timestamp (i called the two fields metadata), here is solution a found.



    public BasicEvent() {
    this.id = MetaGenerator.idGenerator().generate();
    this.timestamp = MetaGenerator.timePlayer().timestamp();
    }


    public class MetaGenerator {

    public static IDGenerator idGenerator() {
    // DGenerator.BY_COUNTER is the default value
    return MetaGeneratorPlugins.onIDGenerator(IDGenerator.BY_COUNTER);
    }

    public static TimePlayer timePlayer() {
    return MetaGeneratorPlugins.onTimePlayer(TimePlayer.realtime);
    }
    }

    public class MetaGeneratorPlugins {

    private static Function<? super TimePlayer, ? extends TimePlayer> onTimePlayerHandler;
    private static Function<? super IDGenerator, ? extends IDGenerator> onIDGeneratorHandler;

    public static void setTimePlayerHandler(@Nullable Function<? super TimePlayer, ? extends TimePlayer> handler) {
    onTimePlayerHandler = handler;
    }

    public static void setIDGeneratorHandler(@Nullable Function<? super IDGenerator, ? extends IDGenerator> handler) {
    onIDGeneratorHandler = handler;
    }

    //return the default value or the value returned by the handler
    public static TimePlayer onTimePlayer(@Nonnull TimePlayer defaultScheduler) {
    if (onTimePlayerHandler == null) {
    return defaultScheduler;
    }
    return apply(onTimePlayerHandler, defaultScheduler);
    }

    public static IDGenerator onIDGenerator(@Nonnull IDGenerator defaultScheduler) {
    if (onIDGeneratorHandler == null) {
    return defaultScheduler;
    }
    return apply(onIDGeneratorHandler, defaultScheduler);
    }

    private static <T, R> R apply(@Nonnull Function<T, R> f, @Nonnull T t) {
    return f.apply(t);
    }
    }


    In my tests now i can change this MetaGenerator's implementation by calling MetaGeneratorPlugins



    MetaGeneratorPlugins.setIDGeneratorHandler(IDGenerator.INCREMENTAL);
    MetaGeneratorPlugins.setTimePlayerHandler(TimePlayer.simulated);


    This is how RxJavaPlugins works, i have been inspired by they solution,



    Now the creation of my models are simple and it works for production and tests.










    share|improve this question


























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I want to reproduce the "static" injection of RxJava using the RxJavaPlugins and i'am wondring if the design of this class is a well known pattern !?



      I have a basic model class for all my events



      import lombok.Getter;

      public abstract class BasicEvent {

      @Getter
      private final String id;

      @Getter
      private final long timestamp;

      public BasicEvent() {
      this.id = IDGenerator.BY_COUNTER.generate();
      this.timestamp = TimePlayer.clock().timestamp();
      }
      }


      The main drawback of the class above is the testability. I cannot change the IDGenerator and the TimePlayer.



      I think that having a third party class, designed like RxJavaPlugins could help me changing my metadata generators for tests



      UPDATE .



      I've followed the RxJavaPlugins solution for keeping model's creation simple, without worrying about the id and the timestamp (i called the two fields metadata), here is solution a found.



      public BasicEvent() {
      this.id = MetaGenerator.idGenerator().generate();
      this.timestamp = MetaGenerator.timePlayer().timestamp();
      }


      public class MetaGenerator {

      public static IDGenerator idGenerator() {
      // DGenerator.BY_COUNTER is the default value
      return MetaGeneratorPlugins.onIDGenerator(IDGenerator.BY_COUNTER);
      }

      public static TimePlayer timePlayer() {
      return MetaGeneratorPlugins.onTimePlayer(TimePlayer.realtime);
      }
      }

      public class MetaGeneratorPlugins {

      private static Function<? super TimePlayer, ? extends TimePlayer> onTimePlayerHandler;
      private static Function<? super IDGenerator, ? extends IDGenerator> onIDGeneratorHandler;

      public static void setTimePlayerHandler(@Nullable Function<? super TimePlayer, ? extends TimePlayer> handler) {
      onTimePlayerHandler = handler;
      }

      public static void setIDGeneratorHandler(@Nullable Function<? super IDGenerator, ? extends IDGenerator> handler) {
      onIDGeneratorHandler = handler;
      }

      //return the default value or the value returned by the handler
      public static TimePlayer onTimePlayer(@Nonnull TimePlayer defaultScheduler) {
      if (onTimePlayerHandler == null) {
      return defaultScheduler;
      }
      return apply(onTimePlayerHandler, defaultScheduler);
      }

      public static IDGenerator onIDGenerator(@Nonnull IDGenerator defaultScheduler) {
      if (onIDGeneratorHandler == null) {
      return defaultScheduler;
      }
      return apply(onIDGeneratorHandler, defaultScheduler);
      }

      private static <T, R> R apply(@Nonnull Function<T, R> f, @Nonnull T t) {
      return f.apply(t);
      }
      }


      In my tests now i can change this MetaGenerator's implementation by calling MetaGeneratorPlugins



      MetaGeneratorPlugins.setIDGeneratorHandler(IDGenerator.INCREMENTAL);
      MetaGeneratorPlugins.setTimePlayerHandler(TimePlayer.simulated);


      This is how RxJavaPlugins works, i have been inspired by they solution,



      Now the creation of my models are simple and it works for production and tests.










      share|improve this question















      I want to reproduce the "static" injection of RxJava using the RxJavaPlugins and i'am wondring if the design of this class is a well known pattern !?



      I have a basic model class for all my events



      import lombok.Getter;

      public abstract class BasicEvent {

      @Getter
      private final String id;

      @Getter
      private final long timestamp;

      public BasicEvent() {
      this.id = IDGenerator.BY_COUNTER.generate();
      this.timestamp = TimePlayer.clock().timestamp();
      }
      }


      The main drawback of the class above is the testability. I cannot change the IDGenerator and the TimePlayer.



      I think that having a third party class, designed like RxJavaPlugins could help me changing my metadata generators for tests



      UPDATE .



      I've followed the RxJavaPlugins solution for keeping model's creation simple, without worrying about the id and the timestamp (i called the two fields metadata), here is solution a found.



      public BasicEvent() {
      this.id = MetaGenerator.idGenerator().generate();
      this.timestamp = MetaGenerator.timePlayer().timestamp();
      }


      public class MetaGenerator {

      public static IDGenerator idGenerator() {
      // DGenerator.BY_COUNTER is the default value
      return MetaGeneratorPlugins.onIDGenerator(IDGenerator.BY_COUNTER);
      }

      public static TimePlayer timePlayer() {
      return MetaGeneratorPlugins.onTimePlayer(TimePlayer.realtime);
      }
      }

      public class MetaGeneratorPlugins {

      private static Function<? super TimePlayer, ? extends TimePlayer> onTimePlayerHandler;
      private static Function<? super IDGenerator, ? extends IDGenerator> onIDGeneratorHandler;

      public static void setTimePlayerHandler(@Nullable Function<? super TimePlayer, ? extends TimePlayer> handler) {
      onTimePlayerHandler = handler;
      }

      public static void setIDGeneratorHandler(@Nullable Function<? super IDGenerator, ? extends IDGenerator> handler) {
      onIDGeneratorHandler = handler;
      }

      //return the default value or the value returned by the handler
      public static TimePlayer onTimePlayer(@Nonnull TimePlayer defaultScheduler) {
      if (onTimePlayerHandler == null) {
      return defaultScheduler;
      }
      return apply(onTimePlayerHandler, defaultScheduler);
      }

      public static IDGenerator onIDGenerator(@Nonnull IDGenerator defaultScheduler) {
      if (onIDGeneratorHandler == null) {
      return defaultScheduler;
      }
      return apply(onIDGeneratorHandler, defaultScheduler);
      }

      private static <T, R> R apply(@Nonnull Function<T, R> f, @Nonnull T t) {
      return f.apply(t);
      }
      }


      In my tests now i can change this MetaGenerator's implementation by calling MetaGeneratorPlugins



      MetaGeneratorPlugins.setIDGeneratorHandler(IDGenerator.INCREMENTAL);
      MetaGeneratorPlugins.setTimePlayerHandler(TimePlayer.simulated);


      This is how RxJavaPlugins works, i have been inspired by they solution,



      Now the creation of my models are simple and it works for production and tests.







      java rx-java2 reactive






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 10 at 11:21

























      asked Nov 9 at 14:29









      Elma Cherb

      11




      11
























          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote













          Change the design of BasicEvent so that the id and timestamp are bound in a more testable fashion.



          Introduce a "stamper" interface:



          public interface Stamper {
          String generateId();
          long generateTimestamp();
          }


          The "default" implementation would look like:



          public RealTimeStamper implements Stamper {
          @Override public String generateId() {
          return IDGenerator.BY_COUNTER.generate();
          }
          @Override public long generateTimestamp() {
          return TimePlayer.clock().timestamp();
          }
          }


          Provide a testable implementation of Stamper. Then bind the appropriate implementation using whatever dependency injection process you use.



          public abstract class BasicEvent {
          static Stamper stamper;
          ...
          public BasicEvent() {
          this.id = stamper.generateId();
          this.timestamp = stamper.generateTimestamp();
          }
          }


          The stamper field can be injected either manually or using a dependency injection framework.






          share|improve this answer





















          • Sorry i can't show you my final code because of the auto ban, i'll try to put it on github for more explanation
            – Elma Cherb
            Nov 10 at 11:18










          • i've updated my poste above. My response is after the UPDATE line
            – Elma Cherb
            Nov 10 at 11:22












          • Your solution looks to be a comprehensive answer to your original question. It uses dependency injection to provide the values that you need when you need them. As such, there is nothing I can add to it. Or remove.
            – Bob Dalgleish
            Nov 13 at 17:43











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53227635%2frxjavaplugins-the-pattern-behind%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          1
          down vote













          Change the design of BasicEvent so that the id and timestamp are bound in a more testable fashion.



          Introduce a "stamper" interface:



          public interface Stamper {
          String generateId();
          long generateTimestamp();
          }


          The "default" implementation would look like:



          public RealTimeStamper implements Stamper {
          @Override public String generateId() {
          return IDGenerator.BY_COUNTER.generate();
          }
          @Override public long generateTimestamp() {
          return TimePlayer.clock().timestamp();
          }
          }


          Provide a testable implementation of Stamper. Then bind the appropriate implementation using whatever dependency injection process you use.



          public abstract class BasicEvent {
          static Stamper stamper;
          ...
          public BasicEvent() {
          this.id = stamper.generateId();
          this.timestamp = stamper.generateTimestamp();
          }
          }


          The stamper field can be injected either manually or using a dependency injection framework.






          share|improve this answer





















          • Sorry i can't show you my final code because of the auto ban, i'll try to put it on github for more explanation
            – Elma Cherb
            Nov 10 at 11:18










          • i've updated my poste above. My response is after the UPDATE line
            – Elma Cherb
            Nov 10 at 11:22












          • Your solution looks to be a comprehensive answer to your original question. It uses dependency injection to provide the values that you need when you need them. As such, there is nothing I can add to it. Or remove.
            – Bob Dalgleish
            Nov 13 at 17:43















          up vote
          1
          down vote













          Change the design of BasicEvent so that the id and timestamp are bound in a more testable fashion.



          Introduce a "stamper" interface:



          public interface Stamper {
          String generateId();
          long generateTimestamp();
          }


          The "default" implementation would look like:



          public RealTimeStamper implements Stamper {
          @Override public String generateId() {
          return IDGenerator.BY_COUNTER.generate();
          }
          @Override public long generateTimestamp() {
          return TimePlayer.clock().timestamp();
          }
          }


          Provide a testable implementation of Stamper. Then bind the appropriate implementation using whatever dependency injection process you use.



          public abstract class BasicEvent {
          static Stamper stamper;
          ...
          public BasicEvent() {
          this.id = stamper.generateId();
          this.timestamp = stamper.generateTimestamp();
          }
          }


          The stamper field can be injected either manually or using a dependency injection framework.






          share|improve this answer





















          • Sorry i can't show you my final code because of the auto ban, i'll try to put it on github for more explanation
            – Elma Cherb
            Nov 10 at 11:18










          • i've updated my poste above. My response is after the UPDATE line
            – Elma Cherb
            Nov 10 at 11:22












          • Your solution looks to be a comprehensive answer to your original question. It uses dependency injection to provide the values that you need when you need them. As such, there is nothing I can add to it. Or remove.
            – Bob Dalgleish
            Nov 13 at 17:43













          up vote
          1
          down vote










          up vote
          1
          down vote









          Change the design of BasicEvent so that the id and timestamp are bound in a more testable fashion.



          Introduce a "stamper" interface:



          public interface Stamper {
          String generateId();
          long generateTimestamp();
          }


          The "default" implementation would look like:



          public RealTimeStamper implements Stamper {
          @Override public String generateId() {
          return IDGenerator.BY_COUNTER.generate();
          }
          @Override public long generateTimestamp() {
          return TimePlayer.clock().timestamp();
          }
          }


          Provide a testable implementation of Stamper. Then bind the appropriate implementation using whatever dependency injection process you use.



          public abstract class BasicEvent {
          static Stamper stamper;
          ...
          public BasicEvent() {
          this.id = stamper.generateId();
          this.timestamp = stamper.generateTimestamp();
          }
          }


          The stamper field can be injected either manually or using a dependency injection framework.






          share|improve this answer












          Change the design of BasicEvent so that the id and timestamp are bound in a more testable fashion.



          Introduce a "stamper" interface:



          public interface Stamper {
          String generateId();
          long generateTimestamp();
          }


          The "default" implementation would look like:



          public RealTimeStamper implements Stamper {
          @Override public String generateId() {
          return IDGenerator.BY_COUNTER.generate();
          }
          @Override public long generateTimestamp() {
          return TimePlayer.clock().timestamp();
          }
          }


          Provide a testable implementation of Stamper. Then bind the appropriate implementation using whatever dependency injection process you use.



          public abstract class BasicEvent {
          static Stamper stamper;
          ...
          public BasicEvent() {
          this.id = stamper.generateId();
          this.timestamp = stamper.generateTimestamp();
          }
          }


          The stamper field can be injected either manually or using a dependency injection framework.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 9 at 17:20









          Bob Dalgleish

          5,5311933




          5,5311933












          • Sorry i can't show you my final code because of the auto ban, i'll try to put it on github for more explanation
            – Elma Cherb
            Nov 10 at 11:18










          • i've updated my poste above. My response is after the UPDATE line
            – Elma Cherb
            Nov 10 at 11:22












          • Your solution looks to be a comprehensive answer to your original question. It uses dependency injection to provide the values that you need when you need them. As such, there is nothing I can add to it. Or remove.
            – Bob Dalgleish
            Nov 13 at 17:43


















          • Sorry i can't show you my final code because of the auto ban, i'll try to put it on github for more explanation
            – Elma Cherb
            Nov 10 at 11:18










          • i've updated my poste above. My response is after the UPDATE line
            – Elma Cherb
            Nov 10 at 11:22












          • Your solution looks to be a comprehensive answer to your original question. It uses dependency injection to provide the values that you need when you need them. As such, there is nothing I can add to it. Or remove.
            – Bob Dalgleish
            Nov 13 at 17:43
















          Sorry i can't show you my final code because of the auto ban, i'll try to put it on github for more explanation
          – Elma Cherb
          Nov 10 at 11:18




          Sorry i can't show you my final code because of the auto ban, i'll try to put it on github for more explanation
          – Elma Cherb
          Nov 10 at 11:18












          i've updated my poste above. My response is after the UPDATE line
          – Elma Cherb
          Nov 10 at 11:22






          i've updated my poste above. My response is after the UPDATE line
          – Elma Cherb
          Nov 10 at 11:22














          Your solution looks to be a comprehensive answer to your original question. It uses dependency injection to provide the values that you need when you need them. As such, there is nothing I can add to it. Or remove.
          – Bob Dalgleish
          Nov 13 at 17:43




          Your solution looks to be a comprehensive answer to your original question. It uses dependency injection to provide the values that you need when you need them. As such, there is nothing I can add to it. Or remove.
          – Bob Dalgleish
          Nov 13 at 17:43


















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53227635%2frxjavaplugins-the-pattern-behind%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          How to pass form data using jquery Ajax to insert data in database?

          National Museum of Racing and Hall of Fame

          Guess what letter conforming each word