1

I have problem in inter-service communication load balancing.

I am using spring (1.4.2), spring cloud with netflixOSS.

I have two services shoppingcart-service and user-service.

Here is ShoppingCartController from shopppingcart-service app:

@RestController
@RequestMapping("shoppingCarts")
public class ShoppingCartController extends AbstractRESTController<ShoppingCart, String>{

private ShoppingCartService shoppingCartSrevice;

@Autowired
public ShoppingCartController(ShoppingCartService service) {
    super(service);
    this.shoppingCartSrevice = service;
}

@RequestMapping(value = "{userId}/createShoppingCart", method = RequestMethod.POST)
ShoppingCart createShoppingCart(
        @RequestBody List<CartItem> items,
        @PathVariable(name = "userId") String userId
        ){

    Boolean userOK = shoppingCartSrevice.checkUser(userId);

    if(userOK != null)
        if(userOK)
            return shoppingCartSrevice.createShoppingCart(items, userId);

    return null;
}

@FeignClient("user-service")//the server.port property name, for the "server" service
public interface UserServiceClient {
    @RequestMapping(value = "users/checkUser", method = RequestMethod.POST)// the endpoint which will be balanced over
    Boolean checkUser(
            @RequestParam(name = "userId") String userId);// the method specification must be the same as for users/hello
}

}

"checkUser"

methosd is from ShoppingCartService class:

@Service
public class ShoppingCartService extends AbstractCRUDService<ShoppingCart, String>{

private ShoppingCartRepository shoppingCartRepository;
private RestTemplate restTemplate;

@Autowired
private UserServiceClient userServiceClient;// feign client

@Autowired
public ShoppingCartService(ShoppingCartRepository repo, RestTemplate restTemplate) {
    super(repo);
    this.shoppingCartRepository = repo;
    this.restTemplate = restTemplate;

}

/**
 * Method checks if the given user is registered and active
 * We use Ribbon and Feign to get data from user-service, load-balancing 
 * @param userId
 * @return
 */
@HystrixCommand(fallbackMethod="fallbackCheckUser")
public Boolean checkUser(String userId) {

    /*USING LOAD-BALANCING*/
     Boolean resp = userServiceClient.checkUser(userId);//HERE I GET THE EXCEPTION
     return resp;
}

public Boolean fallbackCheckUser(String userId){
    return true;
}

When I try to execute checkUser(userId) @HystricsCommand method I get: java.lang.reflect.InvocationTargetException.

Please HELP.

UPDATE 1:

shoppingcart-service pom.xml:

 <?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>

    <groupId>rs.uns.acs.ftn</groupId>
    <artifactId>ShoppingCartService</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>ShoppingCartService</name>
    <description>Shopping Cart Service</description>

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

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jglue.fluent-json</groupId>
            <artifactId>fluent-json</artifactId>
            <version>2.0.3</version>
        </dependency>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Camden.SR2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

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


</project>
branko terzic
  • 654
  • 1
  • 8
  • 27
  • Please add more of the exception. That single line is useless. – spencergibb Apr 20 '17 at 18:23
  • The stack trace is empty on exception object, also I don't get any output on console. I have also running 3 more services alongside Eureka and Zuul. I will put pom.xml for shoppingcart-service, please see update. – branko terzic Apr 20 '17 at 18:35
  • I don't know how to help, unless you can provide a sample. Camden.SR6 is the latest in the Camden release train. – spencergibb Apr 20 '17 at 18:39
  • com.netflix.hystrix.exception.HystrixRuntimeException: UserServiceClient#checkUser(String) failed while executing. Does this make any ideas? This is only I can get. – branko terzic Apr 20 '17 at 19:08
  • I think I know what I did. I had two services with Feign client specifications that was the same aka: @FeignClient("user-service"). @spencergibb can you tell why? – branko terzic Apr 20 '17 at 19:15
  • Final conclusions: 1. I was using STS IDE for development and starting apps. For some reason this native starting does not works properly. If I start service like right-click->run as Java Application, than the first request fails on fallback method, and every new request passes without problems. When I make .jar files using mvn build, the same behavior: firs request triggers fallback method, every other passes. If someone can explain this, please comment. – branko terzic Apr 20 '17 at 20:43
  • I have no idea. – spencergibb Apr 24 '17 at 21:38

1 Answers1

-1

Spring Cloud, Feign, Ribbon aside these "REST" endpoints don't seem to follow recommended practices.

POST to check if a user exists doesn't look right, POST are normally used to create a resource such as a user or product.

POST to /..../{userId}/createShoppingCart doesn't look right either. nouns are recommended in REST API Design, /users, /products, /users/{id} and HTTP verbs (POST, PUT, PATCH, DELETE, GET, ....) represent operations on those "nouns": POST /users means create a user, PUT /products/{id} means update product whose id is {id}. Verbs are usually not recommended as part of the URL.

And as @spencergibb mentioned, without the config files (application.yml or properties), the source code and meaningful stacktrace it would be very difficult to troubleshot this issue.

One possible issue might be your pom file missing the <start-class> element inside <properties>.

ootero
  • 3,235
  • 2
  • 16
  • 22
  • The HTTP API specification is different from user case to use case. But this is noting to do with the issue that I have right now. – branko terzic Apr 21 '17 at 10:17