Thursday, November 12, 2020

Java: Solving Anagrams with streams

I have been playing with code problems. Since I'm studying for Java 11 certification, I decided to resolve the Anagrams problem using streams. Here what I do is sort the two strings characters and then making a comparison.


public class Anagrams {
    static boolean isAnagram(String a, String b) {
        return sortStringChars(a).equals(sortStringChars(b));
    }

    static String sortStringChars(String str) {
        return str.toLowerCase().chars()
            .mapToObj(c -> (char) c)
            .sorted()
            .reduce("", (s,c) -> s.concat(String.valueOf(c)), String::concat);
    }

    public static void main(String[] args) {
        String a = "anagram";
        String b = "margana";

        boolean ret = isAnagram(a, b);
        System.out.println( (ret) ? "Yes, Anagrams!" : "Not Anagrams" );
    }
}

Thursday, October 22, 2020

Gradle: Exclude SpringBoot Application Class from Jacoco Coverage

 

Jacoco plugin is a must if you care about not just writing random unit tests, but to ensure you have the right coverage for your code base. The plugin also comes with a report that shows the coverage at package level.

One thing that has been bothering me with SpringBoot apps I work with is the low number that always appears for the main SpringBoot Application class. This is a boiler plate class with a simple main method to launch the SpringApplication:

@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

Almost in every application we won't need to add any other additional logic to this method which makes it kind of dumb to create a test just to cover this class and main method. Best thing is to exclude it from our coverage using this format (in this case for Gradle):

jacocoTestReport {

    afterEvaluate {
        classDirectories.from = files(classDirectories.files.collect {
            fileTree(dir: it, exclude: 'com/mycom/shoppingcart/ServiceShoppingCartApplication.class')
        })
    }
}

Thursday, April 2, 2020

Spring REST Controller: Resolve conflicts between root controllers endpoints and swagger-ui.html


Our team had some issues setting up swagger. We've been adding swagger to multiple services and for a strange reason, one service was not loading the swagger-ui.html. After some testing, we realize there was a conflict with some endpoint that were mapping to the root of the site:

@RestController
public class ReportController {
    
    @RequestMapping(method = RequestMethod.GET, value = "/{reportId}")
    public ResponseEntity getReport(@PathVariable String reportId) {
        ....
    }
}

As we can see, since controller class has no request mapping, and endpoint method is mapping with /{some_id}, when we try to hit /swagger-ui.html, the request is mapped to this method.

After googling a lot, we ended up just making our request mapping more specific to a certain type of ids. In our case we are using mongo ids for the reports. It means ids can only have number or letters in lowercase.


@RestController
public class ReportController {
    
    @RequestMapping(method = RequestMethod.GET, value = "/{reportId:^[0-9a-f]+$}")
    public ResponseEntity getReport(@PathVariable String reportId) {
        ....
    }
}

Now because swagger-ui.html contains a dot (.) and a dash (-), the request is not being caught by this endpoint anymore.

Friday, June 14, 2019

Save binary files in MongoDB with Spring-Boot

Saving binary files in MongoDB is pretty simple with Spring-Boot. You simply need to put byte[] type in the CrudRepository entity:



public interface BinayFilesRepository extends MongoRepository<BinaryEntity, String> {

}

@Document(BinaryEntity = "binaries")
public class BinaryEntity {

    private String id;
    private byte[] data;

}

Wednesday, May 22, 2019

Docker: Run MySql Server

A practical way to start MySQL server using docker:



docker run -d -p 3306:3306 --name=mysql-server --env="MYSQL_ROOT_PASSWORD=123456" mysql --default-authentication-plugin=mysql_native_password


Then just connect outside the container with host:
localhost, port:3306, user:root, password:123456