4

Edit: What started as a low-priority question to make my work easier has become a really interesting exercise in Java witchcraft. Thanks for your input, everyone!

I'm working with auto-generated Java code (specifically, code generated by AnyLogic) that produces a method called onChange(). I'd like to call my own method when onChange() is called. Is there any way to "hook into" onChange() via reflection or other standard Java mechanism?

Dylan Knowles
  • 2,726
  • 1
  • 26
  • 52
  • 2
    Have you tried using AOP (AspectJ or Spring AOP). You could have an aspect that advices that the given method could be called after before or around the given point cut. You can [find more here] (http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html) – Prashant Feb 29 '16 at 04:20
  • 2
    If onChange doesn't have a hook there is probably a different way to accomplish an override by either extending it or a configuration change. Its always best to use the framework recommended way. – Bob Feb 29 '16 at 04:46
  • 1
    AOP was my first thought too, but it's rather difficult in this framework: if memory serves it was a part of someone's master's project at our local university to get it integrated. I unfortunately can't override `onChange()` either as the auto-gen clobbers the method I write. I'm hoping the maintainers of the package fix this in the future -- I've pestered them about it -- but I think I'll need to settle for a work-around in the meantime. – Dylan Knowles Feb 29 '16 at 05:18
  • 4
    no one can answer unless you give us more information on how the method is "auto-generated", are u using any container, etc. Even it is a third-party library, you can still make use of AOP. AOP doesn't require you to "override" the method. Of course there are other choices like using an instrumentation agent, using javassist etc but I believe all of them works under certain situations which we cannot tell if they are applicable to you – Adrian Shum Feb 29 '16 at 06:49
  • The code is graphically represented, then converted into Java code: the closest (text-based) comparison I have is a compiler or parser generator like ANTLR. The tool being used, specifically, is AnyLogic. (Thankfully, this question isn't blocking for me: it would just make some of my tasks less manual / hack-ish. I ask mostly out of curiosity and for future efforts.) – Dylan Knowles Mar 01 '16 at 21:33
  • Please give the AnyLogic details: what is the element that you want to hook into the onChange method of? For AnyLogic Parameters, you have access to the on-change 'hook' in the design UI of the Parameter. For other things, I have used overriding before so I'll need to understand the exact context to understand why it doesn't work for you. (In general, this is an AnyLogic question so I would always couch it in terms of the AnyLogic problem; as it is, it's couched as a Java question which is confusing people.) – Stuart Rossiter Mar 02 '16 at 10:05
  • @StuartRossiter I can hook into parameter `onChange()`s easily enough, but it's the *Agent* onChange() that I can't hook into. When that method is auto-generated, it seems to clobber / disagree with my onChange() method, so I need an alternate strategy. This is why this is a Java question: I have a predefined method I need to hook into that I can't override, and I need a Java mechanism (not AnyLogic mechanism, because none exist AFAIK) to gain access to that method. – Dylan Knowles Mar 02 '16 at 23:42
  • 1
    @DylanKnowles Thanks for the explanation; I'll have a think. But it does still help knowing the AnyLogic context since that's the starting point in terms of what Java will get generated under what circumstances (thus providing the Java context for the problem). I wouldn't write off a more 'AnyLogic-y' solution just yet... – Stuart Rossiter Mar 03 '16 at 09:10
  • 1
    @DylanKnowles, I just passed by. onChange() can be overriden in AnyLogic 8.1. Contact with me if you need sample. – Gregory Monahov Aug 11 '17 at 12:39

1 Answers1

1

One solution that I could suggest is using Proxy objects. Here is a tutorial that might be of some help to you.

Prashant
  • 4,775
  • 3
  • 28
  • 47
  • The auto-generated code creates a Java class rather than an interface. Proxies seem interface-based: how might I use a Proxy in this situation? (It might be that I've misinterpreted how Proxies work.) – Dylan Knowles Mar 01 '16 at 21:54
  • 1
    No it does not allow us to use classes. The only solution that I can think of for now is to use and external library like [CGLib](https://github.com/cglib). Follow [this](https://dzone.com/articles/cglib-missing-manual) tutorial. It works the same way as Proxy but by creating a subclass of the Super concrete class. It also uses the same API as InvocationHandler. – Prashant Mar 02 '16 at 04:33
  • @DylanKnowles Is the class called through an interface though? The method name (`onChange()`) does suggest it is. In which case you can use proxies. – biziclop Mar 02 '16 at 23:44
  • It's unfortunately a core class (i.e., not an interface) named Agent from which all agent subclasses are derived: all subclasses then have their onChange method auto-generated when compiled. *This said,* I wonder if I can make *my* Agent subclasses extend an interface with `onChange()`, which is then autogenerated, and then I use a proxy to hook into the interface, which should then give me a hook into to the generated `onChange()`? – Dylan Knowles Mar 03 '16 at 00:23
  • HA! It looks I can actually do that! Now I just need to figure out how I can make this proxy thing work... – Dylan Knowles Mar 03 '16 at 00:27
  • **Note:** I'm going to consider this the answer as I think it is the closest I can get in AnyLogic with the current version. I shall petition the company to release a proper hook sometime in the future :P – Dylan Knowles Mar 07 '16 at 21:34