Swagger for Spring Boot How To

This is the note about how to make the swagger work together with Spring Boot. Swagger here is used as great tool to automatically create the Restful API html docs and testing API web UI.

1. Add swagger2 and UI to POM.XML

<dependency>
 <groupId>io.springfox</groupId>
 <artifactId>springfox-swagger2</artifactId>
 <version>2.6.1</version>
 <scope>compile</scope>
 </dependency>

<dependency>
 <groupId>io.springfox</groupId>
 <artifactId>springfox-swagger-ui</artifactId>
 <version>2.6.1</version>
 <scope>compile</scope>
 </dependency>

2. Create a class for spring boot configuration for swagger:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import static springfox.documentation.builders.PathSelectors.regex;

@EnableSwagger2
@Configuration
public class SwaggerConfig {

@Bean
 public Docket productApi() {
 return new Docket(DocumentationType.SWAGGER_2).select()
 .apis(RequestHandlerSelectors.basePackage("com.wayneshare.springboot.swaggerexample"))
 .paths(regex("/rest.*")).build().apiInfo(metaInfo());
 }

private ApiInfo metaInfo() {

ApiInfo apiInfo = new ApiInfo("WayneShare RestfulAPI", "Enable knowledge sharing ...", "1.0",
 "Terms of Service", new Contact("WayneShare", "https://www.wayneshare.com", "zhou_xiaowei@yahoo.com"),
 "", "");

return apiInfo;
 }
}

3. Then you can start run the application and goes to this URL http://localhost:8080/swagger-ui.html

You will see the swagger API html docs and can test over there.

4.  Try to change this part of code in config to see changes on the UI, then you will know the meta data reflecting on UI.

ApiInfo apiInfo = new ApiInfo("WayneShare RestfulAPI", "Enable knowledge sharing ...", "1.0",
 "Terms of Service", new Contact("WayneShare", "https://www.wayneshare.com", "zhou_xiaowei@yahoo.com"),
 "", "");

5. If you want to change the grouping name and description for one controller, then use @Api for you controller:

@RestController
@RequestMapping("/rest/account")
@Api(tags = "API 02", description = "Account info management")
public class AccountController {

6. Check these annotations too in case you want to change some meta on UI  and even the http return code desc. @ApiModelProperty @ApiOperation @ApiResponses

@ApiOperation(value = "Returns Authentication Result")
 @ApiResponses(value = { @ApiResponse(code = 200, message = "Successful Authentication") })

7. You can also run the testing for each API. Here is the final result I have done for a sample project:

Screenshot from 2018-04-27 10-41-10

Enjoy it and credit goes two these two links

https://github.com/TechPrimers/spring-boot-swagger-example

https://github.com/indrabasak/swagger-deepdive/wiki/Renaming-and-Sorting-REST-Controllers

Advertisements

Spring boot actuator – system monitoring and management

I am using the 1.5.10 as the example, detailed docs can see at here:

https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/html/production-ready.html

1. Just add starter-actuator to maven

<!– for logging and minitoring =============================== –>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2. Restart and suppose my app running at the 8080 port, you can see the actuator works at http://localhost:8080/health

{
  "status" : "UP",
  "diskSpace" : {
    "status" : "UP",
    "total" : 217631211520,
    "free" : 20183724032,
    "threshold" : 10485760
  },
  "rabbit" : {
    "status" : "UP",
    "version" : "3.5.7"
  },
  "db" : {
    "status" : "UP",
    "database" : "MySQL",
    "hello" : 1
  }
}

actuator gives you a lot data about your system, such as metrics, health, configuration, http trace ….FULL list can see from here ID List

3. Some ID will be blocked by spring security if your system using it. So you have to authenticate and get the token or get the role to access them. But if system is behind a firewall, you can disable the security for actuator. Let us change the actuator to running in a different port and using new path root to access it. Add these into the application.properties file:

management.port = 9091
management.address = 127.0.0.1
management.security.enabled=false
management.context-path=/manage
endpoints.jmx.enabled=false

So we can access http://localhost:9091/manage/health  now to get data.

4. Based on actuator feature, you can monitor and manage the system performance and health,  logging, and many others.  And use actuator API to process data by your self.

5. There are some GUI feature has been done based on the actuator already. like this one:

spring-boot-admin

Try to use it for your system!

 

 

 

 

 

 

 

RabbitMQ for Spring Boot with Jackson

Issue:

When you use rabbitMQ to send the java object you might get this exception. The error you will meet would like this :

Caused by: org.springframework.messaging.converter.MessageConversionException: Cannot convert from [[B]

 

Solution:

This is caused by the MQ converter not using Jackson yet. So just add following piece to solve this issue:

@SpringBootApplication
@EnableRabbit

public class MYCloudApplication {

@Bean
 public MessageConverter jsonMessageConverter() {
 return new Jackson2JsonMessageConverter();
 }

RabbitMQ quick start for Spring Boot

  1. Install the rabbitmq
sudo apt-get update
sudo apt-get install rabbitmq-server
sudo service rabbitmq-server stop
sudo service rabbitmq-server start
sudo service rabbitmq-server status
sudo rabbitmqctl status

cat /proc/$RABBITMQ_BEAM_PROCESS_PID/limits

The broker always appends to the log files, so a complete log history is retained.

/var/log/rabbitmq directory.
See /etc/logrotate.d/rabbitmq-server to configure logrotate.

The rabbbitMQ will run at port localhost:5672

 

2. Let us build a Spring Boot project to make MQ work.

2.1  Download the spring boot sample project from https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-amqp.

remember to change pom.xml parent as this:

 <parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>1.5.10.RELEASE</version>
 <relativePath /> <!-- lookup parent from repository -->
 </parent>

 

2.2 Use eclipse to import this maven project. and use “java -jar” run it, you will see it continuously say hello.

2.3 The code use following tricks:

a. @EnableScheduling and @Scheduled(fixedDelay = 1000L)  will make the app auto start a Schedule task every 1 second and call the send() method to send a msg “hello” to the MQ queue “foo”:

@RabbitListener(queues = "foo")

defines a mq listener to listen to the queue of “foo”.

b. When a msg is in the queue, this method

@RabbitHandler
 public void process(@Payload String foo) { ...}

will be triggered to process the msg got in this queue, code just prints it our in stdout.

c. the method fooQueue must names as the fooQueue as the queue name in this example is “foo”.

public Queue fooQueue() {...}

d. This code:

 @Autowired
 private RabbitTemplate rabbitTemplate;

Will auto get a connection from the RabbitMQ so it can do the send later for you.

 

3. Access RabbitMQ GUI to make simple management

Enable the rabbitmq_management module:

sudo rabbitmq-plugins enable rabbitmq_management

The Web UI is located at: http://server-name:15672/
The user “guest” is created with password “guest” by default.

 

 

 

 

 

 

 

 

 

NLU tools – Apache Tika

https://tika.apache.org/

Apache Tika – This is a must have tool if you doing the Natural Language Understanding related work in Java. As you have to prepare your training materials  with many text and articles. Tika is a tool to help you extract the text from all kinds of the docs such as  html, PPT, word and other office doc types, and many many others.

“Tika detects and extracts metadata and text from over a thousand different file types (such as PPT, XLS, and PDF). ”

Add these dependency to your maven:

<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-core</artifactId>
    <version>1.16</version>
  </dependency>

and you can use the core tika, such as check the doc file type etc.

If you want more to extract content, you also need to add parser and also some others upon needs.

 <dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-parsers</artifactId>
    <version>1.16</version>
  </dependency>

It also support running at Restful service mode with Jetty server. so you can call API through the web service. And it has simple GUI too.

 

 

How to call a c/c++ shared lib from java

You have two ways at here, JNI and JNA. JNA is based on JNI, but simpler at usage here. I will give an example for JNA usage today. It does not need use javah to create a header file.

  1. Add jna lib to you maven :
    <dependency>
    
     <groupId>net.java.dev.jna</groupId>
    
     <artifactId>jna</artifactId>
    
     <version>4.4.0</version>
    
     </dependency>
  2. Create a c file like this:
    cd /home/test
    
    touch MyTest.c
    /* MyTest.c */
    #include <stdio.h>
    
    void aSimplePrint() {
     printf("Hello world from C!\n");
    }
  3. compile the c file to the .so share lib file:
    gcc -c -fPIC MyTest.c -o MyTest.o
    gcc -shared -o libMyTest.so MyTest.o
  4. Create a java file like this, TestJNA.java
    import com.sun.jna.Library;
    import com.sun.jna.Native;
    
    public class TestJNA {
    
        static {
            System.setProperty("jna.library.path", "/home/test");
      }
    
        public interface MyTest extends Library {
            public void aSimplePrint();
         }
    
        public static void main(String[] args) {
            MyTest ctest = (MyTest) Native.loadLibrary("MyTest", MyTest.class);
            ctest.aSimplePrint();
         }
    }

    Compile to get the TestJNA.class.

  5. Then you can run the java main to test it:
    java -cp .:/path/to/jna-4.4.0.jar TestJNA

The whole process will be like this. And you could face some issue if lib is 3rd party one or others reason.
Here are some issues you may encounter in the process.

1. In linux, loadLibrary(“MyTest” will point to load a libMyTest.so file. You need pay attention name of lib at here.

2. “Exception in thread “main” java.lang.UnsatisfiedLinkError: no MyTest in java.library.path ……..”
This means java can not find the libMyTest.so in the lib folder.  This code is to solve that problem.
System.setProperty(“jna.library.path”, “/home/test”);
If you still have issue, you can try this code too:
System.load(“/home/test/libMyTest.so”);

3. If you can load lib, but can not find symbol or function name in the lib:
Exception in thread “main” java.lang.UnsatisfiedLinkError: Error looking up function ‘aSimplePrint’: /home/test/libMyTest.so: undefined symbol: …………………

Then use this command to check what a share lib .so contains in the API:
nm -D /home/test/libMyTest.so
By this way, you can know that (T) function is existing in the lib or not.

4. Command :
file /home/test/libMyTest.so
— will tell you info about this file include it is for 32bit or 64 bit will will cause some problem of some 3rd party lib files.

Multiple version JAVA in Ubuntu

Install JDK 8

sudo apt-get update ; sudo apt-get install openjdk-8-jre-headless
sudo  update-java-alternatives --list
sudo update-java-alternatives -s java-1.8.0-openjdk-amd64

to list off all the Java installations on a machine by name and directory, and then run

sudo  update-alternatives --config java

to choose which JRE/JDK to use.If you want to use different JDKs/JREs for each Java task, you can run can be configured (java, javac, javah, javaws, etc). And then

sudo  update-alternatives --config [javac|java|javadoc|etc.]
sudo update-alternatives --config javah
sudo update-alternatives --config javac
sudo update-alternatives --config jar
sudo update-alternatives --config jarsigner 
sudo update-alternatives --config javadoc
...

will associate that Java task/command to a particular JDK/JRE.