Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Possibility to use a certain environment by a Qualifier #73

Closed
Juchar opened this issue Oct 5, 2017 · 6 comments
Closed

Possibility to use a certain environment by a Qualifier #73

Juchar opened this issue Oct 5, 2017 · 6 comments

Comments

@Juchar
Copy link

Juchar commented Oct 5, 2017

Feature Request

It would be great to be able to use a specified environment by using a custom qualifier.

Currently I have to implement a @Named producer for each environment I want to use.
It would be much easier to have something like that:

@Inject 
@Environment("env")
UserMapper userMapper;

I do not know if it is feasable.

I already tried to implement something like that by using a custom annotation:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Environment {

  /**
   * Environment identifier
   */
  @Nonbinding String value() default "";

}

And an according producer:

@Produces
@Environment
public SqlSessionFactory produceEnvironmentFactory(InjectionPoint ip)
  throws Exception {
  Environment environment = ip.getAnnotated().getAnnotation(Environment.class);
  return produceFactory(environment.value());
}

But that did not work due to the fact that you can't provide an @ApplicationScoped producer with a relation to an injection point.

And second problem is that MyBatis CDI creates instances without injection point and therefore I cant reference it.

@mnesarco
Copy link
Member

mnesarco commented Oct 6, 2017

HI @Juchar
How many environments do you have in your App?

In terms of mapper injection, this:

@Inject 
@Environment("env1")
UserMapper userMapper;

Is not so different from this:

@Inject 
@Named("env1")
UserMapper userMapper;

And in terms of the producer, this is not a big deal:

@Produces
@Named("env1")
@SessionFactoryProvider
public SqlSessionFactory produceFactory1() {
  return produceFactory("env1");
}

@Produces
@Named("env2")
@SessionFactoryProvider
public SqlSessionFactory produceFactory2() {
  return produceFactory("env2");
}

You can also use your own Qualifier annotation, as soon as you use a producer method per Environment.

I don't know your implementation details but I suppose there are few environments. But if you have so many environments (something like more than 10) then it is a different story, but Environments are static anyway so I don't see the use case but please elaborate more to continue the discussion.

Thanks.

@mnesarco
Copy link
Member

@hazendaz what do you think about this issue?

@hazendaz
Copy link
Member

Not sure the benefit here. I generally have my environmental information separated from the code so I'm basically only injecting in what I actually need for any given environment with a system property to tell me what specific file to read and use. That may not be entirely cloud ready solution but not sure about using it in this way. Unfortunately I have not gotten far enough at my day job to finally start using mybatis-cdi over our home grown solution due to changing priorities and the code being given off to another team I only occassionally get to help. I might have a better opinion in a couple months given I've recently been pulled back in a bit.

@hazendaz
Copy link
Member

And I must says the added backwards compatibility that is now present which was the primary holdup on switching over sooner.

@Juchar
Copy link
Author

Juchar commented Oct 19, 2017

I will give a little bit more detailed information about the use case I have, maybe it's more easy to understand.

We have a project that consists of several sub-projects, possibly all connecting to different environments (so not Prod, Dev, Test, etc.).

As we wanted simplify the handling we thought about a determined place to put the different configuration.xml files inside the classpath.

We then merge those to a big configuration.xml and let the application inject the according mappers by just using a qualifier with their environment as an argument (e.g. @Environment("ABC")).

That way it is not needed that an application provides an own producer and the configuration handling would be centralized at a single point.

This would be quite easy by using a @NonBindinding field inside the qualifier and use the InjectionPoint as a method parameter of the producer.

The big problem we faced is that mybatis already registers various mapper beans at startup and we can't access the injection point and therefore not use the qualifiers parameter inside the producer that constructs the session factory.

@mnesarco
Copy link
Member

mnesarco commented Apr 9, 2018

Hi @Juchar , I am sorry. This feature won't be included any time soon. Y Suggest you to create a fork and do some experiments, then if you want you can contribute any enhancement via a PR.

@mnesarco mnesarco closed this as completed Apr 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants