We use a abstract classes for services like this pseudocode
abstract class AbstractApiService {
#Timed(value="get", useClassPrefix=true)
def get(Long id) {
... returns sth ....
}
#Timed(value="create", useClassPrefix=true)
def create(Map params) {
... returns sth ....
}
}
There are beans which inherit AbstractApiService and serve features like creating, deleting, updating entities like
class UserAccountService extends AbstractApiService {
... code ....
}
I would like to get metrics for each call a function from child classes like UserAccountService, but Prometheus sends events with full parent class prefix.
App is based on Grails 3.3.8
build.gradle:
compile 'com.moelholm:prometheus-spring-boot-starter:1.0.2'
compile 'io.dropwizard.metrics:metrics-core:4.0.0-alpha2'
compile 'io.dropwizard.metrics:metrics-jvm:4.0.0-alpha2'
compile 'org.grails.plugins:dropwizard-metrics:1.0.0.M2'
Unfortunately, I believe you will have to define the #Timed annotation for each method you want tracked. I don't think that the annotation code will spin up a separate metric for each concrete class.
I created a custom manual solution
https://gist.github.com/michmzr/1e03534bc5fb6df89065f6964acf9c71
Related
Gradle documentation states that using the getProject() method in the #TaskAction method of a Task class should not be used if you want compatibility with Gradle Configuration Cache. The question I have is that, suppose you have something like this:
public abstract class AbstractMyTask extends DefaultTask {
#Internal
protected abstract DirectoryProperty getRootDirectory();
protected AbstractMyTask() {
getRootDirectory().convention(getProject().getRootProject().getLayout().getProjectDirectory());
}
}
The general intent of the code snippet is to have a Directory property representing the root project directory (ie. a safe replacement for getProject().getRootDir()), and it seems like the getProject() call in the constructor would be okay. I'd like some sober second thought on whether that is the case.
I want to implement a generic service interface into multiple classes. Is this possible to do? Seems that it just picks one of the classes to inject into. I'm likely missing something with the dependency injection itself. I would like to stay away from creating a separate interface for each class if possible.
Assume that you have an interface like that:
public interface IMyService<TEntity> { ... }
and you have 2 implementations:
public class MyUserService : IMyService<User> { ... }
public class MyRoleService : IMyService<Role> { ... }
To be able to inject IMyService<User> or IMyService<Role> you should register them to DI in your module's Initialize method:
IocManager.Register<IMyService<User>, MyUserService>(DependencyLifeStyle.Transient);
IocManager.Register<IMyService<Role>, MyRoleService>(DependencyLifeStyle.Transient);
I have the following groovy class as part of my gradle plugin:
class MyClass {
final Expando someOptions
MyClass() {
someOptions = new Expando()
}
def call(Closure configure) {
configure.delegate = someOptions
configure.resolveStrategy = Closure.DELEGATE_ONLY
configure()
}
}
Now I want to user to have the ability to configure this class by adding extra properties to it, but those properties should be stored in someOptions.
I tried doing this in the class:
def call(final Closure configure) {
configure.delegate = someOptions
configure.resolveStrategy = Closure.DELEGATE_ONLY
configure()
}
The user of the plugin can do:
myClass {
hello='world'
}
However, gradle does not seem to understand that the hello property does not exist on the myClass instance but rather on someOptions within the class. Whenever I use the above, I get errors about hello not existing in the MyClass instance.
How do I do this? Is it possible?
FWIW, it works in the groovy console, but not in gradle.
Any classes you define in your plugin are not directly used in Gradle, but wrapped in proxy classes by Gradle. As an example,
Gradle will create a proxy class for the actual class implementation and adds (among other things) also a property setter method. The method has the name of the property and has a single argument of the same type as the property. It is different from the setProperty and getProperty methods already added by Groovy. For example if we have a task with a property with the name message of type String then Gradle will add the method message(String) to the proxy class. (Source)
This is the reason, why you can omit the assignment sign in Gradle scrips:
task myTask {
myProperty true // uses Gradle generated method
myProperty = true // uses Groovy generated setter
}
Gradle also adds a method similar to yours to allow the configuration of any object in the DSL:
myExtension {
// this works thanks to Gradle
}
Without this proxy method, it would be necessary to use the method with(Closure) from the Groovy language for any block:
myExtension.with {
// this works thanks to Groovy
}
It seems like this proxy method overrides the call(Closure) method of your example.
To solve this, you could use the Delegate annotation in Groovy on someOptions. This would make all its properties available to the MyClass instance. You could also register someOptions as convention on MyClass.
EDIT
You can see that your method is never called by comparing the stacktrace of your current example and a second stacktrace, after you changed the name of the call method and called it explicitly (you need to use another property to get the same exception).
I'm relatively new to Spring and I've got myself dug in a hole. I'm trying to model motor cars. Each model has it's own builder object, and I have a BuilderFactory that returns the correct builder based upon user selection from a web-app.
So I'm looking for suggestions on how to approach this problem where I need to create a number of individual vehicles, but I don't know what type of vehicle I'm going to need until run-time, and each vehicle needs to be unique to the user.
What I've got at the moment is shown below. The problem I have at the moment is that because the individual builders are singletons so are the individual vehicles. I need them
to be prototypes. I know it all looks pretty horrible so I'm sure there must be a better way of doing this.
The top level from the web-app looks like;
Vehicle vehicle = vehicleBuilderFactory.getBuilder(platform).build();
My vehicleBuilderFactory looks like this;
#Service
public class VehicleBuilderFactory {
#Autowired
Discovery3Builder discovery3Builder;
#Autowired
Discovery4Builder discovery4Builder;
// Lots of #Autowired statements here.
#Autowired
FreeLander2010Builder freeLander2010Builder;
public VehicleBuilder getBuilder(Platform platform) {
switch (platform.getId()) {
case 1: return discovery3Builder;
case 2: return discovery4Builder;
// Lots of case statements here
case 44: return freeLander2010Builder;
default: return null;
}
}
}
which itself looks pretty horrible. Each individual builder looks like;
#Service
public class DefenderBuilder implements VehicleBuilder {
#Autowired
Defender defender;
// Loads of Defender specific setters ommitted
#Override
public Vehicle build() {
return defender;
}
}
and finally the individual vehicle
#Service
#Scope("prototype")
public class Defender extends Vehicle {
}
The main problem now, is that because the builders are singletons, so are the vehicles, and
I need them to be prototypes, because User A's Defender is different to user B's Defender.
You can use Spring's ObjectFactory to have it service up prototype scoped beans from a singleton scoped bean. The usage is pretty straightforward:
#Component
class DefenderBuilder implement VechicleBuilder {
#Autowired
ObjectFactory<Defender> defenderFactory;
Defender build() {
return defenderFactory.getObject()
}
}
#Component
#Scope("prototype")
class Defender {
}
This returns a new Defender on each call to defenderFactory.getObject()
Without reading too much into the detail you say you want to produce Prototype beans from a singleton possibly with a look up in the IoC container.
Section 3.4.6.1 Lookup method injection of the Spring documentation describes how this can be done without losing the Inversion of Control i.e. without your beans knowing about the bean store.
I have made use of the ServiceLocatorFactoryBean to solve a similar problem before. The class level Javadoc is excellent and contains some clear examples.
Two things:
1) You can use proxy in order to hold narrower scope from wider scope(e.g prototype from singleton)
All you need is to define the prototype component with the relevant scope and proxyMode
You can read about scoped proxy here.
2) Another thing that I have noticed is that you plan to use multiple autowired annotation.
note that you can use autowire on a list of interface and it will autowire all components that implements this interface as discussed here.
Moreover you can add a platform id to the VehicleBuilder interface and then generate a map in the constructor e.g:
Map<Integer, VehicleBuilder> vehicleBuilders;
#Autowired
public VehicleBuilderFactory(List<VehicleBuilder> vehicleBuilders) {
this.vehicleBuilders = vehicleBuilders.stream()
.collect(Collectors(x -> x.getPlatformId(), x -> x));
}
in that way you can avoid the switch case.
I wanted to instrument a large number of classes to use with Spring Insight and instead of adding the #InsightOperation manually to the methods, I wrote an aspect to annotate the methods using point cuts.
However, this is not working. While the manual annotation affects the Spring Insight trace logging, the AspectJ method does not work.
Is there anything I am doing wrong here? (I decompiled the classes after aspectizing and do find the annotation in the class methods)
This is the aspect code snippet:
declare #method :public * com.example.IExample.execute(..) : #InsightOperation;
Spring documentation says this:
Use of the #Insight* annotations are
optional. They make it easy for end
users to define custom operation
frames and end points without needing
to create a plug-in. Because end user
code modification is required to use
the annotations, they are an option
for users who cannot or do not wish to
write aspects.
http://static.springsource.com/projects/tc-server/2.5/devedition/htmlsingle/devedition.html
So looks like the only way is to write a custom plugin
http://static.springsource.com/projects/tc-server/2.5/devedition/htmlsingle/devedition.html#tutorial-plugin
It is possible that the Insight LTW does not pick up your introduced annotations. I'll have to dig deeper on that.
In the meantime, you can try a more low-level annotation:
com.springsource.insight.collection.method.MethodOperationsCollected
If you look at the spring-core plugin, you will see that it does something similar:
public aspect RepositoryMethodOperationCollectionAspect {
declare #type: #Repository * : #MethodOperationsCollected;
}
An easy work around is to call another method from within your aspect method to continue executing the join point. I only tried calling a static method in a static class. See below my code for adding the #InsightOperation to all my JSON serialization.
My aspect:
#Aspect
public class JSONSerializerAspect {
#Around("call(* *.JSONSerializer.serialize(..)) && args(target)")
public Object serialize(ProceedingJoinPoint joinPoint, Object target) throws Throwable {
return JSONSerializationWrapper.serialize(joinPoint, target);
}
}
The static class it is calling:
public class JSONSerializationWrapper {
#InsightOperation(label = "JSON_SERIALIZATION")
public static Object serialize(ProceedingJoinPoint joinPoint, Object target) throws Throwable {
return joinPoint.proceed(new Object[]{target});
}
}
I'm using this myself and tested that it works.