spring Posts

Create JWT Token based on Public – Private Key Certificate On Spring Security

Previously im always creating JWT token using a simple 20digit random character string, despite it works well but somehow it feels like there is something wrong. It feels like it is less secure.
Therefore, after spending some time researching, im changing below code where im using a 20 digits random String character


	String signingKey = "V5iwaQYUyqyi71ij3OtP";
	
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(signingKey);
        return converter;
    }

To signing and veryfing using a simple public and private key, first we need to create a simple public key file, public.txt

-----BEGIN PUBLIC KEY-----
MIICITANBgkqhkiG9w0BAQEFAAOCAg4AMIICCQKCAgBoDqqgVQd0VX0RFBxquFPI
7o0WabMhCV+BplU3MX+RVq8djCVvkb0FwZSuqZT8d3mvxLtEdHxHXI2vRL9qhOvD
pBgyXw6z+IrzSwYM1LrRj+vM61jCD9lhD5y5kbvzonNbTEGNX2//oJHKC0uwCXWP
ZNx6WdQkWrCD3FDtQyuDkPuGWeuXMqBwuLLrhMg1c4B3CF2DUyVxRLT21WfguRKE
8gkNBI6f9PsG/DAFyTbXJNRHjyqam4Uanc/kuiw/kUUCCdiNC7jUD64pPixJy0pC
8gXKH/iZZ4omSygFBCDHkcTJvCYdVOz36Smzzus8V38i2vx0gP5ri+eYgVdCsPG8
WkaL/8QwUB0zJIM6o7ELb4OyDDX8M99nOTovAsgSMvMu2dCAjsPAwwaJKb6Rnn84
zu3xWuDZNOTox/l4+YqV91p3+nvsizPbme3qiYNM6GJJX6mGUXCX7yaC7t4UEcQS
oLBvo/zXa1SOHrIMZVFhbT9PPpspBXC3YX+zS5/4XR1+m3PWvGiXBOpD47r1+Oz1
MWpZXqq5TT53AsbXOhGIGO54TLKq/m7lPJd1Y8KeKMdR5j+a1gmPy6kv68YBHPOx
npvlrpEvNFujNeBftfNrBoeHtiYCUKZjSTHLquCbuq2/w3FF8kRQNUc04btysTJ8
LdulnXqPagx9egAGjjG4QwIDAQAB
-----END PUBLIC KEY-----

and private key, private.txt. And put both of them under resources folder so accessible by our app

-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

And change our code to below,

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        Resource resource = new ClassPathResource("public.txt");
        Resource privateResource = new ClassPathResource("private.txt");
        String publicKey = null;
        String privateKey = null;
        try {
            publicKey = IOUtils.toString(resource.getInputStream());
            privateKey = IOUtils.toString(privateResource.getInputStream());
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
        converter.setVerifierKey(publicKey);
        converter.setSigningKey(privateKey);
        return converter;
    }

The downside of this new signing is it almost doubled the size of my JWT token, but hopefully makes it more secure.

Google+

Distributed Tracing on Openshift using Jaeger and Spring Sleuth

There is one big issue when we are using microservices environment, that is sometimes we are unable to see messages goes from each microservice goes to which microservice and also unable to see latency for each microservices.

Luckily we have Jaeger to do that. According to its website, Jaeger is an open source, end-to-end distributed tracing for monitor and troubleshoot transactions in complex distributed systems. And it can also be installed easily on Openshift with a very simple oc command,

oc process -f https://raw.githubusercontent.com/jaegertracing/jaeger-openshift/master/all-in-one/jaeger-all-in-one-template.yml | oc create -f -

After installed, you will see Jaeger pod on Openshift project dashboard with several opened ports and a url for accessing query dashboard. See the red box on the image, it is the url for accessing zipkin api from other pods internally.

Next is creating two simple java app, one as backend, and another one as api gateway.
As usual, we’ll start with a simple maven file for our backend service,

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.edw.test</groupId>
    <artifactId>HelloWorld</artifactId>
    <version>1.0.1</version>
    <name>Hello World</name>
    <description>A Simple Hello World</description>

    <properties>
        <java.version>1.8</java.version>

        <version.fabric8.plugin>3.5.38</version.fabric8.plugin>
        <fabric8.generator.fromMode>istag</fabric8.generator.fromMode>
        <fabric8.generator.from>redhat-openjdk18-openshift:1.0</fabric8.generator.from>

    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>io.fabric8</groupId>
                <artifactId>fabric8-maven-plugin</artifactId>
                <version>${version.fabric8.plugin}</version>

                <executions>
                    <execution>
                        <id>fmp</id>
                        <goals>
                            <goal>resource</goal>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>
</project>

Create a simple java app,

package com.edw.test.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
package com.edw.test.demo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

@RestController
public class IndexController {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @GetMapping("/")
    public HashMap sayHelloApi(@RequestParam String id) {
        logger.debug("say something, anything - {}", id);
        return new HashMap(){{
            put("Message", "Hello My World "+id);
        }};
    }
}

A logback.xml file for logging format,

<configuration>
    <statusListener class="ch.qos.logback.core.status.NopStatusListener"/>
    <springProperty scope="context" name="springAppName" source="spring.application.name"/>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %-5level [${springAppName},%X{X-B3-SpanId:-}] %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <logger name="com.edw" level="DEBUG" additivity="false">
        <appender-ref ref="STDOUT"/>
    </logger>
    <root level="ERROR" additivity="false">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

And finally, a properties file for storing our configuration.

spring.application.name=Hello World
spring.zipkin.baseUrl: http://zipkin:9411/
spring.sleuth.sampler.probability=1.0

Next is creating our Api Gateway class, we’ll start with a simple POM file.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.edw</groupId>
    <artifactId>ApiGateway</artifactId>
    <version>1.0</version>

    <name>ApiGateway</name>
    <description>Demo project for Api Gateway</description>

    <properties>
        <java.version>1.8</java.version>

        <version.fabric8.plugin>3.5.38</version.fabric8.plugin>
        <fabric8.generator.fromMode>istag</fabric8.generator.fromMode>
        <fabric8.generator.from>redhat-openjdk18-openshift:1.0</fabric8.generator.from>

    </properties>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>io.fabric8</groupId>
                <artifactId>fabric8-maven-plugin</artifactId>
                <version>${version.fabric8.plugin}</version>

                <executions>
                    <execution>
                        <id>fmp</id>
                        <goals>
                            <goal>resource</goal>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>
</project>

And several java classes,

package com.edw;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
package com.edw.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.UUID;

@RestController
public class IndexController {

    @Autowired
    private RestTemplate restTemplate;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @GetMapping(value="/", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public String indexApi() throws Exception {
        String result = "";
        for (int i = 0; i< 3; i++) {
            logger.debug("firing");
            result = restTemplate.getForObject("http://helloworld:8080/?id="+ UUID.randomUUID().toString()+"&timestamp="+new Date().getTime(), String.class);
            logger.debug("response is {}, MDC is {}", result, MDC.get("X-B3-SpanId"));
        }
        return result;
    }
}
package com.edw.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * <pre>
 *     com.edw.config.RestTemplateConfig
 * </pre>
 *
 * @author Muhammad Edwin < emuhamma at redhat dot com >
 * 23 Sep 2019 10:47
 */
@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate getRestTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate;
    }
}

And a logback.xml, and application.properties.

<configuration>
    <statusListener class="ch.qos.logback.core.status.NopStatusListener"/>
    <springProperty scope="context" name="springAppName" source="spring.application.name"/>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %-5level [${springAppName},%X{X-B3-SpanId:-}] %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <logger name="com.edw" level="DEBUG" additivity="false">
        <appender-ref ref="STDOUT"/>
    </logger>
    <root level="ERROR" additivity="false">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>
spring.application.name=API Gateway
spring.zipkin.baseUrl: http://zipkin:9411/
spring.sleuth.sampler.probability=1.0

We can deploy both project to Openshift using fabric8 command. And this is the result after deployed successfully and hitting Api Gateway url from browser,

And we can see the detail for each request by click on it,

To see a more detailed information, we can click more and see class and method name, and also information span.

And there is one good feature when using Jaeger, is that we can visualize how a message is delivered among different microservices,

And we can search the request SpanId on Kibana,

Well, hopefully it helps. (^)

Google+

Creating a Simple SpringBoot App and Deploy it on Top of Openshift in Less than Two Minutes

Today im trying to demonstrate how easy and fast to deploy a Spring Boot application on ton of Openshift Platform. But before we go too far, let us familiarize ourself with Openshift. Openshift is a Red Hat product which is a leading hybrid cloud, enterprise Kubernetes application platform. It lets you easily and quickly build, develop, and deploy in nearly any infrastructure, public or private. Whether it’s on-premise, in a public cloud, or hosted.

For this scenario, im trying to deploy a hello world apps which are build using Spring Boot. It only consist of 2 java class, and a configuration file (maven). Below is my main java class.

package com.edw.test.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

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

}

And below is the java class im using for controller,

package com.edw.test.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

@RestController
public class IndexController {
    @GetMapping("/")
    public HashMap get() {
        return new HashMap(){{
            put("Message", "Hello World");
        }};
    }
}

And my pom.xml file,

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.edw.test</groupId>
    <artifactId>demo</artifactId>
    <version>1.0.1</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

After everything runs well on your local, lets put those code online by using Github. Once published to Github, remember to copy your github’s project url. We shall need it later.

First thing to do after creating your code is creating your free Openshift account, you can login to it with your RedHat Developer account. Next is opening your Openshift web console, and click “create project” button and insert its name,

Click on project and choose “Browse Catalog”,

And chose RedHat Open JDK 8, and create application

And below is perhaps the most important feature, that is inserting your github url on Openshift. So that it can take your code and build it accordingly. And dont forget to checklist “Create Route”.

Once application is successfully created, it will shows logs as shown below and also it will show list of pods and its status,

Next is checking where is our route,

Clicking on it will show to the index page of our SpringBoot app,

Have fun using Openshift (^)

Google+

Error “Overriding bean of same name declared in: class path resource” when Integrating Spring Cloud Sleuth and ActiveMQ Library

Had this weird error when integrating ActiveMQ JMS and Spring Cloud Sleuth,

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.jms.config.DefaultJmsListenerContainerFactory]: Factory method 'jmsListenerContainerFactory'
threw exception; nested exception is java.lang.IllegalStateException: @Bean method JMSReceiver.receiverActiveMQConnectionFactory called as bean reference for type [org.apache.activemq.ActiveMQConnectionFactory] but overridden by non-compatible bean instance of type [org.springframework.cloud.sleuth.instrument.messaging.LazyConnectionFactory].
Overriding bean of same name declared in: class path resource [id/co/edw/xxx/api/notificationengineservice/jmsClient/JMSReceiver.class]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:622)
    ... 27 common frames omitted
Caused by: java.lang.IllegalStateException: @Bean method JMSReceiver.receiverActiveMQConnectionFactory called as bean reference for type [org.apache.activemq.ActiveMQConnectionFactory]
but overridden by non-compatible bean instance of type [org.springframework.cloud.sleuth.instrument.messaging.LazyConnectionFactory]. Overriding bean of same name declared in:
class path resource [id/co/edw/xxx/api/notificationengineservice/jmsClient/JMSReceiver.class]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.resolveBeanReference(ConfigurationClassEnhancer.java:418)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:366)
    at id.co.edw.xxx.api.notificationengineservice.jmsClient.JMSReceiver$$EnhancerBySpringCGLIB$$10f22401.receiverActiveMQConnectionFactory(<generated>)
    at id.co.edw.xxx.api.notificationengineservice.jmsClient.JMSReceiver.jmsListenerContainerFactory(JMSReceiver.java:40)
    at id.co.edw.xxx.api.notificationengineservice.jmsClient.JMSReceiver$$EnhancerBySpringCGLIB$$10f22401.CGLIB$jmsListenerContainerFactory$1(<generated>)
    at id.co.edw.xxx.api.notificationengineservice.jmsClient.JMSReceiver$$EnhancerBySpringCGLIB$$10f22401$$FastClassBySpringCGLIB$$36560b20.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
    at id.co.edw.xxx.api.notificationengineservice.jmsClient.JMSReceiver$$EnhancerBySpringCGLIB$$10f22401.jmsListenerContainerFactory(<generated>)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    ... 28 common frames omitted

It happens because Spring Sleuth overriding bean provided by JMSReceiver,

package id.co.edw.xxx.api.notificationengineservice.jmsClient;
 
 
import org.apache.activemq.ActiveMQConnectionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
 
import java.util.ArrayList;
import java.util.Arrays;
 
@Configuration
@EnableJms
public class JMSReceiver {
 
 
    @Value("somevalue")
    private String brokerUrl;
 
    @Bean
    @Primary
    public ActiveMQConnectionFactory receiverActiveMQConnectionFactory() {
        ActiveMQConnectionFactory activeMQConnectionFactory =
                new ActiveMQConnectionFactory();
        activeMQConnectionFactory.setBrokerURL(brokerUrl);
        activeMQConnectionFactory.setTrustedPackages(new ArrayList<>(Arrays.asList("id.co.edw.xxx.api,java.lang".split(","))));
 
 
        return activeMQConnectionFactory;
    }
 
    @Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        factory
                .setConnectionFactory(receiverActiveMQConnectionFactory());
        factory.setConcurrency("2");
 
        return factory;
    }
}

Problem solved after remarking Sleuth import on pom.xml,

<dependency>
	<groupId>javax.activation</groupId>
	<artifactId>javax.activation-api</artifactId>
</dependency>


<!--        <dependency>-->
<!--            <groupId>org.springframework.cloud</groupId>-->
<!--            <artifactId>spring-cloud-starter-sleuth</artifactId>-->
<!--            <version>2.1.2.RELEASE</version>-->
<!--        </dependency>-->


<dependency>
	<groupId>com.github.tomakehurst</groupId>
	<artifactId>wiremock-standalone</artifactId>
	<version>2.19.0</version>
	<scope>test</scope>
</dependency>

<!--     swaggwer -->
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger2</artifactId>
	<version>2.9.2</version>
</dependency>

<!-- SMTP SPRING -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-mail</artifactId>
</dependency>

<dependency>
	<groupId>javax.activation</groupId>
	<artifactId>javax.activation-api</artifactId>
</dependency>
Google+

Importing Swagger API Into Postman

There is one feature that i like the most from Postman, is the ability to import apis from Swagger API directly. On this example, im using two most popular Swagger generator, Springfox and swagger-jaxrs. Basically, this is how you do it,

First need to click on button import on the top of Postman,
postman 1

Next is, selecting import from link,
postman 2

And paste your Swagger documentation url on that textbox, url for Springfox is like this “http://(urlname)/v2/api-docs”, and on Swagger-jaxrs is on “http://(urlname)/api/swagger.json”.

:-D

Google+