Error when trying to use Guava FluentIterable with GWT - java

I'm trying to use Guava 12.0's FluentIterable with GWT 2.0.3, like so:
import com.google.common.collect.FluentIterable;
class FooPresenter {
// snip
private List<NullSafeCheckBox> asCheckboxes() {
return FluentIterable.from(getDisplay().getMetricInputs())
.transform(new Function<HasValueChangeHandlers<Boolean>, NullSafeCheckBox>() {
#Override
public NullSafeCheckBox apply(#Nullable HasValueChangeHandlers<Boolean> checkbox) {
return (NullSafeCheckBox) checkbox;
}
})
.toImmutableList();
}
}
However, when I run GWT in dev mode, I get the following error when trying to load the first module:
DEBUG: Validating newly compiled units
ERROR: Errors in 'jar:file:/home/josh/.m2/repository/com/google/guava/guava-gwt/12.0/guava-gwt-12.0.jar!/com/google/common/math/super/com/google/common/math/LongMath.java'
ERROR: Line 23: The import java.math cannot be resolved
My pom.xml looks like this:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>12.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-gwt</artifactId>
<version>12.0</version>
</dependency>
And my Application.gwt.xml sucks in Guava like this:
<!-- Guava -->
<inherits name="com.google.common.collect.Collect"/>
Update
Following the advice in Arcadian's answer, I added gwt-math to my pom.xml and my Application.gwt.xml:
<!-- Guava -->
<inherits name="com.google.common.collect.Collect"/>
<inherits name="com.googlecode.gwt.math.Math" />
Now I get this error when running hosted mode:
DEBUG: Validating newly compiled units
WARN: Warnings in 'jar:file:/home/josh/.m2/repository/videoplaza-third-party/gwt-incubator/20100204-r1747/gwt-incubator-20100204-r1747.jar!/com/google/gwt/widgetideas/client/impl/GlassPanelImpl.java'
WARN: Line 30: Referencing deprecated class 'com.google.gwt.user.client.impl.DocumentRootImpl'
WARN: Line 38: Referencing deprecated class 'com.google.gwt.user.client.impl.DocumentRootImpl'
ERROR: Errors in 'jar:file:/home/josh/.m2/repository/com/google/guava/guava-gwt/12.0/guava-gwt-12.0.jar!/com/google/common/primitives/UnsignedLong.java'
ERROR: Line 77: The method bitLength() is undefined for the type BigInteger
ERROR: Line 79: The method longValue() is undefined for the type BigInteger
ERROR: Line 200: The method valueOf(long) is undefined for the type BigInteger
ERROR: Line 202: The method setBit(int) is undefined for the type BigInteger

You can try to add gwt-java-math project as dependency. As said on their wiki,
This library is in the process of getting merged into GWT itself!
Currently it is on GWT trunk.
It may be available in the upcoming v2.5.

FYI, it looks to me like java.math should be available in current versions of GWT, though probably not in 2.0.3. See, e.g., the JRE emulation reference for GWT 2.2, probably the first version where it was available.
I don't know what to expect in combination with gwt-java-math; possibly Guava itself would need to declare a dependency on its module for it to work?
We do need to do a much better of of determining and advertising which version of GWT is required for Guava, including running our GWT tests against Guava (and not just our internal version of it) to verify that.

Related

Getting exception when trying to add entry to PROTOSTREAM based cache in Wildfly

I want to use an Infinispan cache with a PROTOSTREAM marshaller in my app running on Wildfly 26.0.1.
I found the following post on StackOverflow, where both #MyKey_ and #Paul_Ferraro gave some excellent pointers on how to do it:
How to configure a custom Protostream serialization context initializer for Wildfly Infinispan subsystem?
I got quite far with this, but at the moment I am experiencing a stumbling block where I am getting an exception when trying to add an entry to this cache.
Before getting into detail about the error, I just wanted to give an overview of the stuff I have done so far.
As mentioned in the above StackOverflow post, I created a module in which I defined the Initializer as well as the annotated Java entity. For this exercise I copy and pasted from the Book/Author example provided in the Infinispan documentation.
In creating this module I used the following Gradle dependency snippet:
dependencies {
annotationProcessor "org.infinispan.protostream:protostream-processor:4.4.1.Final"
implementation "org.infinispan.protostream:protostream-processor:4.4.1.Final"
implementation 'org.infinispan.protostream:protostream:4.4.1.Final'
}
When doing the gradle build to create the module jar, the annotationProcessor automatically adds the files to META-INF, which #Paul_Ferraro mentioned.
I then copied the generated module to the modules folder in Wildfly, and added a module.xml, which looked as follows:
<module name="za.co.company" xmlns="urn:jboss:module:1.9">
<properties>
<property name="jboss.api" value="private"/>
</properties>
<resources>
<resource-root path="my-module.jar"/>
</resources>
<dependencies>
<module name="org.infinispan.protostream"/>
<module name="org.jboss.logging"/>
</dependencies>
</module>
I found that the dependencies tag were necessary, otherwise you get some link errors when Wildfly tries to load your module.
Next, I have added the following snippet to the Infinispan subsystem in my standalone-full-ha.xml:
<cache-container name="company" statistics-enabled="true" marshaller="PROTOSTREAM" modules="org.wildfly.clustering.infinispan.spi za.co.company">
<transport/>
<replicated-cache name="author">
<off-heap-memory size="1"/>
</replicated-cache>
</cache-container>
I can confirm that Wildfly indeed loads my module specified.
Now, I used the following code to test the Cache:
package za.co.company;
import org.jboss.ejb3.annotation.TransactionTimeout;
import za.co.company.Author;
import javax.annotation.Resource;
import javax.ejb.*;
import java.util.Map;
import java.util.concurrent.TimeUnit;
#Singleton
#Startup
#ConcurrencyManagement(ConcurrencyManagementType.BEAN)
#AccessTimeout(value = 1, unit = TimeUnit.HOURS)
#TransactionTimeout(value = 1, unit = TimeUnit.HOURS)
public class BookCache {
#Resource(lookup="java:jboss/infinispan/cache/company/author")
private Map<String, Author> cache2;
#Schedule(hour = "*", minute = "*/1", persistent = false)
void testCache() {
cache2.put("entry1", new Author("Johan", "Steenkamp"));
}
}
When trying to add the entry to the Cache, I get the following exception:
Caused by: org.infinispan.commons.marshall.MarshallingException: ISPN000615: Unable to unmarshall 'za.co.company.Author' as a marshaller is not present in the user or global SerializationContext
at org.infinispan#12.1.7.final//org.infinispan.encoding.protostreamtranscoder.getctxformarshalling(protostreamtranscoder.java:198)
at org.infinispan#12.1.7.final//org.infinispan.encoding.protostreamtranscoder.marshall(protostreamtranscoder.java:127)
at org.infinispan#12.1.7.final//org.infinispan.encoding.protostreamtranscoder.transcode(protostreamtranscoder.java:68)
at org.infinispan#12.1.7.final//org.infinispan.encoding.dataconversion.tostorage(dataconversion.java:227)
at org.infinispan#12.1.7.final//org.infinispan.cache.impl.encodercache.valuetostorage(encodercache.java:105)
at org.infinispan#12.1.7.final//org.infinispan.cache.impl.encodercache.put(encodercache.java:698)
at org.infinispan#12.1.7.final//org.infinispan.cache.impl.abstractdelegatingcache.put(abstractdelegatingcache.java:449)
at deployment.Company.war//za.co.company.BookCache.testCache(BookCache.java:22)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImp
In order to debug this issue, I have added some source files from Wildfly and Infinispan, just to get an idea what was happening behind the scenes. I was debugging this in debug mode in IntelliJ, and encountered a couple of things that was strange.
Firstly, I added a breakpoint at the cach2.put line, and evaluated the following:
cache2.getCacheManager().getCacheManagerConfiguration().cacheContainer().serialization.marshaller()
In the results I spotted a field marshallersByClass. This was a HashMap and I could see an entry with Author.class as the key for the entry.
I also placed a breakpoint within the following method of ProtostreamTranscoder.java:
private ImmutableSerializationContext getCtxForMarshalling(Object o) {
Class<?> clazz = o instanceof Class<?> ? (Class<?>) o : o.getClass();
if (isWrappedMessageClass(clazz) || ctxRegistry.getUserCtx().canMarshall(clazz))
return ctxRegistry.getUserCtx();
if (ctxRegistry.getGlobalCtx().canMarshall(clazz))
return ctxRegistry.getGlobalCtx();
throw logger.marshallerMissingFromUserAndGlobalContext(o.getClass().getName());
}
The weird thing here is that evaluating both ctxRegistry.getUserCtx() and ctxRegistry.getGlobalCtx() and returns a HashMap that doesn't faintly resembles the HashMap I mentioned earlier.
Another thing I can also confirm is that my Initializer get registered in the class org.infinispan.protostream.impl.SerializationContextImpl upon startup via the method registerMarshaller, which adds it to the field marshallersByClass of that class.
However, when I do cache.put, it seems that a total different list of marshallers is used, to try and find my Marshaller.
Can someone try and point me in the right direction?
Thanks
I think the problem is that the 'za.co.company.Author' is resolving against your deployment module rather than your custom 'za.co.company' module.
Your application should not bundle this class (nor include its jar), but instead include a dependency on the 'za.co.company' module.
e.g.
/META-INF/MANIFEST.MF:
Dependencies: za.co.company services
N.B. This use case should be much simpler in WildFly 27. You will be able to marshall custom key/value types using ProtoStream without the need to bundle these types within a global module.
See: https://github.com/wildfly/wildfly/pull/15397

VScode Java/Maven environment problem different computers

Im using jdk1.8.0_191, jre1.8.0_191 and apache-maven-3.6.2.
I have a pretty big open liberty / maven project that uses the javax.xml.bind maven library :
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.4.0-b180830.0359</version>
</dependency>
The problem occurs on one pc, not on the other. The javax.xml.bind.*; is rendered different on the different computers causing compilation errors , for example im trying to use the class
JAXBContext.newInstance(Class.class)
which works fine on one computer since the method that i can peek definition is as follows:
public static JAXBContext newInstance( Class... classesToBeBound )
throws JAXBException {
return newInstance(classesToBeBound,Collections.<String,Object>emptyMap());
}
But on my ohter pc the class method is rendered like :
public static javax.xml.bind.JAXBContext newInstance(java.lang.String pPath) throws javax.xml.bind.JAXBException {
return null;
}
This causes compilation error like
The method newInstance(String) in the type JAXBContext is not applicable for the arguments (Class<FormObject>)
Also the JAXContext.class file in the none working one has the comment above
// Failed to get sources. Instead, stub sources have been generated by the disassembler.
// Implementation of methods is unavailable.
, and the one that is working has a bunch of documentation.
There's more bugs from the javax.xml.bind.*; lib like that javax.xml.bind.Marshaller for instance. Ive tried to do mvn clean install but nothing seems to fix this issue!

swagger-maven-plugin triggers Javadoc warning: element value must be a constant expression (but it is!) in Java annotation

Javadoc (via Maven) is giving me the following error in one my Java JAX-RS interface method signatures:
error: element value must be a constant expression
Here is my JAX-RS interface:
public interface FooResource {
#Consumes(APPLICATION_FORM_URLENCODED_UTF_8)
public void bar();
}
Javdoc gives the error for #Consumes. Here is the definition for APPLICATION_FORM_URLENCODED_UTF_8, which appears in MyAppConstants in the same project:
public static final String APPLICATION_FORM_URLENCODED_UTF_8 =
APPLICATION_FORM_URLENCODED + ";" + CHARSET_PARAMETER + "=UTF-8";
And here is the definition of APPLICATION_FORM_URLENCODED, which appears in javax.ws.rs.core.MediaType:
public final static String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded";
And here is the definition of CHARSET_PARAMETER, which also appears in javax.ws.rs.core.MediaType:
public static final String CHARSET_PARAMETER = "charset";
Now I ask you: what about APPLICATION_FORM_URLENCODED_UTF_8 is not constant at compile time?
The error message didn't say that I have to provide a literal. It said I had to provide a constant. So what about this is not a constant?
(I could almost swear that this worked at one time but suddenly stopped working.)
Update: Found cause, but still don't understand.
For some reason, merely including the swagger-maven-plugin in the POM will trigger this problem! My code doesn't change at all, but as soon as I add the following dependency, suddenly I get Javadoc warnings for my existing code!!!
<dependency>
<groupId>com.github.kongchen</groupId>
<artifactId>swagger-maven-plugin</artifactId>
<version>3.1.5</version>
</dependency>
How can a single dependency make Javadoc work differently on a code file? What is swagger-maven-plugin doing?
My best guess is that this happens because swagger-maven-plugin transitively (via io.swagger:swagger-core:1.5.13) an old version of the JAX-RS specification in javax.ws.rs:jsr311-api:1.1.1. Note that the JAX-RS 2 artifact ID is javax.ws.rs-api, Maven doesn't realize that they are different versions of the same JAR, and pulls them both in as dependencies. I can only guess that javax.ws.rs:jsr311-api in fact does not use constants for the variables in question. In any case, when I threw out swagger-maven-plugin and pulled in io.swagger:swagger-annotations (which was all I needed in this project for documentation), the problem went away.
See https://github.com/kongchen/swagger-maven-plugin/issues/543.

Truth.assertAbout and JavaSourceSubjectFactory.javaSource()

I'm writing an annotation processor and want to write some unit tests for it by using google-compile-testing and truth:
So I want to write a very simple unit test.
import static com.google.common.truth.Truth.assertAbout;
import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
#Test
public void componentOnConcreteClass() {
JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.NotAClass",
"package test;",
"",
"import my.annotation.MyAnnotation;",
"",
"#MyAnnotation",
"interface NotAComponent {}");
assertAbout(javaSource()).that(componentFile)
.processedWith(new MyProcessor())
.failsToCompile()
.withErrorContaining("interface");
}
So basically I have copy an pasted a simple test from google's dagger2 repo and replaced the relevant data with my annotation processor.
I'm using maven, and I'm using the same dependencies as dagger2:
<dependency>
<groupId>com.google.testing.compile</groupId>
<artifactId>compile-testing</artifactId>
<version>0.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
But I can't compile the code. I guess there is an generics param problem, but can't figure out what the problem is.
Compilation failure:
[ERROR] ProcessorTest.java:[46,5] method assertAbout in class com.google.common.truth.Truth cannot be applied to given types;
[ERROR] required: com.google.common.truth.SubjectFactory<S,T>
[ERROR] found: com.google.testing.compile.JavaSourceSubjectFactory
[ERROR] reason: no instance(s) of type variable(s) S,T exist so that argument type com.google.testing.compile.JavaSourceSubjectFactory conforms to formal parameter type com.google.common.truth.SubjectFactory<S,T>
Any hint what I'm doing wrong? I can't find any difference to google dagger2 tests (which by the way compiles on my machine)
The artifact com.google.testing.compile:compile-testing:0.5 depends on org.truth0:truth:0.15 which is the old location of Truth. Try using version 0.6 of compile-testing instead.

Is there a way to ignore a single FindBugs warning?

With PMD, if you want to ignore a specific warning, you can use // NOPMD to have that line be ignored.
Is there something similar for FindBugs?
The FindBugs initial approach involves XML configuration files aka filters. This is really less convenient than the PMD solution but FindBugs works on bytecode, not on the source code, so comments are obviously not an option. Example:
<Match>
<Class name="com.mycompany.Foo" />
<Method name="bar" />
<Bug pattern="DLS_DEAD_STORE_OF_CLASS_LITERAL" />
</Match>
However, to solve this issue, FindBugs later introduced another solution based on annotations (see SuppressFBWarnings) that you can use at the class or at the method level (more convenient than XML in my opinion). Example (maybe not the best one but, well, it's just an example):
#edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
value="HE_EQUALS_USE_HASHCODE",
justification="I know what I'm doing")
Note that since FindBugs 3.0.0 SuppressWarnings has been deprecated in favor of #SuppressFBWarnings because of the name clash with Java's SuppressWarnings.
As others Mentioned, you can use the #SuppressFBWarnings Annotation.
If you don't want or can't add another Dependency to your code, you can add the Annotation to your Code yourself, Findbugs dosn't care in which Package the Annotation is.
#Retention(RetentionPolicy.CLASS)
public #interface SuppressFBWarnings {
/**
* The set of FindBugs warnings that are to be suppressed in
* annotated element. The value can be a bug category, kind or pattern.
*
*/
String[] value() default {};
/**
* Optional documentation of the reason why the warning is suppressed
*/
String justification() default "";
}
Source: https://sourceforge.net/p/findbugs/feature-requests/298/#5e88
Here is a more complete example of an XML filter (the example above by itself will not work since it just shows a snippet and is missing the <FindBugsFilter> begin and end tags):
<FindBugsFilter>
<Match>
<Class name="com.mycompany.foo" />
<Method name="bar" />
<Bug pattern="NP_BOOLEAN_RETURN_NULL" />
</Match>
</FindBugsFilter>
If you are using the Android Studio FindBugs plugin, browse to your XML filter file using File->Other Settings->Default Settings->Other Settings->FindBugs-IDEA->Filter->Exclude filter files->Add.
Update Gradle
dependencies {
compile group: 'findbugs', name: 'findbugs', version: '1.0.0'
}
Locate the FindBugs Report
file:///Users/your_user/IdeaProjects/projectname/build/reports/findbugs/main.html
Find the specific message
Import the correct version of the annotation
import edu.umd.cs.findbugs.annotations.SuppressWarnings;
Add the annotation directly above the offending code
#SuppressWarnings("OUT_OF_RANGE_ARRAY_INDEX")
See here for more info: findbugs Spring Annotation
At the time of writing this (May 2018), FindBugs seems to have been replaced by SpotBugs. Using the SuppressFBWarnings annotation requires your code to be compiled with Java 8 or later and introduces a compile time dependency on spotbugs-annotations.jar.
Using a filter file to filter SpotBugs rules has no such issues. The documentation is here.
While other answers on here are valid, they're not a full recipe for solving this.
In the spirit of completeness:
You need to have the findbugs annotations in your pom file - they're only compile time, so you can use the provided scope:
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>findbugs-annotations</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
This allows the use of #SuppressFBWarnings there is another dependency which provides #SuppressWarnings. However, the above is clearer.
Then you add the annotation above your method:
E.g.
#SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE",
justification = "Scanning generated code of try-with-resources")
#Override
public String get() {
try (InputStream resourceStream = owningType.getClassLoader().getResourceAsStream(resourcePath);
BufferedReader reader = new BufferedReader(new InputStreamReader(resourceStream, UTF_8))) { ... }
This includes both the name of the bug and also a reason why you're disabling the scan for it.
Finally you need to re-run findbugs to clear the error.
I'm going to leave this one here: https://stackoverflow.com/a/14509697/1356953
Please note that this works with java.lang.SuppressWarningsso no need to use a separate annotation.
#SuppressWarnings on a field only suppresses findbugs warnings
reported for that field declaration, not every warning associated with
that field.
For example, this suppresses the "Field only ever set to null"
warning:
#SuppressWarnings("UWF_NULL_FIELD") String s = null; I think the best
you can do is isolate the code with the warning into the smallest
method you can, then suppress the warning on the whole method.

Categories