Does Sonar support commons-lang StringUtils ?
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
Env:
INFO: SonarQube Scanner 3.2.0.1227
INFO: Java 1.8.0_121 Oracle Corporation (64-bit)
INFO: Linux 4.19.2-1.el7.elrepo.x86_64 amd64
Community EditionVersion 7.6 (build 21501)
code to reproduce this issue:
public class DetectorImport {
public String check1(Nonentity nonentity) {
String s;
if(nonentity == null) {
s = null;
}else {
s = nonentity.getName();
}
if(StringUtils.isNotBlank(s)) {
s = s.replaceAll("(", "(");
}
return s;
}
}
From this sonar google groups, it is mentioned that the common.langs methods are supported by sonar.
https://groups.google.com/forum/#!topic/sonarqube/aluTP63hfyA
Maybe another approach could be for you to use other utility classes, commonly used across Java projects. We currently support methods from commons-lang StringUtils (v2, and v3), guava preconditions, and java 8 methods from java.util.Objects (nonNull, isNull, requireNonNull). As we know how these methods behave, we are able to correctly handle such call and discard similar FPs. Of course, I don't want to force you using such libraries to make the analyzer happy. :)
changing above code to following one indeed solve this issue:
public class DetectorImport {
public String check1(Nonentity nonentity) {
String s;
if(nonentity == null) {
s = null;
}else {
s = nonentity.getName();
}
if(s !=null) {
s = s.replaceAll("(", "(");
}
return s;
}
}
The above question is copied from
https://community.sonarsource.com/t/commons-lang-stringutils-isnotblank-method-still-raise-npe/21517
Am not the OP in Sonar, but I provided my solution there. I had the exact same question, so I am copying the solution over to others who end up here.
We are using the SonarScanner and not the maven sonar plugin for our scans. And for us the issue was that the “sonar.java.libraries” variable was not properly set. I added the target “dependency:copy-dependencies” as part of the maven execution. This copied all the dependencies to the right location, then I set the property “-Dsonar.java.libraries=target/dependency” and everything started working as it's supposed to.
Related
A super-simple String.format("this is a test %d",5) doesn't work in my HelloWorld CodenameOne project: I get "error: cannot find symbol".
It doesn't seem to matter what format I used, I always get the same error. This seems to be an import problem, though I'm not importing any special packages outside of the defaults.
Here is the java source:
package com.test.test;
import static com.codename1.ui.CN.*;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.ui.Dialog;
import com.codename1.ui.Label;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.util.Resources;
import com.codename1.io.Log;
import com.codename1.ui.Toolbar;
import java.io.IOException;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.io.NetworkEvent;
/**
* This file was generated by Codename One for the purpose
* of building native mobile applications using Java.
*/
public class MyApplication {
private Form current;
private Resources theme;
public void init(Object context) {
// use two network threads instead of one
updateNetworkThreadCount(2);
theme = UIManager.initFirstTheme("/theme");
// Enable Toolbar on all Forms by default
Toolbar.setGlobalToolbar(true);
// Pro only feature
Log.bindCrashProtection(true);
/*
Updating property file: C:\Users\admin\Desktop\test2\build\built-jar.properties
Compile is forcing compliance to the supported API's/features for maximum device compatibility. This allows smaller
code size and wider device support
Compiling 1 source file to C:\Users\admin\Desktop\test2\build\tmp
C:\Users\admin\Desktop\test2\src\com\test\test\MyApplication.java:39: error: cannot find symbol
s = String.format("this is a test %d",5);
symbol: method format(String,int)
location: class String
1 error
C:\Users\admin\Desktop\test2\build.xml:62: Compile failed; see the compiler error output for details.
BUILD FAILED (total time: 0 seconds)
*/
String s;
s = String.format("this is a test %d",5);
addNetworkErrorListener(err -> {
// prevent the event from propagating
err.consume();
if(err.getError() != null) {
Log.e(err.getError());
}
Log.sendLogAsync();
Dialog.show("Connection Error", "There was a networking error in the connection to " + err.getConnectionRequest().getUrl(), "OK", null);
});
}
public void start() {
if(current != null){
current.show();
return;
}
Form hi = new Form("Hi World", BoxLayout.y());
hi.add(new Label("Hi World"));
hi.show();
}
public void stop() {
current = getCurrentForm();
if(current instanceof Dialog) {
((Dialog)current).dispose();
current = getCurrentForm();
}
}
public void destroy() {
}
}
CodenameOne compiles your source code using its own subset of the Java SE API, which is missing some features that the standard Java API includes.
Quoting their FAQ:
What features of Java are supported? What features of Java aren't supported?
The most obvious thing missing is reflections. The main problem is that when we package the VM into devices that don’t have Java, we would have to include EVERYTHING. If reflections were included, they wouldn’t work anyway since we obfuscate the code for the platforms where reflections do work (e.g. Android). On top of that reflection code is generally slow and a bad idea on a mobile device to begin with. As an alternative some developers were successful with bytecode manipulation which is something that is completely seamless to the server and as performant/efficient as handcoding.
Many of the desktop API’s such as java.net, java.io.File etc. aren’t very appropriate for mobile devices and just didn’t make it. We provide our own alternatives which are more portable and better suited for mobile settings.
Of the other missing things, if you run into a missing method or ability, there are cases where that functionality can be added.
Specifically, its version of java.lang.String does not include the format method.
In this case, it can be rewritten using simple string concatenation:
String s = "this is a test " + 5;
I'm trying to solve a problem with my Java project and one of the possible solutions is to change jdk.io.File.enableADS to TRUE in system properties. But, i don't know how to change it.
I'm also working in a project that uses jhipster and undertow. My project builds with no error, generating the connection link, but when I try to connect the page it doesn't load and the application shows the error:
java.lang.NoClassDefFoundError: Could not initialize class org.xnio.conduits.Conduit
I've looked at the code, found the line that throws the error and I saw in many blogs people telling to change the config above the text.
I'm using the JDK 11.0.15
This is the code that throws the error:
try {
if (osName.contains("windows")) {
return new FileOutputStream("NUL:").getChannel();
} else {
return new FileOutputStream("/dev/null").getChannel();
}
} catch (FileNotFoundException e) {
throw new IOError(e);
}
It seems you're running into this problem: Java: FileOutputStream("NUL:") not working after Java upgrade
The code you're referencing that is causing the problem is from https://code.yawk.at/org.jboss.xnio/xnio-api/3.8.4.Final/org/xnio/conduits/Conduits.java
static {
NULL_FILE_CHANNEL = AccessController.doPrivileged(new PrivilegedAction<FileChannel>() {
public FileChannel run() {
final String osName = System.getProperty("os.name", "unknown").toLowerCase(Locale.US);
try {
if (osName.contains("windows")) {
return new FileOutputStream("NUL:").getChannel();
} else {
return new FileOutputStream("/dev/null").getChannel();
}
} catch (FileNotFoundException e) {
throw new IOError(e);
}
}
});
}
I've looked at the sources for this release (3.8.4) and the most recent release on maven central (3.8.7): https://mvnrepository.com/artifact/org.jboss.xnio/xnio-api/3.8.7.Final
And there is some good news, it has been fixed in the latest release of xnio-api. The current code in version 3.8.7 is now as follows: (NUL: was replaced by NUL)
if (osName.contains("windows")) {
return new FileOutputStream("NUL").getChannel();
} else {
return new FileOutputStream("/dev/null").getChannel();
}
So if it's possible i would suggest you try to upgrade your dependency so that xnio-api-3.8.7.Final.jar is used.
Update 09-2022
Thanks to the comment of #NicolasRiousset, who found the following issue logged on jhipster's github, i have further traced this problematic dependency.
It starts with the optional dependency to spring-boot-starter-undertow, which in turn depends on undertow-core, and that depends on xnio-api from Jboss.
The earliest version that includes the fix (xnio-api-3.8.7) can be found in undertow-core 2.2.18.Final. The earliest version that uses this is spring-boot-starter-undertow 2.7.1.
And JHipster starts including spring-boot version >= 2.7.1 from jhipster-framework 7.9.0.
So upgrading to JHipster >= 7.9.0 should fix this problematic xnio-api dependency.
In case you don't strictly need undertow as your embedded web server, you can also switch (back) to spring-boot-starter-tomcat, since tomcat doesn't use the xnio-api.
Otherwise the mentioned system property should indeed also be a valid workaround for now. Since the code is statically loaded, i think you'll have to use VM arguments to include it in your program instead of using System.setProperty.
So add -Djdk.io.File.enableADS=true to your programs startup/command line.
See for reference the following question that was mentioned in the comments: How to set system property?
It does also seem to be fixed in newer version of the Java runtime, so upgrading your JDK/JRE is also an option. According to the linked question at the top it's fixed in Java 8u333, and on my test system with Java 17.0.2 both versions of NUL also work.
I ran into this same issue. I closed and reopened IntelliJ. Now it works. Worth trying before getting too deep down the rabbit hole.
I have this Java code:
public class Calc {
public int quotient(int a, int b){
return a/b;
}
}
and TestNG unit test for this method:
#Test ()
public void testingMethod3() {
Assert.assertEquals(0, calc.quotient(5,0));
}
On my work computer I successfully get
java.lang.ArithmeticException: / by zero
message, as expected.
But when my colleague runs this test on home computer, then mentioned exception is not throwing and test passes.
How this magic could occur?
P.S.
Environment
OS: Windows 10
TestNG version: 6.13.1
Java version: 8 (don't know exact build version)
P.P.S.
Deletion of target folder and rebuilding of the project was that very helpful solution. Seem like IDE cashed old project sources, and didn't flush them after changes in the code.
In the past, I experienced something like yours. Because different JDK compile environment and/or JRE runtime environment. And need check the different of version of TestNG.
check by add few line of code to print Java properties.
Properties p = System.getProperties();
Enumeration keys = p.keys();
while (keys.hasMoreElements()) {
String key = (String)keys.nextElement();
String value = (String)p.get(key);
System.out.println(key + ": " + value);
}
then comparing
I have a small Unity3d project to integrate JAR with it. My (simplified) java class in Android Studio library project is like below code:
package com.playsqreen.library.api;
... imports ...
public class PlaysreenAPI {
private static PlayscreenAPI _api;
private PlayscreenAPI(Activity activity) {
this.activity = activity;
}
// static method to create singleton
public static PlayscreenAPI build(Activity activity, String key) {
if (_api == null) {
// post processing something
// before returning instance of this class
_api = new PlayscreenAPI(activity);
}
return _api;
}
public String doEchoThis(String msg) {
return "ECHO: " + msg;
}
}
So from Android Studio, I generate my JAR and dump it into ../MyProject/Assets/Plugins/Android and from Unity IDE I can see something like below:
Then I create a C# script like below to load my java class:
void Start () {
_builder = new StringBuilder();
try
{
_builder.Append(">>> Step 1\n");
AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
if (activityClass != null)
{
_builder.Append(">>> Step 2\n");
AndroidJavaObject activity = activityClass.GetStatic<AndroidJavaObject>("currentActivity");
if (activity != null)
{
_builder.Append(">>> Step 3\n");
AndroidJavaClass apiClass = new AndroidJavaClass("com.playsqreen.library.api.PlayscreenAPI");
if (apiClass != null)
{
_builder.Append(">>> Step 4\n");
object[] args = { activity, secretKey };
api = apiClass.CallStatic<AndroidJavaObject>("build", args);
}
}
}
}
catch (System.Exception e)
{
_builder.Append(e.StackTrace.ToString());
}
}
I print my StringBuilder in Text UI object in order for me to capture on which Step my code brakes, and it turns out after step 3. and my Text UI object prints:
java.lang.ClassNotFoundException:com.playsqreen.library.api.PlayscreenAPI and etc...
A thread I found here suggest me to use Java Decompiler to check if the java class really included in the Jar, from this site. And so I did, and the Java Decompiler shows my java class does exists (see below)
So I really stuck now. How can I load my java class from Unity? Please help.
Thanks.
After following lysergic-acid advice below, I includes the rest of jars that required by my custom jar, see below pic. And everything fine :)
You did not post the full error message you are getting at runtime. Also you did not mention which of your debug prints get printed, so i'll try to come up with a few different issues that you can check. Hopefully, one of these can assist in fixing the issue:
JAR name contains '.' (period character). Not sure how Unity interprets this (i've never used such a naming convention myself). Select the .JAR file in Unity and make sure that Unity marks it up as an Android plugin (should have "Android" selected in the plugin importer. I would also try to rename that to a name without any periods just to be on the safe side.
Wrong invocation of the Java method: in your example, the static method build in Java receives a single argument (Activity), but when you're calling it from Unity, you're passing an array of 2 arguments.
Missing dependencies: When your native Java code relies on other classes (e.g: from other libraries), in case you do not include these libraries with your .JAR file, your class will not be loaded at runtime and it will fail with cryptic errors such as NoClassDefFoundException. Make sure to include all dependencies as well.
**Shameless Promotion: ** I offer services to fix Android related issues in Unity. Check it out here, in case you're interested :)
Install newest JDK version and try again.
After some problems with differences between JSE versions, I'm trying to log the Java compiler version used to compile (it's Groovy 2.1.9, Grails 2.3.8, Java 1.7.0_60 in fact).
After some rummaging around, I've constructed this piece of code to read the leading bytes of the class - see /http://en.wikipedia.org/wiki/Java_class_file#General_layout
(change the path to the class to match the package name):
class CompilerVersionSupport {
public static String getVersion() {
String classAsPath = 'com/my/organisation/CompilerVersionSupport.class';
InputStream stream = (new CompilerVersionSupport()).getClass().getClassLoader().getResourceAsStream(classAsPath);
DataInputStream ins = new DataInputStream (stream)
assert( ins.readUnsignedShort() == 0xcafe )
assert( ins.readUnsignedShort() == 0xbabe )
int minor = ins.readUnsignedShort();
int major = ins.readUnsignedShort();
ins.close();
int javaVersion = major - 44
return "1.$javaVersion"
}
}
Trouble is, it returns 1.5.
What could be going on?
Charles
The default Groovy behaviour is not to compile the code with the same bytecode version as the JDK being used. 1.5 is the default for compatibility reasons, IMHO. If you want the compiler to output newer bytecode you need to set that explicitly.
For example if you're using Maven to compile the code, you can use the GMavenPlus plugin. See the description of the targetBytecode parameter.
If you're not using Maven you can use -Dgroovy.target.bytecode=1.7 or research the possibilities for your particular build tool
If you're using Maven as the build tool, then chances are that it's using the gmavenplus-plugin to compile Groovy. To find out the target Java version of the bytecode generated I poked into the pom of the gmavenplus-plugin that my application uses: ~/.m2/repository/org/codehaus/gmavenplus/gmavenplus-plugin/1.5/gmavenplus-plugin-1.5.pom.
Inside that file I saw this, notice <javaVersion/>,
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<mavenVersion>2.2.1</mavenVersion>
<coberturaPluginVersion>2.7</coberturaPluginVersion>
<javadocPluginVersion>2.10.1</javadocPluginVersion>
<!-- these are properties so integration tests can use them -->
<javaVersion>1.5</javaVersion>
<dependencyPluginVersion>2.10</dependencyPluginVersion>
<compilerPluginVersion>3.2</compilerPluginVersion>
<junitVersion>4.12</junitVersion>
<surefirePluginVersion>2.18.1</surefirePluginVersion>
<pluginPluginVersion>3.4</pluginPluginVersion>
<!-- this is a property so that site generation can use it -->
<sourcePluginVersion>2.4</sourcePluginVersion>
<!-- this is a property so that site generation and integration tests can use it -->
<groovyVersion>2.4.1</groovyVersion>
</properties>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compilerPluginVersion}</version>
<configuration>
<source>${javaVersion}</source>
<target>${javaVersion}</target>
</configuration>
</plugin>
I use IntelliJ for an IDE. IntelliJ is automatically setting the language level to Java 1.5. Even if I change it, when I re-import projects it resets back to Java 1.5 (I've fuzzed out sensitive information),
I think the issue is with the program you are using to find the class version. If the assertion is not enabled the stream doesnt read the first two unsigned shorts and hence the subsequent minor and major read statements results in 0Xcafe and 0xbabe respectively. Try enabling assertion or try using an if check.
public static String getVersion() throws Exception {
String classAsPath = "com/my/organisation/CompilerVersionSupport.class";
InputStream stream = (new CompilerVersionSupport()).getClass().getClassLoader().getResourceAsStream(classAsPath);
DataInputStream ins = new DataInputStream(stream);
if(ins.readUnsignedShort() != 0xcafe) throw new AssertionError("Invalid Class");
if(ins.readUnsignedShort() != 0xbabe) throw new AssertionError("Invalid Class");
int minor = ins.readUnsignedShort();
int major = ins.readUnsignedShort();
ins.close();
int javaVersion = major - 44;
return "1." + javaVersion;
}