Explicit binding required with MapBinder - Guice 4.0 beta4 - java

I tried to update my Guice version from 4.0-beta to 4.0-beta4 this morning and I started having problems with the MapBinder. I have a base module that extend JerseyServletModule. In the configureServlets() method, I do :
MapBinder<String, ExportData> exportDataMapBinder = MapBinder.newMapBinder(binder(),String.class,ExportData.class);
binder().requireExplicitBindings();
bindCommonServices();
install(new V8Module(exportDataMapBinder));
I populate the map in private modules, like this :
exportDataMapBinder.addBinding(VERSION).to(ExportDataV8.class);
ExportData is an interface and ExportDataV8 implements it (I won't paste them to keep the question short).
It worked just fine using guice 4.0-beta, but with guice 4.0-beta4, I started having errors like this :
1) Explicit bindings are required and com.coveo.ua.data.export.ExportData annotated with #com.google.inject.multibindings.Element(setName=, uniqueId=2, type=MAPBINDER) is not explicitly bound.
while locating com.coveo.ua.data.export.ExportData annotated with #com.google.inject.multibindings.Element(setName=, uniqueId=2, type=MAPBINDER)
at com.google.inject.multibindings.MapBinder$RealMapBinder$1.initialize(MapBinder.java:380)
at com.coveo.ua.config.UsageAnalyticsBaseModule.configureServlets(UsageAnalyticsBaseModule.java:223)
Anybody has an idea what I am doing wrong ?
Please tell me if I forgot to include important details.

I see from your example that you are setting that explict bindings are required for your main module. Just remove that method and it will surely work. Do not know what has been changed in 4.0-beta if that code worked before.
Your code:
MapBinder<String, ExportData> exportDataMapBinder = ...
binder().requireExplicitBindings();
Should probably remove this line:
binder().requireExplicitBindings();

I updated to Guice 4.0 beta 5 and it fixed my problem. As Tavian Barnes suggested. It was probably a bug with beta 4.

Related

Customizing swagger static resources with Springdoc

According to the documentation (see the link below) the static resources can be customized with Java by extending SwaggerIndexPageTransformer and overriding the transform method.
https://springdoc.org/#customizing-swagger-static-resources
As I understand the following files could be customized:
index.html
swagger-ui-bundle.js
swagger-ui.css
swagger-ui-standalone-preset.js
swagger-ui.css.map
swagger-ui-bundle.js.map
swagger-ui-standalone-preset.js.map
favicon-32x32.png
According to the example code I can check the name of the resource like:
if (resource.toString().contains("swagger-ui.css")) {
...
My problem is the only resource handled by this method is "META-INF/resources/webjars/swagger-ui/4.10.3/index.html"
Anybody had the same issue or do I misunderstand something?
I upgraded Spring to 2.7.0 and the issue disappeared.

Use Errai Ui with GWT

I'd really like to use Errai UI(3.2.4) in my GWT (2.8) application. I already have one setup with an EntryPoint implementation and an onModuleLoad. I have restGWT setup and interacting with my server (which uses Jersey).
All of the documentation I find assumes that you are building a full-on Errai project, starting from scratch using the forge addon thing. I'm not. I just want to use the templating stuff and data-binding. I'm working with a barebones setup and I can't even make a label show in my app.
I have this GWT entry point:
public class App implements EntryPoint
{
#Inject
private ApplicationContainer applicationContainer;
public void onModuleLoad()
{
RootPanel.get("root").add(applicationContainer);
}
}
And the ApplicationContainer:
#Templated
public class ApplicationContainer extends Composite
{
#DataField
private Element applicationContainer = DOM.createDiv();
#PostConstruct
public void init()
{
GWT.log("Initializing");
}
}
And it's accompanying template:
<div id="applicationContainer" data-field="applicationContainer">
Application Container
</div>
I should see "Application Container" in the browser, but I get this error in the browser console:
ComplexPanel.java:96 Uncaught TypeError: Cannot read property 'removeFromParent_0_g$' of undefined
The widget and the template are named the same and in the same package. My widget is created just like the documentation shows: http://erraiframework.org/getting-started/index.html#ErraiUIPage
Can someone tell me what I'm missing here? Examples for this are very minimal, and they all assume a complete Errai project. Do I still need an #EntryPoint? Do I need #PostConstruct? Is Errai even designed to work like this?
Thanks for any help.
Yes, the #EntryPoint annotation is important and I'm not sure you'll be able to mix up part of this framework with some other approach. It doesn't mean you need to use all the modules, but you should rather follow the Errai's guidelines if about the part you use.
Please see example entry point here:
https://github.com/errai/errai/blob/3.2.4.Final/errai-demos/errai-jpa-demo-todo-list/src/main/java/org/jboss/errai/demo/todo/client/local/ClientEntryPoint.java
You'll find also more examples from the path .../3.2.4.Final/errai-demos/
Above is about Errai 3.x.
Please also note that Errai 4.x brings some changes if it is just about the Errai UI. It's nicely described here:
http://errai-blog.blogspot.com/2016/04/errai-400beta1-released.html
Now your #Templated bean do not need to extend Composite. The root element of the template is accessible as a #DataField etc.
Hope you'll find it helpful. Good luck!
The answer to your questions is here: https://github.com/errai/errai-tutorial
You basically need to migrate your app to use Maven so you get the dependencies right first, then use the POM in this project and snap it in your project.
Then you can include a Bootstrap file to add a #EntryPoint class however this is not necessary you can just add a Page in the client path e.g.:
com.mycompany.app.client
-->MyPage.html
-->MyPage.java
Where the java file here contains the default page, i.e.
#Dependent
#Templated
#Page(role = DefaultPage.class)
public class MyPage extends Composite{}

com.liferay.portlet.ActionResponseImpl cannot be cast to com.liferay.portlet.ActionResponseImpl

I tried to cast Action response like this:
private void mappingMethod(ActionResponse response) {
ActionResponseImpl actionResponseImpl = (ActionResponseImpl)response;
...}
In debugging on "Expression Evaluation" window I can see the type of "responce" is ActionResponseImpl, and cast does not cause exception. But on runtime I have this exeption:
java.lang.ClassCastException: com.liferay.portlet.ActionResponseImpl cannot be cast to com.liferay.portlet.ActionResponseImpl
Please tell me what is the problem.
P.S.: In PortalImpl class, the copyRequestParameters method has same string, but here it's working....
It would do you good if you refrained from using classes from portal-impl.jar in your custom plugin portlet.
ActionResponseImpl is a class in the portal-impl.jar. So if you can give a use-case as to why you are planning to use this class, then we can suggest alternative.
You have ActionResponseImpl twice on the classpath - what jars from Liferay did you include in your project? As Prakash mentions, it's portal-impl.jar, which you can not have in a plugin.
What the ClassCastException wants to tell you is that your class extends one implementation of ActionResponseImpl, but the runtime environments expects it to be another implementation - they might be identical, but as they are loaded from two different sources, the classloader cannot refer one to another superclass than it extends.
I saw this issue, when I call a method using Ajax from XHTML page. I modified my method to return simple string and removed the code that tries to modify the actionResponseImpl and that resolved the issue.
This type of errors are produced by different classloaders. A class is identified by their fully qualified class name AND its Classloader. So if you embedd portal-impl in your portlet; the action is going to receive an ActionResponseImpl instance from the portal classloader and is trying to cast this one to a class of your portlet class loader .
see more: http://www.javaspecialists.eu/archive/Issue018.html

#NotThreadSafe not found error

0.3 code.
#NotThreadSafe
public class VoicemailPlaybackFragment extends Fragment {
//
}
I am getting compile time error as "NotThreadSafe cannot be resolved to a type"
i.e, #NotThreadSafe not imported
can anyone help, thanks in advance.
That annotation is not in the standard Java or Android codebases yet.
Depending on how and why you are using this, you should either add some third-party JAR containing it to your classpath, or just add a copy to your codebase.
This page lists a few products that include the annotation.

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