i have refreshscope bean with a constructor which is calling x method which will be invoked on initialization by spring.
Upon /actuator/refresh, this bean is getting detached. on next first request to x method the bean is getting initialized which in turn causing x method to run again. is there any way to resolve it (without duplicating x method by different names).
Related
I have a method in an #Aspect service method called logChangesAndAnnounceNewContributions that fires whenever somewhere in the webapp the save method of Spring-data's JpaRepository is called. I don't want the logChanges method to be called when the save method is used within the Aspect class itself, so i used this in the pointcut definition !within(Services.SystemListenerService). But its not having any effect! The save method is still being called despite using this condition in the definition. The full definition looks like this:
#AfterReturning("execution(* org.springframework.data.jpa.repository.JpaRepository.save(..))" +
"&& !within(Services.SystemListenerService) && args(entity)")
private void logChangesAndAnnounceNewContributions(Object entity){
What am i missing here?
EDIT: I tried changing !within content to !within(#org.aspectj.lang.annotation.Aspect *) but that doesn't work either..
Assuming that Services.SystemListenerService is the fully qualified name of your aspect (class name SystemListenerService, package name Services with strange upper-case first letter), within() does not work because at the time of execution(* org.springframework.data.jpa.repository.JpaRepository.save(..)) we are not within(Services.SystemListenerService) anyway but rather within(org.springframework.data.jpa.repository.JpaRepository). So there is the logical error in your pointcut.
There are ways to solve this in AspectJ, such as
call(A) && !adviceexecution(),
execution(A) && !cflow(execution(B)),
but both pointcut types are unsupported in Spring AOP. So you
either need to activate full AspectJ via LTW in Spring
or abuse some Spring methods in order to get the real object underneath the proxy via ((Advised) myProxy).getTargetSource().getTarget() and call the method directly on that object from your aspect
or obtain a stack trace from a newly created exception or from the current thread and inspect it manually - very ugly.
Sorry, but Spring AOP is just "AOP lite", I think you should go for AspectJ. The second option is also a bit hacky but will probably work.
https://github.com/scala/scala/blob/2.11.x/src/library/scala/Predef.scala#L230
??? in scala is a function defined in predef that throws a NotImplementedError
In my project I am using Google Guice in order to inject dependencies, and thought it would be good to have a similar function that throws an exception if the injection never happened, in order to catch missing usages of the injector or missing #Inject annotations.
In my project I have a class that is expecting to be injected
class OScoreboard {
#Inject
val source :Provider[ScoreboardBuilder] = injected;
}
and an object
class ExpectedInjectionException(message: String = null, cause: Throwable = null) extends RuntimeException
object injected extends Nothing{
def apply : Nothing = {
throw new ExpectedInjectionException("Expected an injection")
}
}
But I get the error that injected isn't of type Provider[ScoreboardBuilder]
Am I abusing apply? How else can I reference the scala function apply (or even with a different name) without referencing the object injected?
Also I suspect that even if I fix this error, the function will be eagerly run causing the exception before injection happens, does that mean I need to make every injected field lazy, or is there another solution?
Edit:
The problem was my understanding of Scala.
vals are eagerly computed, so the ???-like function is immediately executed on class construction (which since it's using field injection, occurs immediately before injection happens) causing the field to never be injected.
Values like final fields in Java CAN be injected, because it's only a restriction by the byte code verifier. final fields can be written to fine by using reflection (which Guice does).
In order to answer this question there needs to be a way to delay the execution of the ???-like function/value until the field is first read. I'm unsure how, or if it is even possible. The other option is just to initialize them to null. But that will result in NullPointerExceptions which are famously unhelpful. I was hoping to use a null-like error with an explanation that the injection failed.
First of all: in one place you wrote INJECTED and in the other place injected. I'll assume this was a typo and that you mean the same thing with both.
An assignment like this:
val source :Provider[ScoreboardBuilder] = INJECTED;
will not work because you are trying to assign the object INJECTED to a variable of type Provider[ScoreboardBuilder]. The object is not of that type, so you can't do that assignment.
Maybe you expected that the object would behave like a function and that its apply method would automatically be called, but that's not how it works.
You can define INJECTED as a method inside your class:
class OScoreboard {
#Inject
val source :Provider[ScoreboardBuilder] = INJECTED
private def INJECTED : Nothing =
throw new ExpectedInjectionException("Expected an injection")
}
Or you can put it in a separate object, but then you'd have to import it in your class:
object injected {
def INJECTED : Nothing =
throw new ExpectedInjectionException("Expected an injection")
}
class OScoreboard {
import injected._
#Inject
val source :Provider[ScoreboardBuilder] = INJECTED
}
The problem was my understanding of Scala.
vals are eagerly computed, so the ??? function is immediately executed on class construction (which since it's using field injection, occurs immediately before injection happens) causing the exception to be thrown.
Making it lazy results in the injection happening using reflection without the exception being thrown on construction. HOWEVER the generated Java code is not aware that this happens. So when the injected value is accessed for the first time, the generated code replaces the injected reference with ??? then proceeds to throw the exception.
There is no way that I can see in order to make this work.
How can I add interceptor to an interface registration so that it is executed when I call a method from resolved instance (IoC.Resolve) but not when I use an instance that has been injected (as constructor argument) from the inside of my class/object?
In our infrastructure we add an interceptor that opens/closes nhibernate session for every call but then the injected proxy instance will open a session inside of a session and cause deadlocks if you query the same entity in outer and inner session.
I've had a look at this and I don't see any easy way to change the behavior of the interceptor depending on the context in which it is called.
What you could do is create an interceptor that wraps a component with a singleton lifetime that creates a single session and returns the same session while it is not closed. When trying to create a second session, it returns the initial session and increments a sessionCreated counter. When trying to close a session it decrements the sessionCreated counter and only closes it if it is 0
I am having a problem while persisting a class. I have a class called Scraper which uses an interface called Paginator. There are several implementations of the Paginator interface which will be instantiated at runtime. So the structure looks like this:
class Scraper {
//some code
Paginator paginator
//more code
def Scraper(Paginator paginator){
this.paginator = paginator
}
}
and then there are the concrete implementations of the paginator interface lets say paginatorA and paginatorB. So now I am trying to do the following:
PaginatorA p = new PaginatorA()
Scraper s = new Scaper(p)
s.save(flush:true)
...and what it get is:
Error Error executing script TestApp:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoDatastore': Cannot resolve reference to bean 'mongoMappingContext' while setting bean property 'mappingContext';
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoMappingContext': FactoryBean threw exception on object creation; nested exception is java.lang.NullPointerException (Use --stacktrace to see the full trace)
Can anybody tell me what to make of this? I guess it has something to do with the Mapper because it doesn't know which concrete Paginator to use or how to persist it? If that is the case then how can I tell the framework what to do? I tried to come up with a solution for hours now and am really frustrated so any help would be really really appreciated.
Oh btw I also tried implementing against the concrete implementation (PaginatorA) ... this works perfectly fine since my assumption that it has something to do with the paginator interface.
Thanks for any response...
The error is bad, you should probably raise a JIRA issue for that, but fundamentally there are 2 problems I can see with the code:
Your persistent classes must have a public no-args constructor as per any JavaBean, by adding a constructor that takes your interface, you are no longer providing one
Your Scraper class needs to mark the 'Paginator' as transient to tell the persistence engine not to attempt to persist the 'paginator' property. Since this a custom interface it will not know how to persist it.
I have a stateless bean resposible for persisting entities to a database. This stateless bean is called by a message bean's onMessage method. The wired thing is that on the first message everything works fine, but on the next message the method responsible for persisting is invoked outside a transaction, even though the method is annotated with REQUIRES_NEW.
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public StateChange persistChange(long deviceId, ...) {
...
StateChange change = new StateChange(...);
em.persist(change);
em.refresh(change); // To provoke the error
return change;
}
Calling refresh triggers the following exception:
Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
Any ideas? I'm fairly new to JTA so I might have missed something important?
I tried a lot to solve it and after about 16 hours or so it seems to be working. I'm not sure exactly what did the trick, but it might be the upgrade to Glassfish 2.1.
Finally able to sleep at night again!