I don't want to discuss the merits of this approach, just if it is possible. I believe the answer to be "no". But maybe someone will surprise me!
Imagine you have a core widget class. It has a method calculateHeight(), that returns a height. The height is too big - this result in buttons (say) that are too big. You can extend DefaultWidget to create your own NiceWidget, and implement your own calculateHeight() to return a nicer size.
Now a library class WindowDisplayFactory, instantiates DefaultWidget in a fairly complex method. You would like it to use your NiceWidget. The factory class's method looks something like this:
public IWidget createView(Component parent) {
DefaultWidget widget = new DefaultWidget(CONSTS.BLUE, CONSTS.SIZE_STUPIDLY);
// bunch of ifs ...
SomeOtherWidget bla = new SomeOtherWidget(widget);
SomeResultWidget result = new SomeResultWidget(parent);
SomeListener listener = new SomeListener(parent, widget, flags);
// more widget creation and voodoo here
return result;
}
That's the deal. The result has the DefaultWidget deep within a hierarchy of other objects. The question - how to get this factory method to use my own NiceWidget? Or at least get my own calculateHeight() in there. Ideally, I'd like to be able to monkey patch the DefaultWidget so that its calculateHeight did the right thing...
public class MyWindowDisplayFactory {
public IWidget createView(Component parent) {
DefaultWidget.class.setMethod("calculateHeight", myCalculateHeight);
return super.createView(parent);
}
}
Which is what I could do in Python, Ruby, etc. I've invented the name setMethod() though. The other options open to me are:
Copying and pasting the code of the createView() method into my own class that inherits from the factory class
Living with widgets that are too big
The factory class can't be changed - it is part of a core platform API. I tried reflection on the returned result to get to the widget that (eventually) got added, but it is several widget-layers down and somewhere it gets used to initialize other stuff, causing odd side effects.
Any ideas? My solution so far is the copy-paste job, but that's a cop out that requires tracking the changes in the parent factory class when upgrading to newer versions of the platform, and I'd be interested to hear other options.
Perhaps you could use Aspect Oriented Programming to trap calls to that function and return your own version instead?
Spring offers some AOP functionality but there are other libraries that do it as well.
One ugly solution would be to put your own implementation of DefaultWidget (with same FQCN) earlier on the Classpath than the normal implementation. It's a terrible hack, but every other approach that I can think of is even worse.
Just my concept idea,
It is possible that use AOP, with bytecode engineering way, to inject a aspect to the calculateHeight method.
Then, you may enable you patch by ThreadLocal or else variable.
cglib is a Java library that can do some things similar to monkey patching - it can manipulate bytecode at runtime to change certain behaviours. I'm not sure if it can do exactly what you need, but it's worth a look...
It is totally possible to monkeypatch in Java, using Unsafe.putObject and a class finder. Wrote a blog post here:
https://tersesystems.com/blog/2014/03/02/monkeypatching-java-classes/
The object-oriented way of doing this would be to create a wrapper implementing IWidget, delegating all calls to the actual widget, except calculateHeight, something like:
class MyWidget implements IWidget {
private IWidget delegate;
public MyWidget(IWidget d) {
this.delegate = d;
}
public int calculateHeight() {
// my implementation of calculate height
}
// for all other methods: {
public Object foo(Object bar) {
return delegate.foo(bar);
}
}
For this to work, you need to intercept all creations of the widget you want to replace, which probably means creating a similar wrapper for the WidgetFactory. And you must be able to configure which WidgetFactory to use.
It also depends on no client trying to cast the IWidget back to DefaultWidget...
Only suggestions I can think of:
Dig through the library API to see if there's some way of overriding the defaults and sizing. Sizing can be confusing in swing (at least to me) , setMinimum, setMaximum, setdefault, setDefaultOnThursday, ... . It's possible there's a way. If you can contact the library designer(s) you might find an answer that will alleviate the need for unpleasant hacking.
Perhaps extend the factory only overriding some default sizing parameter? depends on the factory but it might be possible.
Creating a class with the same name might be the only other option, as others have pointed out it's ugly and you're liable to forget it and break stuff when you update the api library or deploy in a different environment and forget why you had the classpath set up that way.
You can try using tools like PowerMock/Mockito. If you can mock in tests, you can mock in production too.
However these tools are not really designed to be used that way, so you'll have to prepare the environment yourself and won't be able to use the JUnit runners like you do in tests...
Well, I keep trying to post suggestions, and then I see that they won't work or that you've already mentioned you tried them.
The best solution I can think of is to subclass WindowDisplayFactory, then in the subclass's createView() method, first call super.createView(), then modify the object returned to completely throw out the widget and replace it with an instance of the subclass that does what you want. But the widget is used to initialize stuff, so you'd have to go change all of those.
Then I think of using reflection on the returned object from createView() and trying to fix things up that way, but again, that's hairy because so much stuff was initialized with the widget. I think I would try to use that approach, though, if it was simple enough to justify it over copying and pasting.
I'll be watching this, plus thinking to see if I can come up with any other ideas. Java Reflection sure is nice, but it can't beat the dynamic introspection I've seen available in languages such as Perl and Python.
Related
I'm pretty new to java in general so I've been following a plethora of tutorials. so FEEL FREE TO CORRECT ME AT EVERY TURN! (yes even in code inefficiencies as well!!)
I currently have the issue of getting a single method to return different subclasses/types from a superclass.
The problem code is at the bottom of the post.
Get ready because I'm going to throw this at you.
I've run into a Java language barrier.
I'm in the process of following a tutorial(libGDX) to use LibGDX and another tutorial to implement component based design (see link just below)
I've never seen Objective-C code until now so these are my feeble attempts to convert the tutorial code(component design) to java
Currently the idea is to have an Entity that will use various Components to access different functional abilities(health, rendering, movement, etc) inside the game.
I'm attempting to get the Component associated with an Entity and check its fields, but I've run into some sort of issue with returning class types.
Component System
Component.java
public class Component {
}
HealthComponent.java
public class HealthComponent extends Component{
public boolean alive;
}
RenderComponent.java
public class RenderComponent extends Component {
public boolean canRender;
}
Entity System
I store Entitys with their Components each within a list(ArrayMap[LibGDX]) of available active Components so that I can get all Entitys using a specified Component. Or in this case, get a specific Component associated with an Entity
Entity.java
public class Entity {
private int eid;
public Entity (int eid) {
this.eid = eid;
}
public int eid () {
return this.eid;
}
}
EntityManager.java
public class EntityManager {
public ArrayMap<String, ArrayMap<Integer, Component>> componentsByClass;
// Some other stuff like constructors and methods
public Component getComponentOfClassForEntity(Component component, Entity entity) {
//returns Component type
return componentsByClass.get(component.getClass().getSimpleName()).get(entity.eid());
}
}
My problem comes to this part
My understanding is in order to stay as DRY as possible I don't want to have multiple different methods for each Component subclass just to return a different class type for the ExampleComponent. It would be very convenient if I could get this working smoothly with some sort of type/class smoother outer awesome thingy without any crazy hacks that are bad practices. Also, I'm assuming some if/then statements could work but it seems like there is a better way what with my limited knowledge and all.
I attempt to :
Component health = this.entityManager.getComponentOfClassForEntity(healthComponent, entity);
// No errors, however I don't really have a health component now do I?...Trying out:
if((HealthComponent)health.alive) // Cannot resolve symbol "alive"...
or the same but change the type:
HealthComponent health = this.entityManager.getComponentOfClassForEntity(healthComponent, entity);
// Required: HealthComponent
// Found: Component
// Sucks as I'd like to be able able to follow the DRY conventionthingy:
RenderComponent render = this.entityManager.getComponentOfClassForEntity(renderComponent, entity);
if(render.canRender))//plsssrenddrr
etc...
In full, I understand that you're not supposed to be able to do that, but my question is what is an ideal solution that doesn't break convention or make for a hacky and poorly coded game.
Perhaps there's a better Component based Architecture out there that is a cleaner and more do-able solution...
Thanks so much!!
I recommend you take the DRY principle to its logical conclusion and Don't Repeat Someone Else (if someone can turn that into a snazzy acronym, then let me know).
There are some good ECS libraries for Java already out there, and I highly recommend that you try to use (or extend) one of those instead of creating your own. Quite frankly, if you try to build an ECS of your own, you're probably never going to finish the game itself.
Out of the many ECS available, I'm going to recommend you start with Ashley or Artemis.
Ashley is a light-weight ECS that appears to be affiliated with the libGDX group in some way- the libGDX setup tool gives you the option to include Ashley in the gradle files it generates for you. In my humble opinion, it has more boilerplate code than I'd like, but that also means it's doing less black magic (i.e. reflection).
I personally moved to Artemis because of the syntax benefits, and it appears to be further optimized and more actively maintained. If you want to add it to your game, you can follow the instructions here.
All that being said, these are both great libraries which deserve a more in-depth comparison, and so long as you use one of these (or another ECS library) it should allow you to accomplish your goal.
Now if you're more interested in making the ECS than the game (and I've totally been there), I would still recommend you look at the approaches these two libraries took (their code is on GitHub) and see how they dealt with the syntax issue.
There is a pattern which is widely used in my current project:
private Collection<Converter<T>> converters = new HashSet<>();
#Inject
private void init(#Any Instance<Converter<T>> converters) {
for (Converter<T> converter : converters) {
this.converters.add(converter);
}
}
This way I can create as many converters as I want and they are automatically injected to my bean.
My problem is now with testing: the converters collection is used in my code, but Junit doesn't call the init(..) method and I need to call it to set the mocked converters.
I could make the method protected, but I don't feel OK with it because I would be changing the visibility scope of the method.
I could also call the method using reflection, but this also doesn't feel right.
This brings me to the conclusion that this code could be improved to be more testable.
Is there anyway I change this code so the testability is improved but the references are still automatically injected?
Just go ahead and make it 'public' or 'protected'.
You are not actually gaining any protection from someone changing the collection post-instantiation this way (you've just made it a little more awkward), so you don't lose anything by exposing that method (in fact I'd argue you make your class slightly better, because than you let people chose how they want to construct, rather than forcing a use of injection/reflection).
If you did want to fully prevent post-instantiation modification, than you're going to have to go to a 'final' variable anyway, with an unmodifiable collection type and change to constructor injection, but I don't get the impression that this is what you want to do.
Thing is: if you can't "trust" the people who can write code within your "package" ... I guess having "private" on a method doesn't really help you anyway. Because if people want to mess up, and they can write code in your package, they will find ways to mess up anyway.
Meaning: if you drop the "private" on your method, yes it becomes package-visible. But you can place a javadoc on it that says: "Don't call directly; used for unit test/auto-wiring only" or something like that.
I have a library with several packages-
lets say
package a;
package b;
inside package a I have public a_class
inside package b I have public b_class
a_class uses b_class.
I need to generate a library from this , but I do not want the Client to see b_class.
The only solution I know of is to flatten my beautifully understandable packages to single package and to use default package access for b_class.
Is there another way to do so ? maybe using interfaces or some form of design pattern ??
If you reject to move the code to an individual, controlled server, all you can do is to hinder the client programmer when trying to use your APIs. Let's begin applying good practices to your design:
Let your packages organized as they are now.
For every class you want to "hide":
Make it non-public.
Extract its public API to a new, public interface:
public interface MyInterface {...}
Create a public factory class to get an object of that interface type.
public class MyFactory
{
public MyInterface createObject();
}
So far, you have now your packages loosely coupled, and the implementation classes are now private (as good practices preach, and you already said). Still, they are yet available through the interfaces and factories.
So, how can you avoid that "stranger" clients execute your private APIs? What comes next is a creative, a little complicated, yet valid solution, based on hindering the client programmers:
Modify your factory classes: Add to every factory method a new parameter:
public class MyFactory
{
public MyInterface createObject(Macguffin parameter);
}
So, what is Macguffin? It is a new interface you must define in your application, with at least one method:
public interface Macguffin
{
public String dummyMethod();
}
But do not provide any usable implementation of this interface. In every place of your code you need to provide a Macguffin object, create it through an anonymous class:
MyFactory.getObject(new Macguffin(){
public String dummyMethod(){
return "x";
}
});
Or, even more advanced, through a dynamic proxy object, so no ".class" file of this implementation would be found even if the client programmer dares to decompile the code.
What do you get from this? Basically is to dissuade the programmer from using a factory which requires an unknown, undocumented, ununderstandable object. The factory classes should just care not to receive a null object, and to invoke the dummy method and check the return value it is not null either (or, if you want a higher security level, add an undocumented secret-key-rule).
So this solution relies upon a subtle obfuscation of your API, to discourage the client programmer to use it directly. The more obscure the names of the Macguffin interface and its methods, the better.
I need to generate a library from this , but I do not want the Client to see b_class. The only solution I know of is to flatten my beautifully understandable packages to single package and to use default package access for b_class. Is there another way to do so ?
Yes, make b_class package-private (default access) and instantiate it via reflection for use in a_class.
Since you know the full class name, reflectively load the class:
Class<?> clz = Class.forName("b.b_class")
Find the constructor you want to invoke:
Constructor<?> con = clz.getDeclaredConstructor();
Allow yourself to invoke the constructor by making it accessible:
con.setAccessible(true);
Invoke the constructor to obtain your b_class instance:
Object o = con.newInstance();
Hurrah, now you have an instance of b_class. However, you can't call b_class's methods on an instance of Object, so you have two options:
Use reflection to invoke b_class's methods (not much fun, but easy enough and may be ok if you only have a few methods with few parameters).
Have b_class implement an interface that you don't mind the client seeing and cast your instance of b_class to that interface (reading between the lines I suspect you may already have such an interface?).
You'll definitely want to go with option 2 to minimise your pain unless it gets you back to square one again (polluting the namespace with types you don't want to expose the client to).
For full disclosure, two notes:
1) There is a (small) overhead to using reflection vs direct instantiation and invocation. If you cast to an interface you'll only pay the cost of reflection on the instantiation. In any case it likely isn't a problem unless you make hundreds of thousands of invocations in a tight loop.
2) There is nothing to stop a determined client from finding out the class name and doing the same thing, but if I understand your motivation correctly you just want expose a clean API, so this isn't really a worry.
When using Kotlin, you can use the internal modifier for your library classes.
If I understand correctly you are asking about publishing your library for 3rd party usage without disclosing part of your source? If that's the case you can use proguard, which can obfuscate your library. By default everything will be excluded/obfuscated, unless you specify things you want to exclude from being obfuscated/excluded.
If you want to distribute [part of] your code without the client being able to access it at all, that means that the client won't be able to execute it either. :-O
Thus, you just have one option: Put the sensible part of your code into a public server and distribute a proxy to access it, so that your code would be kept and executed into your server and the client would still be able to execute it through the proxy but without accessing it directly.
You might use a servlet, a webservice, a RMI object, or a simple TCP server, depending on the complexity level of your code.
This is the safest approach I can think of, but it also deserves a price to pay: In addition to complexing your system, it would introduce a network delay for each remote operation, which might be big deal depending on the performance requirements. Also, you should securize the server itself, to avoid hacker intrussions. This could be a good solution if you already have a server that you could take advantage of.
I'm getting into a problem, when I was trying to create a custom LayoutAnimationController for an Android project. It has the method
public final Animation getAnimationForView(View v)
For my custom LayoutAnimationController, I need to override this method, because each view should get a "unique" animation.
Is it possible to override public final methods by using reflection or similar techniques, or do you have an alternative idea?
I know that something similar had been discuses in override java final methods via reflection or other means? but the "solution" which came up there, was pretty specific to the problems of the user and did not completely answer the question of overriding final methods.
It looks like LayoutAnimationController is not intended to be used like this.
If you would be able to override getAnimationForView(View v) with the functionality you want most methods/constructors of LayoutAnimationController would make no sense since this class is created for using a single animation (with different delays) on multiple views.
Maybe it is better to look into the source and create you own animation controller based on this information.
An old question, but I still feel I should answer as there doesn't seem to be a possible solution using LayoutAnimationController.
I ended up overriding AnimationSet and just moved the LayoutAnimationController functionality to that class. Of course, together with my custom code.
Finally, I just have to rant about this: this is hardly the first time I ran into some sort of private / final / access denied in your preferred way code in Google's framework. They seem to find it hilarious if they give us programmers a hard time. I understand that Transformation only Animations are there for performance, but sometimes we just need something different and disabling us through such childish ways is beyond ridiculous. /rant
So, given the following code:
public MyInterface getMyInterface() {
return new MyInterface() {
public SomethingElse getSomethingElse() {
// ....
}
}
}
...
MyInterface obj = getMyInterface();
Is there some way to instrument a call to getSomethingElse() on that obj? To go in and do some bytecode modification or something?
I have production code in there that in a different situation (call it "design time") I want to add some tracing/logging and such code for help in troubleshooting and analysis. Performance is critical for the production case so I want to leave it without the extra tracing/logging overhead. But in the design time situation, I want to have all the trace info.
Yes, it is possible to do what you're asking, although there are definitely better ways to accomplish it - the most obvious would be to create a default implementation of MyInterface, and then a "tracing" subclass of it that extends and logs before invoking the superclass version.
If instrumentation is your only option, then when running at design time, you can start your project with a java agent in Java 5 or add a java agent to the classpath at runtime in Java 6. See the instrumentation documentation.
To instrument the class, you will probably want to use a tool like ASM. The steps would be something like this:
In your Agent class, implement java.lang.instrument.ClassFileTransformer .
In your agentmain() or premain() method, request to transform classes.
When you receive a call to the transform method, you can check if the class implements MyInterface by using Class.getInterfaces().
Optionally, you can check to see if its Class.getEnclosingClass() is the class in which you wrote/found this code.
If the Class passes these sanity checks, then create a ClassWriter that adds logging to the getSomethingElse() method. The ASMifier helps a lot when trying to figure out how to generate the code you want.
Then, in production, none of that code will exist. In development, you would add your Java Agent in your environment, which would enable your debugging.
Again, there are almost certainly better ways to do this, but there are good reasons to use instrumentation, and this is a mini-crash course in doing it.
Hope that helps,
If you want to turn on logging on in development, the simplest thing to do is
if(LOGGER.isDebugEnabled())
LOGGER.debug("my debug message");
The over head added is sub-nanosecond so even if you are working on a system where every nano-seconds count, this is still the best pattern to use.
You can get the class with
Class.forName("package.OuterClass$NNN");
You need to call a constructor which takes an instance of the outer class.
This sounds like a good case for using aspects.
You can simply apply logging/tracing code around any methods you want in your testing environment and leave them out when you move to production.