ReferenceContributor don't works for existing languages - java

I am trying to implements a new reference from an existing language, in case, PHP, but it even is catched from debugger. Seems that it just is not initialized.
My problem is the following: the Laravel Frameworks implements a concept called query scopes. With that, when I do a method call like $user->filterAge() it, on reality, calls from a definition declared as User::scopeFilterAge() (briefly).
What I want to do: I like that PhpStorm understand that the "filterAge" points to scopeFilterAge declaration (ctrl+click). Like it does when I do at $user, for instance:
What I tried: I tried to follow the plugin development doc about reference contribuitor. Then I updated my plugin.xml with a new extension. Note: my inspections or completion contribuitors on this same file works fine. My problem is justly with this reference contribuitor over an existing language.
My plugin.xml:
<extensions defaultExtensionNs="com.intellij">
<psi.referenceContributor language="PHP"
implementation="[...].ScopeReferenceContribuitor"/>
</extensions>
And the implementation of ScopeReferenceContribuitor.java:
public class ScopeReferenceContribuitor extends PsiReferenceContributor {
#Override
public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
// Breakpoint:
[...]
}
}
This breakpoint just don't works, never is called, nothing. Even if I force an error (like an NPE) it just don't works.
What I am forgiving?
This topic seems solve my problem, but I already tested, and for some reason it just don't call the debugger on breakpoint.
I too commited my code example.

Related

setServletContext not activating inside #Configuration file

So, this is something of a follow-on of this question. My current code looks something like this:
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackages = {"base.pkg.name"})
public class MyApp implements ServletContextAware {
private ThingDAO beanThingDAO = null;
public MyApp() {
// Lots of stuff goes here.
// no reference to servletContext, though
// beanThing gets initialized, and mostly populated.
}
#Bean publicD ThingDAO getBeanThingDAO() { return beanThingDAO; }
public void setServletContext(ServletContext servletContext) {
// all references to servletContext go here, including the
// bit where we call the appropriate setters in beanThingDAO
{
}
The problem is, it's not working. Specifically, my understanding was that setServletContext was supposed to be called by various forms of Spring Magic at some point during the startup process, but (as revealed by System.out.println()) it never gets called. I'm trying to finish up the first stage of a major bunch of refactoring, and for the moment it is of notable value to me to be able to handle the access to servletContext entirely inside of the #Configuration file. I'm not looking for an answer that will tell me that I should put it in the controllers. I'm looking for an answer that will either tell me how to get it working inside of the #Configuration file, or explain why that won't work, and what I can do about it.
I just ran into a very similar issue and while I'm not positive it's exactly the same problem I thought I'd record my solution in case it's helpful to others.
In my case I had a single #Configuration class for my spring boot application that implemented both ServletContextAware and WebMvcConfigurer.
In the end it turns out that Spring Boot has a bug (or at least undocumented restraint) that ServletContextAware.setServletContext() will never be called if you also implement WebMvcConfigurer on the same class. The solution was simply to split out a separate #Configuration class to implement ServletContextAware.
Here's a simple project I found that demonstrates and explains more what the problem was for me:
https://github.com/dvntucker/boot-issue-sample
The OP doesn't show that the bean in question was implementing both of these, but given the OP is using simplified example code I thought maybe the fact that the asker could have been implementing both interfaces in his actual code and might have omitted the second interface.
Well, I have an answer. It's not one I'm particularly happy with, so I won't be accepting it, but if someone with my same problem stumbles across this question, I want to at least give them the benefit of my experience.
For some reason, the ServletContextAware automatic call simply doesn't work under those circumstances. It works for pretty much every other component, though. I created a kludge class that looks something like this:
// This class's only purpose is to act as a kludge to in some way get
// around the fact that ServletContextAware doesn't seem to work on MyApp.
// none of the *other* spring boot ways of getting the servlet context into a
// file seem to work either.
#Component
public class ServletContextSetter implements ServletContextAware {
private MyApp app;
public ServletContextSetter(MyApp app) {
this.app = app;
}
#Override
public void setServletContext(ServletContext servletContext) {
app.setServletContext(servletContext);
}
}
Does the job. I don't like it, and I will be rebuilding things later to make it unnecessary so I can take it out, but it does work. I'm going to hold the checkmark, though, in case anyone can tell me either how to make it work entirely inside the #Configuration - decorated file, or why it doesn't work there.
Note that the #Component decorator is important, here. Won't work without it.

Java ME: javax.microedition classes appear unimplemented

I'm developing a Java ME project in Intellij. When I try to call a function from the javax.microedition package, all functions simply return null. After inspection, these functions exist but contain no substance (are unimplemented). For example, the javax.microedition.io.connector class function .open(String var) appears this way and always returns null:
public static Connection open(String var0) throws IOException {
return null;
}
This function does not match the documentation provided by Oracle and according to the documentation Connector is not an abstract class. All other functions I inspected seem to be implemented the same way. Did I miss a step in setting up the Java ME SDK? Am I missing something?
Additionally this is the code I try to run but returns null:
ServerSocketConnection server = (ServerSocketConnection) Connector.open("socket://:4040");
These are called stub classes. They only contain method signatures and default return values. You can use them to compile your code without problems.
When you run your app on an emulator (or on an actual device) these classes will have a proper implementation and behave as expected.

Java + Libgdx: Gdx.app.log() null pointer error

I am learning the LibGDX engine in parallel to re-learning java, and have written a simple logging class that has one method with a string argument to be passed to the Gdx.app.log(). while this isn't needed I did so to practice importing and using custom methods and classes, as well as reducing the length of the line needed to send a message to the console. the method looks like so:
import com.badlogic.gdx.Gdx;
public class logging {
public static final String tag="Console";
//contains method for logging to the console during testing.
public void log(String message){
Gdx.app.log(tag, message);
}
}
Then in the class I am using it in, it is imported properly, and a public logging 'con' is created. Up to this point everything seems to work fine because when I type con. in eclipse I get the log(message) as an autocomplete option, however when it is actually called for instance in a screen, under the show() method. when the program tries to step through that point i get a java.lang.NullPointerException which is confusing the hell out of me since everything is written properly. as an example of its use:
con.log("this is a test");
is the exact usage I attempt which seems fine in eclipse before runtime. Is there some simple idea I am failing to grasp here? or a quirk to the Gdx.app.log()? Please no responses with "just use the Gdx.app.log(); where you need to write to the log" as this is not the point of the exercise for me. thank you in advance for all the help!
If you are getting a NullPointerException in this line:
con.log("this is a test");
The only thing that can be null is con. You are probably defining it, but not actually creating it.
Logging con;
and not
Logging con = new Logging();

Unexpected behavior overriding getWorkbenchErrorHandler in Eclipse RCP

I think I've discovered a kind of Schrödinger's cat problem in my code. The body of a function is never executed if I change one line within the body of that same function; but if I leave that line alone, the function executes. Somehow the program knows ahead of time what the body is, and decides not to call it...
I'm working on an Eclipse RCP application in Java, and have need to use their Error Handling System. According to the page linked,
There are two ways for adding handlers to the handling flow.
using extension point org.eclipse.ui.statusHandlers
by the workbench advisor and its method {#link WorkbenchAdvisor#getWorkbenchErrorHandler()}.
So I've gone into my ApplicationWorkbenchAdvisor class, and overridden the getWorkbenchErrorHandler method:
#Override
public synchronized AbstractStatusHandler getWorkbenchErrorHandler()
{
System.out.println("IT LIVES!");
if (myErrorHandler == null)
{
AbstractStatusHandler delegate = super.getWorkbenchErrorHandler();
MyStatusHandler otherThing = new MyStatusHandler(delegate);
myErrorHandler = otherThing;
}
return myErrorHandler;
}
The MyStatusHandler is meant to act as a wrapper for the delegate handler. I've re-named the class for anonymity. As it is, above, this function is never called. The println never happens, and even in debug mode with breakpoints, they never trigger. Now the wierd part: If I change the line that assigns the myErrorHandler to
myErrorHandler = delegate;
then the function is called; multiple times, in fact!
This problem has me and two java-savvy coworkers stumped, so I'm hoping the good people of SO can help us!
As it turned out, my problem was that the MyErrorHandler class was defined in a different plugin, which presumably wasn't fully loaded yet. That doesn't seem to add up entirely, but once I moved the class definition of my error handler into the same plugin that was calling it during startup, the problems went away.

AspectJ Load time weaver doesn't detect all classes

I am using Spring's declarative transactions (the #Transactional annotation) in "aspectj" mode. It works in most cases exactly like it should, but for one it doesn't. We can call it Lang (because that's what it's actually called).
I have been able to pinpoint the problem to the load time weaver. By turning on debug and verbose logging in aop.xml, it lists all classes being woven. The problematic class Lang is indeed not mentioned in the logs at all.
Then I put a breakpoint at the top of Lang, causing Eclipse to suspend the thread when the Lang class is loaded. This breakpoint is hit while the LTW weaving other classes! So I am guessing it either tries to weave Lang and fails and doesn't output that, or some other class has a reference that forces it to load Lang before it actually gets a chance to weave it.
I am unsure however how to continue to debug this, since I am not able to reproduce it in smaller scale. Any suggestions on how to go on?
Update: Other clues are also welcome. For example, how does the LTW actually work? There appears to be a lot of magic happening. Are there any options to get even more debug output from the LTW? I currently have:
<weaver options="-XnoInline -Xreweavable -verbose -debug -showWeaveInfo">
I forgot tom mention it before: spring-agent is being used to allow LTW, i.e., the InstrumentationLoadTimeWeaver.
Based on the suggestions of Andy Clement I decided to inspect whether the AspectJ transformer is ever even passed the class. I put a breakpoint in ClassPreProcessorAgent.transform(..), and it seems that the Lang class never even reaches that method, despite it being loaded by the same class loader as other classes (an instance of Jetty's WebAppClassLoader).
I then went on to put a breakpoint in InstrumentationLoadTimeWeaver$FilteringClassFileTransformer.transform(..). Not even that one is hit for Lang. And I believe that method should be invoked for all loaded classes, regardless of what class loader they are using. This is starting to look like:
A problem with my debugging. Possibly Lang is not loaded at the time when Eclipse reports it is
Java bug? Far-fetched, but I suppose it does happen.
Next clue: I turned on -verbose:class and it appears as if Lang is being loaded prematurely - probably before the transformer is added to Instrumentation. Oddly, my Eclipse breakpoint does not catch this loading.
This means that Spring is new suspect. there appears to be some processing in ConfigurationClassPostProcessor that loads classes to inspect them. This could be related to my problem.
These lines in ConfigurationClassBeanDefinitionReader causes the Lang class to be read:
else if (metadata.isAnnotated(Component.class.getName()) ||
metadata.hasAnnotatedMethods(Bean.class.getName())) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
return true;
}
In particular, metadata.hasAnnotatedMethods() calls getDeclaredMethods() on the class, which loads all parameter classes of all methods in that class. I am guessing that this might not be the end of the problem though, because I think the classes are supposed to be unloaded. Could the JVM be caching the class instance for unknowable reasons?
OK, I have solved the problem. Essentially, it is a Spring problem in conjunction with some custom extensions. If anyone comes across something similar, I will try to explain step by step what is happening.
First of all, we have a custom BeanDefintionParser in our project. This class had the following definition:
private static class ControllerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
protected Class<?> getBeanClass(Element element) {
try {
return Class.forName(element.getAttribute("class"));
} catch (ClassNotFoundException e) {
throw new RuntimeException("Class " + element.getAttribute("class") + "not found.", e);
}
}
// code to parse XML omitted for brevity
}
Now, the problem occurs after all bean definition have been read and BeanDefinitionRegistryPostProcessor begins to kick in. At this stage, a class called ConfigurationClassPostProcessor starts looking through all bean definitions, to search for bean classes annotated with #Configuration or that have methods with #Bean.
In the process of reading annotations for a bean, it uses the AnnotationMetadata interface. For most regular beans, a subclass called AnnotationMetadataVisitor is used. However, when parsing the bean definitions, if you have overriden the getBeanClass() method to return a class instance, like we had, instead a StandardAnnotationMetadata instance is used. When StandardAnnotationMetadata.hasAnnotatedMethods(..) is invoked, it calls Class.getDeclaredMethods(), which in turn causes the class loader to load all classes used as parameters in that class. Classes loaded this way are not correctly unloaded, and thus never weaved, since this happens before the AspectJ transformer registered.
Now, my problem was that I had a class like so:
public class Something {
private Lang lang;
public void setLang(Lang lang) {
this.lang = lang;
}
}
Then, I had a bean of class Something that was parsed using our custom ControllerBeanDefinitionParser. This triggered the wrong annotation detection procedure, which triggered unexpected class loading, which meant that AspectJ never got a chance to weave Lang.
The solution was to not override getBeanClass(..), but instead override getBeanClassName(..), which according to the documentation is preferable:
private static class ControllerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
protected String getBeanClassName(Element element) {
return element.getAttribute("class");
}
// code to parse XML omitted for brevity
}
Lesson of the day: Do not override getBeanClass unless you really mean it. Actually, don't try to write your own BeanDefinitionParser unless you know what you're doing.
Fin.
If your class is not mentioned in the -verbose/-debug output, that suggests to me it is not being loaded by the loader you think it is. Can you be 100% sure that 'Lang' isn't on the classpath of a classloader higher in the hierarchy? Which classloader is loading Lang at the point in time when you trigger your breakpoint?
Also, you don't mention AspectJ version - if you are on 1.6.7 that had issues with ltw for anything but a trivial aop.xml. You should be on 1.6.8 or 1.6.9.
How does ltw actually work?
Put simply, an AspectJ weaver is created for each classloader that may want to weave code. AspectJ is asked if it wants to modify the bytes for a class before it is defined to the VM. AspectJ looks at any aop.xml files it can 'see' (as resources) through the classloader in question and uses them to configure itself. Once configured it weaves the aspects as specified, taking into account all include/exclude clauses.
Andy Clement
AspectJ Project Lead
Option 1) Aspect J is open source. Crack it open and see what is going on.
Option 2) Rename your class to Bang, see if it starts working
I would not be surprised if there is hard coding to skip "lang' in there, though I can't say why.
Edit -
Seeing code like this in the source
if (superclassnameIndex > 0) { // May be zero -> class is java.lang.Object
superclassname = cpool.getConstantString(superclassnameIndex, Constants.CONSTANT_Class);
superclassname = Utility.compactClassName(superclassname, false);
} else {
superclassname = "java.lang.Object";
}
Looks like they are trying to skip weaving of java.lang.stuff.... don't see anything for just "lang" but it may be there (or a bug)

Categories