0 Replies Latest reply on Jan 2, 2018 2:17 PM by cfang

    @JobScoped, @StepScoped and @PartitionScoped can now be used on TYPE, METHOD and FIELD

    cfang

      JobScoped, StepScoped and PartitionScoped are custom CDI scopes implemented in JBeret to provide more fine-grined scoping specific to batch applications.  In JBeret 1.3.0.Beta7 and earlier releases, only TYPE target is supported for these 3 scopes, which means you can only use these scopes on your own class.  For example, a typical usage is as follows:

       

      import javax.inject.Named;
      import org.jberet.cdi.JobScoped;
      
      @Named
      @JobScoped
      public class Foo {
      ...
      }

      and inject it to a batch artifact class, and the injected bean instance will be scoped to the current job execution:

       

      @Named
      public class JobScopeBatchlet1 extends ScopeArtifactBase implements Batchlet {
          @Inject
          private Foo foo;
      ...
      }

      But what if I don't have control over the source code of the bean class that I want to inject?  For example, it's common to inject types like JPA EntityManager, or JDBC DataSource.  Clearly batch application developers don't own these source code, but it's still desirable to be able to specify a batch-specific scopes to those injected resources.  This is a problem summarized in JBERET-373 (Custom CDI Scopes need to support METHOD and FIELD targets)

       

      Shortly after releasing JBeret 1.3.0.Beta7, this issue was fixed, and these 3 scopes are enhanced to support TYPE, METHOD and FIELD targets.  Now in addition to the above type-level usage, these 3 scopes can be applied on METHOD and FIELD targets as well.

      /**
       * A CDI producer class to produce injection resources to batch artifacts.
       */
      public class FooProducer {
          @Produces
          @JobScoped
          @Named("jobScopedField")
          private FooFieldTarget jobScopedFooFieldTarget = new FooFieldTarget();
      
          @Produces
          @StepScoped
          @Named("stepScopedField")
          private FooFieldTarget stepScopedFooFieldTarget = new FooFieldTarget();
      
          @Produces
          @PartitionScoped
          @Named("partitionScopedField")
          private FooFieldTarget partitionScopedFooFieldTarget = new FooFieldTarget();
      
          @Produces
          @JobScoped
          @Named("jobScopedMethod")
          public FooMethodTarget getJobScopedFooMethodTarget() {
              return new FooMethodTarget();
          }
      
          @Produces
          @StepScoped
          @Named("stepScopedMethod")
          public FooMethodTarget getStepScopedFooMethodTarget() {
              return new FooMethodTarget();
          }
      
          @Produces
          @PartitionScoped
          @Named("partitionScopedMethod")
          public FooMethodTarget getPartitionScopedFooMethodTarget() {
              return new FooMethodTarget();
          }
      }

       

      Note that in above code snippt, @Named is used on each producer method/field to disambiguate between multiple resource producers of the same type.  The injection field in the target batch artifact class will have have the same @Named(...) annotation to denote which producer method/field to apply.  If there is only one producer field/method per java type, there is no need to use the @Named(...) in either the producer class or injection target class.