I cannot access exploits property in domain class - Scenario , from my java class - MatchScenario , located in Grails src folder.
Already tried :
Explicit methods :
I have tried explicitly creating the get;set; but I get stackOverflow error since the setExploits() is called infinitely by itself for some reason.
Service to return the exploit field,
Though the service was created, it's never called on my fork-debug integration testing, so tests hangs with no exception
compilation error ->
Error:(59, 44) java: cannot find symbol
symbol: variable exploits
location: variable scenario of type core.Scenario
Java class, error on the inner loop ->
public class MatchScenario implements Callable{
private static final Logger LOG = Logger.getLogger(MatchScenario.class.getCanonicalName());
private List<Scenario> scenarioList
#Override
public List<Scenario> call() throws Exception {
LOG.debug( "*********************** schedule matcher called *****************************" );
if (scenarioList==null) {
LOG.debug("scenarioList not initialized ");
return null;
}
List<Scenario> scenarioAvailable = new ArrayList<Scenario>();
for (Scenario scenario : scenarioList){
for (Exploit exploit : scenario.exploits){
//println 'exploit -> '+exploit
if (!match( exploit.getExpression() ) ){
break;
}
}
//happens only when all scenario are available ( no break issued )
scenarioAvailable.add(scenario);
}
return scenarioAvailable;
}
private boolean match(String expression) {
return true;
}
}
Scenario domain object ->
package core
class Scenario {
String name
static belongsTo = [ Exploit ]
static hasMany = [ exploits : Exploit ]
static constraints = {
name nullable: false , maxSize: 32
}
}
You're confusing fields and properties. When you declare a property in a Groovy class, e.g. String name, the Groovy compiler converts that to a private field and adds a getter and a setter (unless you already defined one or both of them - it won't overwrite), in this case something like
private String name
public void setName(String name) { this.name = name }
public String getName() { return name }
It only does this if there's no scope modifier, so public String name and protected String name would both stay as defined.
One benefit of this is that you can later add logic to the getter and/or setter to modify the value, do some validation checks or computations, etc., and in Groovy you would still read and write to the name property since property access always calls the underlying setters and getters, and since properties like this are a Groovy-only thing that Java can't access, you would have been calling the setter and getter from Java all along, so you wouldn't need to recompile the Java classes that used the class.
Declaring a hasMany like yours creates an exploits property, effectively
Set<Exploit> exploits
and that property (added by a Grails AST transformation) is likewise converted to a private field with a getter and setter. So to get this working from Java, use the getter:
for (Exploit exploit : scenario.getExploits()) {
Related
I'm having a problem where the related table id fields return 'null' from my domain objects when using inheritance. Here is an example:
In /src/groovy/
BaseClass1.groovy
class BaseClass1 {
Long id
static mapping = {
tablePerConcreteClass true
}
}
BaseClass2.groovy
class BaseClass2 extends BaseClass1 {
String someOtherProperty
static constraints = {
someOtherProperty(maxSize:200)
}
static mapping = BaseClass1.mapping
}
In /grails-app/domain
ParentClass.groovy
class ParentClass extends BaseClass2 {
ChildClass myChild
static mapping = BaseClass2.mapping << {
version false
}
}
ChildClass.groovy
class ChildClass extends BaseClass1 {
String property
static mapping = BaseClass1.mapping
}
The problem appears here:
SomeotherCode.groovy
print parentClassInstance.myChild.id // returns the value
print parentClassInstance.myChildId // returns null
Any ideas what might be going on to get those dynamic properties to break like this?
After debugging into the get(AssociationName)Id source, I found the following:
The handler for this is:
GrailsDomainConfigurationUtil.getAssociationIdentifier(Object target, String propertyName,
GrailsDomainClass referencedDomainClass) {
String getterName = GrailsClassUtils.getGetterName(propertyName);
try {
Method m = target.getClass().getMethod(getterName, EMPTY_CLASS_ARRAY);
Object value = m.invoke(target);
if (value != null && referencedDomainClass != null) {
String identifierGetter = GrailsClassUtils.getGetterName(referencedDomainClass.getIdentifier().getName());
m = value.getClass().getDeclaredMethod(identifierGetter, EMPTY_CLASS_ARRAY);
return (Serializable)m.invoke(value);
}
}
catch (NoSuchMethodException e) {
// ignore
}
catch (IllegalAccessException e) {
// ignore
}
catch (InvocationTargetException e) {
// ignore
}
return null;
}
It threw an exception on the related class (value.getClass().getDeclaredMethod), saying NoSuchMethod for the method getId(). I was unable to remove the id declaration from the base class without Grails complaining that an identifier column was required. I tried marking id as public and it also complained that it wasn't there. So, I tried this
BaseClass {
Long id
public Long getId() { return this.#id }
}
and things worked on some classes, but not on others.
When I removed the ID declaration, I go an error: "Identity property not found, but required in domain class". On a whim, I tried adding #Entity to the concrete classes and viola! everything started working.
class BaseClass {
//Don't declare id!
}
#Entity
class ParentClass {}
#Entity
class ChildClass {}
I still think it is a grails bug that it needs to be added, but at least it is easy enough to work around.
I'm not sure why you are seeing this behavior, but I'm also not sure why you are doing some of the things you are doing here. Why have a domain class extend a POGO? Domains, Controllers, and Services are heavily managed by the Grails machinery, which probably was not designed for this sort of use. Specifically, I believe Grails builds the dynamic property getters for the GrailsDomainProperty(s) of GrailsDomainClass(es), not POGO's. In this case, you have an explicitly declared id field in BaseClass1 that is not a GrailsDomainProperty. I suspect that this POGO id property is not picked up by the Grails machinery that creates the dynamic property getters for Domains.
You might try putting BaseClass1/2 in /grails-app/domain, perhaps making them abstract if you don't want them instantiated, then extending them as you are and seeing if you observe the behavior you want.
Following on from this question I would like autofac to inject the type of the declaring object into the constructor of my NLog service, so that it can correctly log which type is logging entries.
My NLogService class looks like this...
public class NLogService : ILogService
{
private readonly Logger _logger;
public NLogService(Type t)
{
var consumerType = t.DeclaringType.FullName;
_logger = LogManager.GetLogger(consumerType);
}
However it fails on app startup because it obviously cannot work out what to inject into the constructor of the NLogService with the following error...
None of the constructors found with
'Public binding flags' on type
'MyProduct.Domain.Services.Logging.NLogService'
can be invoked with the available
services and parameters: Cannot
resolve parameter 'System.Type t' of
constructor 'Void .ctor(System.Type)'.
So, my question is - how do i instruct autofac to inject the type of the calling class?
I tried this...
public NLogService(Type t)
{
var method = MethodBase.GetCurrentMethod();
Type consumingType = method.DeclaringType;
var consumerType = consumingType.FullName;
var consumerType = t.DeclaringType.FullName;
_logger = LogManager.GetLogger(consumerType);
}
But i just end up with MyProduct.Domain.Services.Logging.NLogService
What i want is the type of the class that is doing the actual logging.
i have already tried this suggestion and it didnt work for me either.
Could make your NLogService generic, i.e. NLogService<T> and use Autofac's open generics support?
Then you could do this:
public class NLogService<T> : ILogger<T>
{
private readonly Logger _logger;
public NLogService()
{
_logger = LogManager.GetLogger(typeof(T).FullName);
}
}
There is no real good way to do this with Autofac, because does not have support for 'context based injection' (which is what you are trying to do). There is a workaround, but it aint pretty...
What you can do is revert to property injection and define a base class or interface for that ILogService property. For instance, you can define the following interface:
public interface ILoggerContainer
{
public ILogService Logger { get; set; }
}
Now you can implement this interface on all types that need a logger:
public class Consumer : IConsumer, ILoggerContainer
{
public ILogService Logger { get; set; }
}
With this in place you can configure Autofac as follows:
builder.RegisterType<ILoggerContainer>()
.OnActivating(e =>
{
var type = typeof(LogService<>)
.MakeGenericType(e.Instance.GetType());
e.Instance.Logger = e.Context.Resolve(type);
});
Another workaround, that you may find cleaner is to inject an ILogger<T> with the same type as the type of the parent type:
public class Consumer : IConsumer
{
public Consumer(ILogger<Consumer> logger) { }
}
This makes the configuration much easier and prevents you from having to have a base class. Which one is most appropriate is up to you.
As I said, these are workarounds, but to be honest, you might need to reconsider your logging strategy in your application. Perhaps you are logging at too many places. In the applications I write there is hardly ever a need to log, and when I do, I write an logging message that is expressive enough so that there is no need to communicate the type that triggered the event. And when you log exception, you will always have a complete stack trace (and exception logging should almost only happen in the outer layer of your application and not within services anyway).
The following technique works well in our experience:
Create an attribute like below, which can be applied at class level or at the injection site:
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class)]
public class LoggerAttribute : Attribute
{
public readonly string Name;
public LoggerAttribute(string name)
{
Name = name;
}
}
Create an Autofac module that you register with the ContainerBuilder:
public class LogInjectionModule : Module
{
protected override void AttachToComponentRegistration(IComponentRegistry registry, IComponentRegistration registration)
{
registration.Preparing += OnComponentPreparing;
}
static void OnComponentPreparing(object sender, PreparingEventArgs e)
{
var typePreparing = e.Component.Activator.LimitType;
// By default, the name supplied to the logging instance is the name of the type in which it is being injected into.
string loggerName = typePreparing.FullName;
//If there is a class-level logger attribute, then promote its supplied name value instead as the logger name to use.
var loggerAttribute = (LoggerAttribute)typePreparing.GetCustomAttributes(typeof(LoggerAttribute), true).FirstOrDefault();
if (loggerAttribute != null)
{
loggerName = loggerAttribute.Name;
}
e.Parameters = e.Parameters.Union(new Parameter[]
{
new ResolvedParameter(
(p, i) => p.ParameterType == typeof (Logger),
(p, i) =>
{
// If the parameter being injected has its own logger attribute, then promote its name value instead as the logger name to use.
loggerAttribute = (LoggerAttribute)
p.GetCustomAttributes(typeof(LoggerAttribute),true).FirstOrDefault();
if (loggerAttribute != null)
{
loggerName = loggerAttribute.Name;
}
// Return a new Logger instance for injection, parameterised with the most appropriate name which we have determined above.
return LogManager.GetLogger(loggerName);
}),
// Always make an unamed instance of Logger available for use in delegate-based registration e.g.: Register((c,p) => new Foo(p.TypedAs<Logger>())
new TypedParameter(typeof(Logger), LogManager.GetLogger(loggerName))
});
}
}
You can now inject a named Logger in any one of these ways depending on individual scenarios:
By default, the injected logger name will be given the full type name of the class it is injected into:
public class Foo
{
public Foo(Logger logger)
{
}
}
Use a constructor parameter [Logger] attribute to override the logger name:
public class Foo
{
public Foo([Logger("Meaningful Name")]Logger logger)
{
}
}
Use a class-level [Logger] attribute to set the same logger name override for all constructor overloads:
[Logger("Meaningful Name")]
public class Foo
{
public Foo(Logger logger, int something)
{
}
public Foo(Logger logger, int something, DateTime somethingElse)
{
}
}
Use constructor parameter [Logger] attributes on each constructor overload to set different logger names depending on the context of how you were constructed:
public class Foo
{
public Foo(Logger("Meaningful Name")]Logger logger, int something)
{
}
public Foo(Logger("Different Name")]Logger logger, int something, DateTime somethingElse)
{
}
}
IMPORTANT NOTE: If you register types to be resolved with logger constructor injection using Autofac's delegate registration, you MUST use the two parameter overload like so: Register((c,p) => new Foo(p.TypedAs<Logger>()).
Hope this helps!
It is possible to do this without generics.
However, please note that in Autofac 6.x, the resolution process has changed to use a resolve pipeline. This doesn't matter for most scenarios, but it does when you want to use the lifetime events like OnPreparing, etc. Most of the answers here on SO around overriding the Preparing event are very old and are now outdated. You can't override Preparing directly anymore.
There is an example on the Autofac documentation site doing this for log4net, and it works with NLog with only minor changes. Here is the basic idea:
public class Log4NetMiddleware : IResolveMiddleware
{
public PipelinePhase Phase => PipelinePhase.ParameterSelection;
public void Execute(ResolveRequestContext context, Action<ResolveRequestContext> next)
{
// Add our parameters.
context.ChangeParameters(context.Parameters.Union(
new[]
{
new ResolvedParameter(
(p, i) => p.ParameterType == typeof(ILog),
(p, i) => LogManager.GetLogger(p.Member.DeclaringType)
),
}));
// Continue the resolve.
next(context);
// Has an instance been activated?
if (context.NewInstanceActivated)
{
var instanceType = context.Instance.GetType();
// Get all the injectable properties to set.
// If you wanted to ensure the properties were only UNSET properties,
// here's where you'd do it.
var properties = instanceType
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.PropertyType == typeof(ILog) && p.CanWrite && p.GetIndexParameters().Length == 0);
// Set the properties located.
foreach (var propToSet in properties)
{
propToSet.SetValue(context.Instance, LogManager.GetLogger(instanceType), null);
}
}
}
}
Please also note that you have to understand how middleware works in Autofac. The documentation is a good place to start.
I'm trying to do some attribute-based interception using structuremap but I'm struggling to tie up the last loose ends.
I have a custom Registry that scans my assemblies and in this Registry I have defined the following ITypeInterceptor whose purpose it is to match types decorated with the given attribute and then apply the interceptor if matched. The class is defined as such:
public class AttributeMatchTypeInterceptor<TAttribute, TInterceptor>
: TypeInterceptor
where TAttribute : Attribute
where TInterceptor : IInterceptor
{
private readonly ProxyGenerator m_proxyGeneration = new ProxyGenerator();
public object Process(object target, IContext context)
{
return m_proxyGeneration.CreateInterfaceProxyWithTarget(target, ObjectFactory.GetInstance<TInterceptor>());
}
public bool MatchesType(Type type)
{
return type.GetCustomAttributes(typeof (TAttribute), true).Length > 0;
}
}
//Usage
[Transactional]
public class OrderProcessor : IOrderProcessor{
}
...
public class MyRegistry : Registry{
public MyRegistry()
{
RegisterInterceptor(
new AttributeMatchTypeInterceptor<TransactionalAttribute, TransactionInterceptor>());
...
}
}
I'm using DynamicProxy from the Castle.Core to create the interceptors, but my problem is that the object returned from the CreateInterfaceProxyWithTarget(...) call does not implement the interface that triggered the creation of the target instance in structuremap (i.e IOrderProcessor in example above). I was hoping that the IContext parameter would reveal this interface, but I can only seem to get a hold of the concrete type (i.e. OrderProcessor in example above).
I'm looking for guidance on how to have this scenario work, either by calling the ProxyGenerator to return an instance that implements all interfaces as the target instance, by obtaining the requested interface from structuremap or through some other mechanism.
I actually got something working with a slight caveat so I'll just post this as the answer. The trick was to obtain the interface and pass that into the CreateInterfaceProxyWithTarget. My only problem was that I could not find a way to query the IContext about which interface it was currently resolving so I ended up just looking up the first interface on the target which worked for me. See code below
public class AttributeMatchTypeInterceptor<TAttribute, TInterceptor> :
TypeInterceptor
where TAttribute : Attribute
where TInterceptor : IInterceptor
{
private readonly ProxyGenerator m_proxyGeneration = new ProxyGenerator();
public object Process(object target, IContext context)
{
//NOTE: can't query IContext for actual interface
Type interfaceType = target.GetType().GetInterfaces().First();
return m_proxyGeneration.CreateInterfaceProxyWithTarget(
interfaceType,
target,
ObjectFactory.GetInstance<TInterceptor>());
}
public bool MatchesType(Type type)
{
return type.GetCustomAttributes(typeof (TAttribute), true).Length > 0;
}
}
Hope this helps someone
Sometimes I have classes which need to get some information for construction. I am not talking about references to other objects (which will be injected) but about (for instance) strings which are holding unique information:
// Scoped as singleton!
class Repository
{
public Repository( InjectedObject injectedObject, string path ) { ... }
}
How do you get this string injected? One possiblity is to write an Init() method and to avoid injection for the string:
class Repository
{
public Repository( InjectedObject injectedObject ) { ... }
public void Init( string path ) { ... }
}
Another possibility is to wrap the information into an object, which can be injected:
class InjectedRepositoryPath
{
public InjectedRepositoryPath( string path ) { ... }
public string Path { get; private set; }
}
class Repository
{
public Repository( InjectedObject injectedObject, InjectedRepositoryPath path ) { ... }
}
This way I'd have to create an instance of InjectedRepositoryPath during the initialisation of my DI-Container and register this instance. But I need such an unique configuration object for every similar class.
Of course I can resolve a RepositryFactory instead of the Repository object, so the factory would ask me for the path:
class RepositoryFactory
{
Repository Create( string path ) { ... }
}
But again, this is one factory just for a singleton object ...
Or, finally, since the path will be extracted from a configuration file, I could skip passing around the string and read the config in my constructor (which is probably not as optimal, but possible):
class Repository
{
public Repository( InjectedObject injectedObject )
{
// Read the path from app's config
}
}
What's your favorite method? For non-singleton classes you have to use imho the Init() or factory solution, but what about singleton-scoped objects?
If you are using Constructor injection I find adding a parameter which is your configuration object to the constructor is the best way. By using an init function you are somewhat sidestepping the point of constructor injection. This makes testing harder, it also makes maintenance and delivery more difficult.
Discovery becomes a problem because it is not readily apparent that this class requires a configuration object. By adding it to the constructor anyone using this object knows explicitly that this configuration must be there.
I prefer not having a DI Container dictate my API design. The container should conform to proper design, not the other way around.
Design your classes in a DI-friendly manner, but without making concessions to your DI Container. If you need a connection string, then take a string through the constructor:
public class Repository : IRepository
{
public Repository(string path) { //... }
}
Many DI Containers can deal with primitive values. As an example, here's one way to do it with Windsor:
container.Register(Component.For<IRepository>()
.ImplementedBy<Repository>()
.DependsOn( new { path = "myPath" } ));
However, if your container of choice can't deal with primitive parameters, you can always decorate Repository with an implementation that knows how to find the string:
public class ConfiguredRepository : IRepository
{
private readonly Repository decoratedRepository;
public ConfiguredRepository()
{
string path = // get the path from config, or whereever appropriate
this.decoratedRepository = new Repository(path);
}
// Implement the rest of IRepository by
// delegating to this.decoratedRepository
}
Now you can simply tell your container to map IRepository to ConfiguredRepository, while still keeping the core Repository implementation clean.
I'm new to Guice and here is a naive question. I learned that we could bind String to a particular value through:
bind(String.class)
.annotatedWith(Names.named("JDBC URL"))
.toInstance("jdbc:mysql://localhost/pizza");
But what if I want to bind String to any possible characters?
Or I think it could be described this way:
How can I replace "new SomeClass(String strParameter)" with Guice?
You first need to annotate the constructor for SomeClass:
class SomeClass {
#Inject
SomeClass(#Named("JDBC URL") String jdbcUrl) {
this.jdbcUrl = jdbcUrl;
}
}
I prefer to use custom annotations, like this:
class SomeClass {
#Inject
SomeClass(#JdbcUrl String jdbcUrl) {
this.jdbcUrl = jdbcUrl;
}
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.PARAMETER})
#BindingAnnotation
public #interface JdbcUrl {}
}
Then you need to provide a binding in your Module:
public class SomeModule extends AbstractModule {
private final String jdbcUrl; // set in constructor
protected void configure() {
bindConstant().annotatedWith(SomeClass.JdbcUrl.class).to(jdbcUrl);
}
}
Then an time Guice creates SomeClass, it will inject the parameter. For instance, if SomeOtherClass depends on SomeClass:
class SomeOtherClass {
#Inject
SomeOtherClass(SomeClass someClass) {
this.someClass = someClass;
}
Often, when you think you want to inject a String, you want to inject an object. For instance, if the String is a URL, I often inject a URI with a binding annotation.
This all assumes there is some constant value you can define at module creation time for the String. If the value isn't available at module creation time, you can use AssistedInject.
This might be off-topic, but Guice makes configuration much easier than writing an explicit binding for every String you need. You can just have a config file for them:
Properties configProps = Properties.load(getClass().getClassLoader().getResourceAsStream("myconfig.properties");
Names.bindProperties(binder(), configProps);
and voilĂ all your config is ready for injection:
#Provides // use this to have nice creation methods in modules
public Connection getDBConnection(#Named("dbConnection") String connectionStr,
#Named("dbUser") String user,
#Named("dbPw") String pw,) {
return DriverManager.getConnection(connectionStr, user, pw);
}
Now just create your Java properties file myconfig.properties at the root of your classpath with
dbConnection = jdbc:mysql://localhost/test
dbUser = username
dbPw = password
or merge authorization information from some other source into the properties and you're set.
I was able to inject a string through Named annotation.
#Provides
#Named("stage")
String stage() {
return domain;
}
class SomeClass {
#Inject
#Named("stage")
String stageName;
}
I find a solution in the FAQ of Guice:
http://code.google.com/docreader/#p=google-guice&s=google-guice&t=FrequentlyAskedQuestions
In addition to define an annotation and a String attribute in MyModule, I need to write below line to get a instance of SomeClass:
SomeClass instance = Guice.createInjector(new MyModule("any string i like to use")).getInstance(SomeClass.class);
But I remembered that Injector.getInstance() should not be used except for the root object, so is there any better way to do this?