Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Friday, July 8, 2022

Java: no such provider: BC


Problem:

java.security.NoSuchProviderException: no such provider: BC


Solution:

1. Download Bouncy Castle JAR, e.g.: bcprov-jdk15on-157.jar

2. In the code, add:

  if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null)
  {
    Security.addProvider(new BouncyCastleProvider());
  }


Friday, August 13, 2021

Java: set command line parameters via environment variable


Instead of:

> java -Xmx256M ...

 

We can:

> set JAVA_TOOL_OPTIONS=-Xmx256M

> java ...


JAVA_TOOL_OPTIONS may not work with jvm.dll. For that we can try _JAVA_OPTIONS. e.g.

> set _JAVA_OPTIONS=-Xmx256M

Tuesday, June 29, 2021

Java ldd


For a C++ library, we can use command ldd to list the dependencies. There isn't such a official tool for the Java. However, if the source code is available, we can build the JAR using javac with the verbose mode turned on. The location of all the dependent JARs will be listed during the build.

Wednesday, May 5, 2021

Spring Boot: escape HTML and non-ASCII characters in Json response


Create an ObjectMapper object and let Spring Boot use our ObjectMapper object with the @Bean and @Primary annotations.

In our configuration bean:

@Configuration
public class MyConfiguration {
 
  @Bean
  @Primary
  public ObjectMapper objectMapper() {
    // create our own ObjectMapper object.
    ObjectMapper objMapper = new ObjectMapper();
 
    // escape all non-ASCII characters
    objMapper.enable(JsonGenerator.Feature.ESCAPE_NON_ASCII);

    // definition of the HTML characters to escape
    final class HtmlCharsToEscape extends CharacterEscapes
    {
      private final int[] asciiEscapes;
    
      public
HtmlCharsToEscape()
      {
        // get the set of default escaped characters (double-quote, backslash etc)
        int[] esc = CharacterEscapes.standardAsciiEscapesForJSON();
        // and force escaping of HTML special characters:
        esc['<'] = CharacterEscapes.ESCAPE_STANDARD;
        esc['>'] = CharacterEscapes.ESCAPE_STANDARD;
        esc['&'] = CharacterEscapes.ESCAPE_STANDARD;
        esc['\''] = CharacterEscapes.ESCAPE_STANDARD;
        asciiEscapes = esc;
      }

      @Override public int[] getEscapeCodesForAscii() {
        return asciiEscapes;
      }

      @Override public SerializableString getEscapeSequence(int ch) {
        // no CUSTOM escaping needed:
        return null;
      }
    }

    // Escape the HTML special characters.
    objMapper.getFactory().setCharacterEscapes(new
HtmlCharsToEscape());
 
    // This will be picked up the Spring Boot.
    return objMapper; 
  }
}



Monday, May 3, 2021

Elipse: debug Maven project with JUnit


1. Set the breakpoints.

2. Right click on the JUnit test Java class. On the popup menu, select Debug as... -> JUnit.

Wednesday, March 24, 2021

Docker commands and Dockerfile examples


To install docker on fedora

$ sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo

$ sudo dnf install docker-ce docker-ce-cli containerd.io 

$ sudo systemctl start docker

$ sudo docker run hello-world


To build and run an image

First, create a Dockerfile under the current directory (see below).

$ sudo docker build -t myimagename:myimageversion .

$ sudo docker  run -p 8888:8080 myimagename:myimageversion

or 

$ sudo docker run --net=host myimagename:myimageversion


Other commands

$ sudo docker image ls

$ sudo docker rmi image-hash

$ sudo docker ps -as

$ sudo docker rm container-hash

$ sudo docker run -it myimagename:myimageversion bash


Dockerfile of adding self CA and Bouncy Castle jar

FROM tomcat:9.0.44-jdk8

# Add myCA certificate

ADD myCA.crt /usr/local/share/ca-certificates/

RUN chmod 644 /usr/local/share/ca-certificates/myCA.crt && update-ca-certificates

# Add Bouncy Castle provider

RUN echo '' >> "/usr/local/openjdk-8/jre/lib/security/java.security"

RUN echo 'security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider' >> "/usr/local/openjdk-8/jre/lib/security/java.security"

ADD bcprov-jdk15on.jar /usr/local/openjdk-8/jre/lib/ext/

# Add web app

ADD myapp.war  /usr/local/tomcat/webapps/

EXPOSE 8080

CMD ["catalina.sh", "run"]



Tuesday, March 16, 2021

Eclipse cannot connect to a server due to certification error


If "Install New Software" fails in Eclipse and it complains that the server's certificate is not trusted, that may be because the Java instance that Eclipse uses does not have the needed CA in its keystore.

Another symptom is that when you try to access Eclipse Marketplace in Eclipse (Help|Eclipse Marketplace...), exceptions are thrown complaining about the server certificate.

Usually Eclipse uses the Java in the system, and you can simple add the CA into the keystore following this post.

Sometimes Eclipse uses a different Java instance and to find out which one it is, you need to go to the installation of Eclipse and find this file eclipse.ini. Use a text editor to open it. Find the line -vm. Under it is the Java instance that Elipse uses.

Go to where the Java instance locates, and enter its lib/security/ directory. Follow this post to add the new CA to cacerts, e.g.:

$ keytool -import -alias CloudService -keystore cacerts -file "/path/to/CloudServiceRootCA.cer"


Monday, January 18, 2021

Spring application unit tests context refreshing


If Mockito is used to mock a Spring singleton bean in one test class, it may impact the second test class so that test cases in the 2nd test class could fail.

It appears that all test cases are successfuly if the 2 test classes are run independently, but when they are run together, the test cases in the 2nd test class would fail.

In that case, @DirtiesContext annotation can be used on the 1st test class. It indicates that the ApplicationContext associated with a test is dirty. After the test, the ApplicationContext would be closed and removed from the context cache. The test cases from the 2nd test class can be run independently from the 1st test class.


Friday, May 8, 2020

Mockito error: You cannot use argument matchers outside of verification or stubbing


There may be many reasons can cause this error. But in this case, this error was wrongly spit out when I wrote:

when(myObject.myMethod(any(), any())).thenReturn("something");

It turned out that it is because the first parameters of myObject.myMethod(int, String) is expecting an int. So that the correction is:

when(myObject.myMethod(anyInt(), any())).thenReturn("something");



Tuesday, May 5, 2020

java.security.NoSuchProviderException - no such provider: BC


1. Download the latest BouncyCastle library, e.g. bcprov-jdk15on-165.jar

2. Copy the JAR file to $JAVA_HOME/jre/lib/ext/.

3. Edit file $JAVA_HOME/jre/lib/security/java.security. Add the following:
security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider

(Note: if you have 10 providers or more already, adjust the number 10 to a higher number accordingly.)

Ref: https://docs.oracle.com/cd/E19830-01/819-4712/ablsc/index.html

Tuesday, September 3, 2019

Java programming: use Matcher to replace patterns with captured groups (code example)


String str = "=123-abc=   =7890-ABCD=";
Pattern pattern = Pattern.compile("=([0-9]*)-([A-Za-z]*)=");
Matcher matcher = pattern.matcher(str);
if (matcher.find())
{
    str = matcher.replaceAll("# $2 + $1 #");
}

System.out.println(str);


The output will be:
# abc + 123 #   # ABCD + 7890 #

Saturday, May 4, 2019

Android: how to prevent soft keyboard from showing up on activity startup


If the first widget of the activity is an EditText, it will get focus when the activity starts and the soft keyboard will automatically show up. This behavior, however, is not desired sometimes. To hide the soft keyboard in this situation, we can add this code in the onCreate() method of the activity or the onCreateView().

    protected void onCreate(Bundle savedInstanceState) {
... ...      getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

... ...
}

or

    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
... ...        getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
... ...

}



Monday, April 22, 2019

Java: example of Lambda Expressions and Method References


In this post, we showed an example of using anonymous class in the forEach method to loop over a list.

stringList.forEach(new Consumer<String>() {
    @Override
    public void accept(String s) {
        String oneItem = s;
        System.out.println(oneItem);
    }
});


Because the Consumer interface is a functional interface (https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html), the above code can be simplified with Lambda Expressions (https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html)


stringList.forEach((s) -> {
        String oneItem = s;
        System.out.println(oneItem);
});


or even:

stringList.forEach(s -> System.out.println(s));

And because the above Lambda Expresso does nothing but call only an existing method, we can use Method References to write the code this way:

stringList.forEach(System.out::println);


Saturday, April 20, 2019

Java: four ways of looping over a List


List<String> stringList = new LinkedList<String>();
stringList.add("item1");
stringList.add("item2");
stringList.add("item3");

System.out.println("loop 1:");
for (int i = 0; i < stringList.size(); i++) {
    String oneItem = stringList.get(i);
    System.out.println(oneItem);
}

System.out.println("loop 2:");
Iterator<String> iterator = stringList.iterator();
while (iterator.hasNext()) {
    String oneItem = iterator.next();
    System.out.println(oneItem);
}

System.out.println("loop 3:");
for (String oneItem : stringList) {
    System.out.println(oneItem);
}

// Supported by Java 8 and plus
System.out.println("loop 4:");
stringList.forEach(new Consumer<String>() {
    @Override
    public void accept(String s) {
        String oneItem = s;
        System.out.println(oneItem);
    }
});


With the use of Lambda Expressions and Method References (explained in this post), the last loop can be replaced with:

stringList.forEach(System.out::println);


The output of the above four loops in the example is:
loop 1:
item1
item2
item3
loop 2:
item1
item2
item3
loop 3:
item1
item2
item3
loop 4:
item1
item2
item3

Tuesday, April 16, 2019

Example of using Checkstyle for coding standard


As it claims on its web site, Checkstyle is a development tool to help programmers write Java code that adheres to a coding standard. It can be downloaded from http://checkstyle.sourceforge.net/. The downloadable binary is a JAR file, e.g. checkstyle-8.19-all.jar.

If you want to follow the Google Java Style (https://google.github.io/styleguide/javaguide.html), you can run Checkstyle with the built-in Google style like this:

$ java -jar checkstyle.jar -c /google_checks.xml MyClass.java

-- checkstyle.jar is the downloaded JAR file from the Checkstyle's site.
-- /google_checks.xml tells Checkstyle to use the built-in style.

You may write your own style but a more convenient way is to download one of the default style configuration and modify it to suit your needs.

For example, the built-in google_checks.xml defines the code indentation offset as 2. If we want to set it to 4 for our own use, we can download google_checks.xml from https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml. Open it with a text editor, look for the Indentation section and change the values from 2 to 4, and 4 to 8:

        <module name="Indentation">
            <property name="basicOffset" value="4"/>
            <property name="braceAdjustment" value="0"/>
            <property name="caseIndent" value="4"/>
            <property name="throwsIndent" value="8"/>
            <property name="lineWrappingIndentation" value="8"/>
            <property name="arrayInitIndent" value="4"/>
        </module>


Then we save the file as my_style_checks.xml.

To use a customized configuration, we run Checkstyle as:

$ java -jar checkstyle.jar -c /path/to/my_style_checks.xml MyClass.java

-- after -c we need to specify the absolute or relative path to the new style file we created.

Monday, April 8, 2019

Java: return more than one result from a method


There are many ways to return multiple results from a method. Here are two of the most simple and typical ways:

public class ExampleTest {

    public void returnMultiple() {
        // Return multiple strings        String[] strArray = returnArray();
        System.out.println("Result from returnArray():");
        System.out.println(strArray[0]);
        System.out.println(strArray[1]);

        // Return boolean and string        ResultObj resultObj = returnObj();
        System.out.println("Result from returnObj():");
        System.out.println(resultObj.boolResult);
        System.out.println(resultObj.strResult);
    }

    private String[] returnArray() {
        String[] results = new String[2];

        results[0] = "result 1";
        results[1] = "result 2";

        return results;
    }

    public class ResultObj {
        public boolean boolResult;
        public String strResult;
    }

    private ResultObj returnObj() {
        ResultObj results = new ResultObj();

        results.boolResult = true;
        results.strResult = "result string";

        return results;
    }
}
 
The first way is to return an Array of the same types. We can set each item of the array inside the method. And the caller and reach them by the array.

The second way is to create a Class with multiple members. Each member holds a result. By returning an object of this Class, the caller can access the results via the Class.

The returnMultiple() method in the example will output:
Result from returnArray():
result 1
result 2
Result from returnObj():
true
result string



Friday, April 5, 2019

Java: Convert byte array to String then back to byte array


The following code works for converting a String to a byte array then back to a String:

String s1 = "Hello World!";
byte[] sb = s1.getBytes();
String s2 = new String(sb);
System.out.println(s1.equals(s2));

The output will be "true".

However, it won't work when using the similar way to convert a byte array to String then back to a byte array.

byte[] b1 = new byte[]{-100, -128, -1, 1, -10, 100, 33, -13, 32, 87};
String bs = new String(b1);
byte[] b2 = bs.getBytes();
System.out.println(Arrays.equals(b1, b2));

The output will be "false".

That is because not every byte can be converted into a character.

One way of doing that would be to convert the byte array to a Base64 encoded string, then you can later decode the string back to a byte array.

byte[] b1 = new byte[] {-100, -128, -1, 1, -10, 100, 33, -13, 32, 87};
String bs = Base64.getEncoder().encodeToString(b1);
byte[] b2 = Base64.getDecoder().decode(bs);
System.out.println(Arrays.equals(b1, b2));

The output will be "true".

The above implementation uses the Base64 class in Java 8. If you are using an earlier version of Java, you need import other implementations of Base64.


Saturday, March 30, 2019

Java: AES encryption example


Encryption:
byte[] encrypt(byte[] plainText, String keySeed, byte[] iv) {
    if (plainText == null || iv == null)
        return null;

    try {
        SecretKey key = getSecretKey(keySeed);

        IvParameterSpec ivParm = new IvParameterSpec(iv);

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, key, ivParm);
        byte[] cipherText = cipher.doFinal(plainText);
        return cipherText;
    } catch (NoSuchAlgorithmException ex) {
    } catch (NoSuchPaddingException ex) {
    } catch (InvalidKeyException ex) {
    } catch (BadPaddingException ex) {
    } catch (IllegalBlockSizeException ex) {
    } catch (InvalidAlgorithmParameterException ex) {
    }

    return null;
}

Decryption:
byte[] decrypt(byte[] cipherText, String keySeed, byte[] iv) {
    if (cipherText == null || iv == null)
        return null;
    
    try {
        SecretKey key = getSecretKey(keySeed);

        IvParameterSpec ivParm = new IvParameterSpec(iv);

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(Cipher.DECRYPT_MODE, key, ivParm);
        byte[] plaintext = cipher.doFinal(cipherText);
        return plaintext;
    } catch (NoSuchAlgorithmException ex) {
    } catch (NoSuchPaddingException ex) {
    } catch (InvalidKeyException ex) {
    } catch (BadPaddingException ex) {
    } catch (IllegalBlockSizeException ex) {
    } catch (InvalidAlgorithmParameterException ex) {
    }

    return null;
}

Helper methods:
byte[] generateIv() {
    SecureRandom random = new SecureRandom();
    byte bytes[] = new byte[16];
    random.nextBytes(bytes);

    return bytes;
}
 
SecretKey getSecretKey(String keySeed) throws NoSuchAlgorithmException {
    byte[] keySeedBytes = keySeed.getBytes();

    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update(keySeedBytes);
    byte[] dgBytes = md.digest();   // generate a 32 bytes key

    SecretKey key = new SecretKeySpec(dgBytes, 0, dgBytes.length, "AES");
    return key;
}

Test code:
void test() {
    byte[] b = new byte[] { 1, 2, 3, 10, 20, 30, 100};
    String key = "mykey";

    byte[] iv = generateIv();

    byte[] enb = encrypt(b, key, iv);
    byte[] deb = decrypt(enb, key, iv);

    System.out.println(Arrays.equals(b, deb));
}

Output:
true





Tuesday, March 26, 2019

Java: Example of convert Object to bytes and vice versa


The code of Object2Bytes.java:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Object2Bytes {
    public static byte[] object2Bytes(Object obj) {
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;

        try {
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            oos.flush();

            return bos.toByteArray();
        } catch (IOException ex) {

        } finally {
            try {
                if (oos != null)
                    oos.close();

                if (bos != null)
                    bos.close();
            } catch (IOException ex) {

            }
        }

        return null;
    }

    public static Object bytes2Object(byte[] bt) {
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;

        try {
            bis = new ByteArrayInputStream(bt);
            ois = new ObjectInputStream(bis);

            return ois.readObject();
        } catch (IOException ex) {

        } catch (ClassNotFoundException ex) {

        } finally {
            try {
                if (ois != null)
                    ois.close();

                if (bis != null)
                    bis.close();
            } catch (IOException ex) {

            }
        }

        return null;
    }
}

The test code of Object2BytesTest.java is below. The class must implements Serializable in order to be converted into bytes.

import org.junit.Test;

import java.io.Serializable;

public class Object2BytesTest implements Serializable {
    public class SimpleClass implements Serializable {
        private int i;

        public int getI() {
            return i;
        }

        public void setI(int i) {
            this.i = i;
        }
    }

    @Test    public void test1() {
        SimpleClass sc = null;
        byte[] bt = null;

        sc = new SimpleClass();
        sc.setI(10);
        bt = Object2Bytes.object2Bytes(sc);
        sc = (SimpleClass)Object2Bytes.bytes2Object(bt);
        System.out.println(sc.getI());

        sc.setI(20);
        bt = Object2Bytes.object2Bytes(sc);
        sc = (SimpleClass)Object2Bytes.bytes2Object(bt);
        System.out.println(sc.getI());
    }
}

The output of the test:
10
20


Monday, March 18, 2019

javapath and JAVA_HOME


The Java SE JDK and JRE 8 installer for Windows will prepend the Windows Path environment variable with the 32-bit path:

C:\Program Files (x86)\Common Files\Oracle\Java\javapath






(https://support.oracle.com/knowledge/Middleware/2412304_1.html)

But the installer won't set JAVA_HOME.

This causes problems if the user wants to install another version of Java (e.g. Java 7). javapath is still there and Java 7 cannot be found there.

It also causes problems when the user tries to run javac or jar as they are not available under javapath.

After the installation of Java 8, one should manually set the JAVA_HOME environment variable pointing to the newly generated Java executables (e.g. C:\Program Files\Java\jdk1.8.0_66\bin). And prepend %JAVA_HOME%\bin to the beginning of the Windows Path environment variable.
 
Get This <