I have an Eclipse plugin which has the purpose of indexing and searching XML files for custom frameworks used by the application my team develops.
There is a toolbar with several buttons on it. Each button has its own command and each command is linked to a separate handler which brings up a search dialog.
The handlers differ only by which file type they search. Currently there are ten concrete handlers and one abstract. All of the functionality is handled in the abstract class, and the concrete classes only implement an abstract "get file type" method.
Ideally I would only have one handler. This means there would need to be a way to inject the enum into the base class directly.
I looked at command parameters, but this appears to be user-facing. I need something hard-coded where the command tells the handler "use this value." I don't care if this is a constructor argument or some hard-coded parameter in plugin.xml.
Thus far I have not been able to find a way to do this. Perhaps my Google-fu is weak, perhaps I am just not seeing it.
Is there a way to specify a hard-coded parameter to a handler constructor or to call a method to set a parameter after it is constructed but before it is invoked?
Command parameters are the right way to achieve that. What are the problems you face with that? Here is an example to use the parameters
Related
I have a question about Reflection, but the motivation is from using Spring Framework.
Consider this project, which is a sort of Minimum Working Example version of a deployed project.
In the ProjectionResourceProcessorConfig class, I have an entityProjectionResourceProcessor method for every projection, and every entity in the database have a few projections. That's about 60 methods.
I don't want to keep this up because of the obvious maintenance disadvantage. I want to use Reflection in order to automatically register one bean for every projection class.
The postProcessBeanDefinitionRegistry method in the ProjectionResourceProcessorConfig class shows that I can get the list of classes I want to use to register one bean for each and shows how to register a bean programatically.
However, because I need to use the ProjectionResourceProcessor class, I need to override the getEntityClass method. I haven't been able to find a way to do that programatically. That's why I've declared the inner class. It shows the programatic bean registration working, but it falls in the same issue as requiring a piece of code for every bean.
Apart from reflection, I tried to use the setMethodOverrides method of the RootBeanDefinition class to override that method, but I couldn't manage to understand how to use that method. Google couldn't find any documentation or usage example (except for a vaguely related Chinese post with copies on several different websites).
I also tried to use the MethodReplacer class but I haven't found how to use it with annotation driven configuration.
I also tried to replace the getEntityClass method by a variable and replace the variable's value by reflection, but apparently when the variable is read the value that was set in the super class is the one that is retrieved.
To test the project, run the tests at DemoApplicationTests. It will print the projection of some entities. If they have links, it's working.
Is it possible to do what I want? If it is, how?
Thanks in advance.
There are a large number of classes in this codebase which use a specific interface. However, picking a few at random, I've been unable to find one which is actually called anywhere; as such, I don't have a great idea of how to use it.
Is there a way in Eclipse to find every instance of any class which implements this interface?
In other words, suppose there exists an interface Interface, and classes ClassA, ClassB, ClassC, ..., ClassX, which all implement it. I want to see every point in the code where something like `ClassX obj = new ClassX(). Most of the classes I'm finding that implement this interface don't have any point where they're actually used; I assume they're for future use.
Open the interface class, hold Control and move your mouse to interface's name, select open implementation. That's the simplest and easiest way to do.
Yes, highlight the interface name and hit F4 or right click -> Open type hierarchy.
Update after OP's edit:
If you are using a framework that uses dependency injection like spring probably you don't find any reference because some of the implementations are defined in a xml file.
Also consider if some implementations are created and invoked via reflection.
Some classes might be loaded during runtime e.g. using reflection. To catch-them-all you can set a method entry breakpoint on the interface method. This is explained in this answer. That way all calls to implementation methods will suspend the JVM regardless of what is the object type.
Do note that unlike the line breakpoints the method breakpoints will really slow down the performance of the JVM.
I'm using IntelliJ IDEA and have it set up to open the JavaDoc for any type or member in my browser. Now it seems that IntelliJ IDEA can't guess the full URL for methods that have a generic type as parameter, when I try to to open the documentation for the method java.lang.Object.isAssignableFrom(Class<?>) it asks which of these two URLs should be opened:
file:///[...]/docs/api/java/lang/Class.html#isAssignableFrom(java.lang.Class<?>)
file:///[...]/docs/api/java/lang/Class.html#isAssignableFrom(java.lang.Class)
Are these two competing standards for encoding the type of a method with generic parameters? Can I assume that only one will be used in the future (presumably the first)?
For an added bonus: Is there a way to set up IntelliJ IDEA to automatically chose one of these forms by defaults?
Eclipse calls the default (zero-argument) constructor when instantiating an extension point. I want to provide some arguments. I found a recommendation to use IExecutableExtension#setInitializationData but that appears to require specifying the argument values statically in XML. I need them to be dynamic. Another recommendation was to implement IExecutableExtensionFactory but that seems heavy handed. (The interface also seems pointless, as all it contains is a create() method.) I could add a method to set the values after creation but my class won't work correctly without them and they shouldn't be changed after creation, so forcing them to be provided at object creation time is preferable. This can't be a unique situation. What's the standard way of handling this?
If the arguments need to be "dynamic," where would they come from? How would Eclipse know what values to use? Extension point objects are created when the plugin is activated, so there is not much context available at that point.
I think the best option for you is to use IExecutableExtensionFactory after all. Your factory can implement IExecutableExtension to receive the XML configuration data and then be coded to create the objects based on that and any other context you can make available to it.
Depending on your needs, you could use Dynamic String Substitution Variables to insert certain context into your factory. See also Externalizing strings in plugin.xml for Eclipse plugin
Is there a way to create a JAR-file that contains some arguments that are passed to the main class? (It does not matter whether it prepends or appends the arguments to potential command line arguments.)
I know I could simply write a bootstrapping class and specify this as main class (calling the real main class with the arguments), but this seems a bit awkward.
To the best of my knowledge, no. You'll have to do that kind of thing yourself, in code.
A lot of people find it useful to write a little main class that sets up an environment and then acts as a ClassLoader for the "real" main program. Typically, such pre-mains fiddle with the classpath of their application, but your kind of problem is something else that could be solved like this.
I would design the application to have default settings built in, and override the defaults if the user gives different arguments.
In your setup, what happens if the user gives arguments that are different? Wouldn't end up with multiple similar arguments and have to awkwardly handle that?