2017-07-10 49 views
9

Camel musi wywołać usługę REST dla pewnej integracji, jednak usługa REST ma jedno api uwierzytelniania (POST api), które musi zostać wywołane jako pierwsze, aby uzyskać token, a następnie inne kolejne wywołania api muszą być wywoływane z tokenem osadzonym w nagłówku żądań HTTP.Wywołanie usługi REST z Camel, które wymaga uwierzytelnienia api o nazwie first

Czy Spring Restemplate czy wielbłąd apache ma api do obsługi tego samego?

+5

Użyłem Apache Camel dla tego przypadku użycia. W efekcie musisz w efekcie wywołać dwie usługi. Stworzyłem trasę, która zwróci buforowany lub nowy token dostępu (i zapisuje go w pamięci podręcznej) w nagłówku autoryzacji (nie mam już dostępu do repo) i wykorzystuję wywołanie wzbogacania na głównej trasie. – gusto2

+0

Camel ma FluentProducerTemplate/ProducerTemplate API, którego można użyć, który działa podobnie do Spring xxxTemplate, ale dla wszystkich komponentów/punktów końcowych Camel. –

+0

@ gusto2 podążyło za twoim podejściem. jego działanie ... dodało działające rozwiązanie jako odpowiedź dla innych użytkowników (w razie potrzeby). – sakura

Odpowiedz

4

Zastosowano podejście @ gusto2, to prawie działa dobrze.

W ten sposób utworzyłem dwie trasy -> Pierwsza jest zegarem opartym na poniższym przykładzie, generuje token, okresowo odświeża go (ponieważ trasa działa w oparciu o licznik czasu) i przechowuje token w zmiennej lokalnej do ponownego użycia przez inna trasa.

@Component 
public class RestTokenProducerRoute extends RouteBuilder { 

    private String refreshedToken; 

    @Override 
    public void configure() throws Exception { 

     restConfiguration().producerComponent("http4"); 

     from("timer://test?period=1200000") //called every 20 mins 
        .process(
          exchange -> exchange.getIn().setBody(
            new UserKeyRequest("apiuser", "password"))) 
        .marshal(userKeyRequestJacksonFormat) //convert it to JSON 
        .setHeader(Exchange.HTTP_METHOD, constant("POST")) 
        .setHeader(Exchange.CONTENT_TYPE, constant("application/json")) 
        .to("http4://localhost:8085/Service/Token") 
        .unmarshal(userKeyResponseJacksonFormat) 
        .process(new Processor() { 
         public void process(Exchange exchange) throws Exception { 
          UserKeyResponse response= exchange.getIn().getBody(
            UserKeyResponse.class); //get the response object 
          System.out.println(response + "========>>>>>>" + 
            response.getResult()); 
          setRefreshedToken(response.getResult()); //store the token in some object 
         } 
        }).log("${body}"); 
     } 

     public String getRefreshedToken() { 
      return refreshedToken; 
     } 

     public void setRefreshedToken(String refreshedToken) { 
      this.refreshedToken = refreshedToken; 
     } 
} 

A druga trasa może wywoływać kolejne apisy, które będą używać tokena wygenerowanego przez pierwszą trasę, to byłoby coś takiego. Należy dodać scenariusze obsługi błędów, w których token może nie być ważny lub wygasł. Ale myślę, że byłby to oddzielny problem do rozwiązania.

@Component 
public class RestTokenUserOnboardRoute extends RouteBuilder { 

    private JacksonDataFormat OtherDomainUserRequestJacksonFormat = new JacksonDataFormat(
      OtherDomainUserRequest.class); 
    private JacksonDataFormat OtherDomainUserResponseJacksonFormat = new JacksonDataFormat(
      OtherDomainUserResponse.class); 
    @Override 
    public void configure() throws Exception { 

     restConfiguration().producerComponent("http4"); 

     //This route is subscribed to a Salesforce topic, which gets invoked when there is any new messages in the topic. 
     from("salesforce:CamelTestTopic?sObjectName=MyUser__c&sObjectClass="+MyUser__c.class.getName())) 
      .convertBodyTo(OtherDomainUserRequest.class) 
      .marshal(OtherDomainUserRequestJacksonFormat).log("${body}") 
      .setHeader(Exchange.HTTP_METHOD, constant("POST")) 
      .setHeader(Exchange.CONTENT_TYPE, constant("application/json")) 
      .log("The token being passed is ==> ${bean:tokenObj?method=getRefreshedToken}") 
      .setHeader("Authorization", simple("${bean:tokenObj?method=getRefreshedToken}")) 
      .to("http4://localhost:8085/Service/DomainUser") 
      .unmarshal(OtherDomainUserResponseJacksonFormat) 
      .process(new Processor() { 
      public void process(Exchange exchange) throws Exception { 
        OtherDomainUserResponse response = exchange.getIn().getBody(
          OtherDomainUserResponse.class); 
          System.out.println(response + "==================>>>>>> " + response.getStatusCode()); 
         } 
      }).log("${body}"); 
    } 
} 

Więc tutaj token jest uzyskiwanie spożywane z tokenObj Bean (instancji RestTokenProducerRoute który ma metodę getRefreshedToken() zdefiniowany. Zwraca ona przechowywana token.

Nie trzeba dodawać, że ustawiłeś fasoli w camelcontext rejestr następująco wraz z innymi ustawieniami (jak składnik, droga itd.) W moim przypadku to była następująca.

@Autowired 
public RestTokenUserOnboardRoute userOnboardRoute; 
@Autowired 
public RestTokenProducerRoute serviceTokenProducerRoute; 

@Autowired 
private RestTokenProducerRoute tokenObj; 

@Override 
protected CamelContext createCamelContext() throws Exception { 
    SimpleRegistry registry = new SimpleRegistry(); 
    registry.put("tokenObj", tokenObj); //the tokenObj bean,which can be used anywhere in the camelcontext 
    SpringCamelContext camelContext = new SpringCamelContext(); 
    camelContext.setRegistry(registry); //add the registry 
    camelContext.setApplicationContext(getApplicationContext()); 
    camelContext.addComponent("salesforce", salesforceComponent()); 
    camelContext.getTypeConverterRegistry().addTypeConverter(DomainUserRequest.class, MyUser__c.class, new MyTypeConverter()); 
    camelContext.addRoutes(route()); //Some other route 
    camelContext.addRoutes(serviceTokenProducerRoute); //Token producer Route 
    camelContext.addRoutes(userOnboardRoute); //Subsequent API call route 
    camelContext.start(); 
    return camelContext; 
} 

to rozwiązuje mój problem ustawiania tokenu dynamicznie gdzie znak jest coraz p powstałe w wyniku wykonania innej trasy.

+0

Widzę, że kod żąda nowego tokena dla każdego żądania serwera. Na początek może być ok, ale najlepszą praktyką (i moją przyszłą sugestią) jest cache (http://camel.apache.org/cache.html) i ponowne użycie tokena (lub - może użyć stałego tokena poziomu aplikacji), aby nie umieszczać niepotrzebnego obciążenia usługi w innej usłudze zewnętrznej. Niezależnie od tego - dziękuję za udostępnienie :) – gusto2

+0

@ gusto2 dla każdego żądania serwera, nie żądając nowego tokena. Token jest odświeżany co 20 minut zgodnie z trasą TokenProducer. Tak więc, co 20 minut zostanie wywołana trasa i buforować/przechowywać token w pamięci wewnętrznej (tokenObj). Inne żądania serwera będą po prostu uzyskiwać dostęp do tokena z tokenObj, nie wiedząc, kiedy zostanie odświeżony. Więc zdecydowanie nie żąda nowego tokena dla każdego żądania serwera. – sakura