In Eclipse, auto-complete for JSF / EL only works for legacy @ManagedBean
or CDI beans (@Named
), at least when using the JBoss tools plugin.
Se
I tried first solution explained by @Thies and it still works for org.jboss.tools.jsf_3.8.500.v20200930-0907.jar
. Actually this is the only way I found to reach my Spring Beans (Having @Component
etc...) from my xhtml files. I wish that he provided the .class
files with support for all Spring annotations instead of just @Controller
, but then I realized that I can do it for everybody. So I downloaded source code and recompiled those two classes to have @Component
support and other Spring annotations. I also wanted to add detailed steps that are required to recompile the files, for the sake of inexperienced coders like me. :)
I tried everything on a clean installation of "Eclipse JEE 2020-09 R Win32 x86_64" and an empty Maven repository. UPPER CASE INFORMATIONS below are things that I have done wrong at the first time and then corrected, so I hope you do not repeat same time consuming mistakes. :)
Before starting the first solution explained by @Thies:
\jbosstools-javaee-master\jsf\plugins\org.jboss.tools.jsf\
folder. Then hit the 'Finish'" button. Wait for Eclipse to do its job, DO NOT TRY TO RUSH THINGS, just wait. :) It will download maven dependencies total of 20-25 MB.\jbosstools-javaee-master\jsf\plugins\org.jboss.tools.jsf\src\org\jboss\tools\jsf\jsf2\bean\model\impl\AbstractMemberDefinition.java
file (find it on Eclipse project) and perform the changes proposed by @Thies as first solution on previous post. But this time make the changes with support for all Spring annotations. :) See his commented out code and update as necessary. It might be something like this:import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMemberValuePair;
import org.jboss.tools.common.java.IAnnotationType;
public boolean isAnnotationPresent(String annotationTypeName) {
//TW: added Spring annotations
boolean b = (getAnnotation(annotationTypeName) != null);
if (!b && JSF2Constants.MANAGED_BEAN_ANNOTATION_TYPE_NAME.equals(annotationTypeName)) {
b = (getAnnotation("org.springframework.stereotype.Controller") != null
|| getAnnotation("org.springframework.stereotype.Service") != null
|| getAnnotation("org.springframework.stereotype.Repository") != null
|| getAnnotation("org.springframework.stereotype.Component") != null);
}
return b;
}
public AnnotationDeclaration getManagedBeanAnnotation() {
AnnotationDeclaration ad = annotationsByType.get(JSF2Constants.MANAGED_BEAN_ANNOTATION_TYPE_NAME);
//TW: added Spring annotations
if (ad != null) return ad;
ad = annotationsByType.get("org.springframework.stereotype.Controller");
if (ad == null) ad = annotationsByType.get("org.springframework.stereotype.Component");
if (ad == null) ad = annotationsByType.get("org.springframework.stereotype.Service");
if (ad == null) ad = annotationsByType.get("org.springframework.stereotype.Repository");
if (ad != null) {
// create wrapper to map "value" (used by Spring) to "name" (which is used by @ManageBean)
ad = new AnnotationDeclaration() {
private AnnotationDeclaration wrapped;
AnnotationDeclaration init(AnnotationDeclaration wrappedAD) {
this.wrapped = wrappedAD;
return this;
}
@Override
public Object getMemberValue(String name) {
Object val = wrapped.getMemberValue(name);
if (val == null && "name".equals(name)) {
val = wrapped.getMemberValue(null);
}
return val;
}
@Override
public Object getMemberValue(String name, boolean resolve) {
Object result = null;
if (resolve) {
result = this.getMemberConstantValue(name);
}
if (result == null) {
result = this.getMemberValue(name);
}
return result;
}
@Override
public void setDeclaration(IJavaAnnotation annotation) {
wrapped.setDeclaration(annotation);
}
@Override
public IJavaAnnotation getDeclaration() {
return wrapped.getDeclaration();
}
@Override
public IResource getResource() {
return wrapped.getResource();
}
@Override
public IMemberValuePair[] getMemberValuePairs() {
return wrapped.getMemberValuePairs();
}
@Override
public Object getMemberConstantValue(String name) {
return wrapped.getMemberConstantValue(name);
}
@Override
public Object getMemberDefaultValue(String name) {
return wrapped.getMemberDefaultValue(name);
}
@Override
public IMember getParentMember() {
return wrapped.getParentMember();
}
@Override
public String getTypeName() {
return wrapped.getTypeName();
}
@Override
public IType getType() {
return wrapped.getType();
}
@Override
public int getLength() {
return wrapped.getLength();
}
@Override
public int getStartPosition() {
return wrapped.getStartPosition();
}
@Override
public IAnnotationType getAnnotation() {
return wrapped.getAnnotation();
}
@Override
public IAnnotation getJavaAnnotation() {
return wrapped.getJavaAnnotation();
}
@Override
public IMember getSourceMember() {
return wrapped.getSourceMember();
}
@Override
public IJavaElement getSourceElement() {
return wrapped.getSourceElement();
}
}.init(ad); // class
}
return ad;
}
AbstractMemberDefinition.class
and AbstractMemberDefinition$1.class
files on \jbosstools-javaee-master\jsf\plugins\org.jboss.tools.jsf\target\classes\org\jboss\tools\jsf\jsf2\bean\model\impl
folder.Here are the AbstractMemberDefinition.class and AbstractMemberDefinition$1.class files I compiled to support 4 spring annotations; @Component
, @Service
, @Repository
and @Controller
. I hope they save some time for somebody one day.
I hope somebody will publish the result of https://issues.jboss.org/browse/JBIDE-25748 in the future and we will just laugh remembering these days and all the coding we have done because of our laziness. :)