aop interception JpaRepository.findAll() is invalid - spring-data-jpa

MyRepository extends JpaRepository
my Aop Pointcut all MyRepository Method
all method is ok, except JpaRepository.findAll() method is invalid

Related

Why #ContributesAndroidInjector doesn't provide Android Framework type

I have simplified my application to get the root of the problem and here is the simplified version. I'm implementing Dagger 2 using following configuration:
AppComponent
#Component(modules = [
AndroidSupportInjectionModule::class,
ActivityBindingModule::class
])
interface AppComponent: AndroidInjector<MyApp> {
#Component.Builder
interface Builder{
#BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
}
ActivityBindingModule
#Module
abstract class ActivityBindingModule {
#ContributesAndroidInjector
abstract fun mainActivity(): MainActivity
#Module
companion object{
#JvmStatic
#Provides
fun provideString(mainActivity: MainActivity): String{
return "Tent"
}
}
}
MainActivity
class MainActivity : DaggerAppCompatActivity() {
#Inject
lateinit var string: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
println("meco simplest ${string}")
}
}
When I run the application I get the following error. What I don't understand is ContributesAndroidInjector is already providing an instace of MainActivity why Dagger still complains about it.
MainActivity cannot be provided without an #Inject constructor or an
#Provides-annotated method
EDIT for #yavor
Keep all classes as is and separate ActivityBindingModule implementation into two classes. Now you can see that instance of the MainActivity is provided and Dagger is not complaining about it.
ActivityBindingModule
#Module
abstract class ActivityBindingModule {
#ContributesAndroidInjector(modulese [StringProviderModule::class])
abstract fun mainActivity(): MainActivity
}
StringProviderModule
#Module
class StringProviderModule {
#Module
companion object{
#JvmStatic
#Provides
fun provideString(mainActivity: MainActivity): String{
return "Tent"
}
}
}
What I don't understand is ContributesAndroidInjector is already providing an instace of MainActivity why Dagger still complains about it.
ContributesAndroidInjector in docs says:
Generates an {#link AndroidInjector} for the return type of this method. The injector is implemented with a {#link dagger.Subcomponent} and will be a child of the {#link dagger.Module}'s component.
So it does not provide MainActivity.
Why do you need it actually at all? I see that you are passing it as parameter to the function:
fun provideString(mainActivity: MainActivity)
but do you really need it there? In general you should inject dependencies in MainActivity. MainActivity should use them. If both(MainActivity and the string) they know about each other it is first - not a good design, and second: you are close to create cyclic dependencies which Dagger 2 does not support and throws exception.
You probably forgot to inject your application in MyApp. You should have something like this (you might need to modify it a bit to fit your AppComponent:
DaggerAppComponent.builder()
.application(this)
.build()
.inject(this)
Also, Dagger is actually providing your MainActivity through your #ContributesAndroidInjector annotated method but that's not what you're injecting.
You're injecting a string so Dagger is using your provideString method. Since this method requires a MainActivity instance to work, Dagger is looking for such a method annotated with #Provides. You don't have any and Dagger won't look at your #ContributesAndroidInjector method since it does not have any reasons to do so.
If you want it to work, you actually have to define your provideString method in a separate module and install it inside your #ContributesAndroidInjector:
#Module
abstract class ActivityBindingModule {
#ContributesAndroidInjector(modules = [StringModule::class])
abstract fun mainActivity(): MainActivity
}
#Module
class StringModule {
#JvmStatic
#Provides
fun provideString(mainActivity: MainActivity): String = "Hehe"
}

Can I use the #Value annotated into the a class annotated as #Entity?

I have a abstract class where I would do:
#Value("${dao.value:5}")
private Integer value;
The value return null, The abstract class is annotatedas #Configurable
This class is used in several class annotated as #Entity
This is the sping boot configuration:
#SpringBootApplication
#EnableJpaRepositories("package.dao")
#ComponentScan("package.server")
#EntityScan("package.model")
#Import(LoggerRegistryClientContext.class)
#EnableSpringConfigured

autofac Register closed subclasses of abstract open generic

public class Sub1 : Base<SomeClass>
{
// for sake of getting injection to work, not injecting anything in ctor
public Sub1() {}
....
}
public class Sub2 : Base<SomeOtherClass>
{
// for sake of getting injection to work, not injecting anything in ctor
public Sub2() {}
....
}
public abstract class Base<T>
{
// abstract, so no ctor
....
}
I tried the following but I'm getting the exception listed below. Notice it the exception references the Base abstract class. What am I missing?
builder.RegisterAssemblyTypes(typeof(Base<>).Assembly)
.Where(t => t.IsSubclassOf(typeof(Base<>))).AsClosedTypesOf(typeof(Base<>)).InstancePerDependency();
No constructors on type 'Base`1[SomeClass]' can be found with the constructor finder 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'.
I think you mixed with generic and non generic abstract class registrations.
You have generic abstract class. Therefore your register should be like this:
builder.RegisterAssemblyTypes(typeof(Base<>).Assembly).AsClosedTypesOf(typeof(Base<>)).InstancePerDependency();

Dependency injection with abstract class and object in Play Framework 2.5

I'm trying to migrate from Play 2.4 to 2.5 avoiding deprecated stuff.
I had an abstract class Microservice from which I created some objects. Some functions of the Microservice class used play.api.libs.ws.WS to make HTTP requests and also play.Play.application.configuration to read the configuration.
Previously, all I needed was some imports like:
import play.api.libs.ws._
import play.api.Play.current
import play.api.libs.concurrent.Execution.Implicits.defaultContext
But now you should use dependency injection to use WS and also to use access the current Play application.
I have something like this (shortened):
abstract class Microservice(serviceName: String) {
// ...
protected lazy val serviceURL: String = play.Play.application.configuration.getString(s"microservice.$serviceName.url")
// ...and functions using WS.url()...
}
An object looks something like this (shortened):
object HelloWorldService extends Microservice("helloWorld") {
// ...
}
Unfortunately I don't understand how I get all the stuff (WS, configuration, ExecutionContect) into the abstract class to make it work.
I tried to change it to:
abstract class Microservice #Inject() (serviceName: String, ws: WSClient, configuration: play.api.Configuration)(implicit context: scala.concurrent.ExecutionContext) {
// ...
}
But this doesn't solve the problem, because now I have to change the object too, and I can't figure out how.
I tried to turn the object into a #Singleton class, like:
#Singleton
class HelloWorldService #Inject() (implicit ec: scala.concurrent.ExecutionContext) extends Microservice ("helloWorld", ws: WSClient, configuration: play.api.Configuration) { /* ... */ }
I tried all sorts of combinations, but I'm not getting anywhere and I feel I'm not really on the right track here.
Any ideas how I can use things like WS the proper way (not using deprecated methods) without making things so complicated?
This is more related to how Guice handles inheritance and you have to do exactly what you would do if you were not using Guice, which is declaring the parameters to the superclass and calling the super constructor at your child classes. Guice even suggest it at its docs:
Wherever possible, use constructor injection to create immutable objects. Immutable objects are simple, shareable, and can be composed.
Constructor injection has some limitations:
Subclasses must call super() with all dependencies. This makes constructor injection cumbersome, especially as the injected base class changes.
In pure Java, it will means doing something like this:
public abstract class Base {
private final Dependency dep;
public Base(Dependency dep) {
this.dep = dep;
}
}
public class Child extends Base {
private final AnotherDependency anotherDep;
public Child(Dependency dep, AnotherDependency anotherDep) {
super(dep); // guaranteeing that fields at superclass will be properly configured
this.anotherDep = anotherDep;
}
}
Dependency injection won't change that and you will just have to add the annotations to indicate how to inject the dependencies. In this case, since Base class is abstract, and then no instances of Base can be created, we may skip it and just annotate Child class:
public abstract class Base {
private final Dependency dep;
public Base(Dependency dep) {
this.dep = dep;
}
}
public class Child extends Base {
private final AnotherDependency anotherDep;
#Inject
public Child(Dependency dep, AnotherDependency anotherDep) {
super(dep); // guaranteeing that fields at superclass will be properly configured
this.anotherDep = anotherDep;
}
}
Translating to Scala, we will have something like this:
abstract class Base(dep: Dependency) {
// something else
}
class Child #Inject() (anotherDep: AnotherDependency, dep: Dependency) extends Base(dep) {
// something else
}
Now, we can rewrite your code to use this knowledge and avoid deprecated APIs:
abstract class Microservice(serviceName: String, configuration: Configuration, ws: WSClient) {
protected lazy val serviceURL: String = configuration.getString(s"microservice.$serviceName.url")
// ...and functions using the injected WSClient...
}
// a class instead of an object
// annotated as a Singleton
#Singleton
class HelloWorldService(configuration: Configuration, ws: WSClient)
extends Microservice("helloWorld", configuration, ws) {
// ...
}
The last point is the implicit ExecutionContext and here we have two options:
Use the default execution context, which will be play.api.libs.concurrent.Execution.Implicits.defaultContext
Use other thread pools
This depends on you, but you can easily inject an ActorSystem to lookup the dispatcher. If you decide to go with a custom thread pool, you can do something like this:
abstract class Microservice(serviceName: String, configuration: Configuration, ws: WSClient, actorSystem: ActorSystem) {
// this will be available here and at the subclass too
implicit val executionContext = actorSystem.dispatchers.lookup("my-context")
protected lazy val serviceURL: String = configuration.getString(s"microservice.$serviceName.url")
// ...and functions using the injected WSClient...
}
// a class instead of an object
// annotated as a Singleton
#Singleton
class HelloWorldService(configuration: Configuration, ws: WSClient, actorSystem: ActorSystem)
extends Microservice("helloWorld", configuration, ws, actorSystem) {
// ...
}
How to use HelloWorldService?
Now, there are two things you need to understand in order to proper inject an instance of HelloWorldService where you need it.
From where HelloWorldService gets its dependencies?
Guice docs has a good explanation about it:
Dependency Injection
Like the factory, dependency injection is just a design pattern. The core principle is to separate behaviour from dependency resolution.
The dependency injection pattern leads to code that's modular and testable, and Guice makes it easy to write. To use Guice, we first need to tell it how to map our interfaces to their implementations. This configuration is done in a Guice module, which is any Java class that implements the Module interface.
And then, Playframework declare modules for WSClient and for Configuration. Both modules gives Guice enough information about how to build these dependencies, and there are modules to describe how to build the dependencies necessary for WSClient and Configuration. Again, Guice docs has a good explanation about it:
With dependency injection, objects accept dependencies in their constructors. To construct an object, you first build its dependencies. But to build each dependency, you need its dependencies, and so on. So when you build an object, you really need to build an object graph.
In our case, for HelloWorldService, we are using constructor injection to enable Guice to set/create our object graph.
How HelloWorldService is injected?
Just like WSClient has a module to describe how an implementation is binded to an interface/trait, we can do the same for HelloWorldService. Play docs has a clear explanation about how to create and configure modules, so I won't repeat it here.
But after creating an module, to inject a HelloWorldService to your controller, you just declare it as a dependency:
class MyController #Inject() (service: Microservice) extends Controller {
def index = Action {
// access "service" here and do whatever you want
}
}
In scala,
-> If you do not want to explicitly forward all the injected parameters to the base constructor, you can do it like that :
abstract class Base {
val depOne: DependencyOne
val depTwo: DependencyTwo
// ...
}
case class Child #Inject() (param1: Int,
depOne: DependencyOne,
depTwo: DependencyTwo) extends Base {
// ...
}

Call 1 jersey resource class from another Jersey resource class with #Context ServletContext

I have Jersey resource class A calling a method in resource class B.Both classes have a #Context ServletContext servletContext at the class level. When I instantiate class B to call it from resource class A using its empty constructor, servletContext is null in the class B method being called. Is there any Jersey framework way I can call class B and yet have the servletContext retain its values/attributes from class A.
You can instantiate class B using ResourceContext. I.e. in class A you can have:
#Context private ResourceContext rc;
And then in you can instantiate resource B as follows:
B resourceB = rc.getResource(B.class);
See ResourceContext javadoc for more info.