Invoking Camel Rest services gives me 401 using restlet - rest

I am trying write a route to call a restful services. all of them donot have a body but query parameters. when i call(https) the rest service i get 401(unauthorised).
but if i use simple non-ssl (http) and invoke it works fine on other apis.
here is my Route and producer template.
Route
public static final String MONITOR_URI = "https://lsapi.thomson-pharma.com//ls-api-ws/ws/rs/opportunity-v1/match?drug=bevacizumab&company=Genentech Inc&fmt=json";
public static final String DIRECT_MONITOR = "direct:getDrugInfo";
from(DIRECT_MONITOR).to(MONITOR_URI).convertBodyTo(String.class);
=========================Main Class===============================
public static void main(String[] args) throws Exception {
CamelContext context = createCamelContext();
context.start();
final String text = "paracetamol";
final String fmt = "json";
final String authMethod = "Digest";
final String authUsername = "TR_Internal_024";
final String authPassword="ZTYA5S1KLF7WCDMN";
final String query = String.format("text=%s&fmt=%s&authMethod=%s&authUsername=%s&authPassword=%s",text,fmt,authMethod,authUsername,authPassword);
Map<String,Object> headers = new HashMap<String, Object>(){
{
put(Exchange.HTTP_METHOD,"POST");
put(Exchange.AUTHENTICATION,"Digest");
put("authUsername","TR_Internal_024");
put("authPassword","ZTYA5S1KLF7WCDMN");
put(Exchange.HTTP_QUERY,query);
}
};
ProducerTemplate template = context.createProducerTemplate();
String request = template.requestBodyAndHeaders(Constants.DIRECT_MONITOR,null,headers,String.class);
System.out.println("Body is : "+request);
}
Can someone help how to configure SSL using camel cxf or restlet ?
How do i add Credentials Provider to CamelContext or Spring Context ?

APologies for the delay. i got it worked by retriving the component from camelContext below is the code.
=========================================================================
HttpComponent http = (HttpComponent) camelContext.getComponent("https");
HttpClientConfigurer httpClientConfigurer = http.getHttpClientConfigurer();
if(httpClientConfigurer == null){
System.out.println("httpClientConfigurer is null");
if(http.getHttpClientConfigurer() == null ){
HttpConfiguration httpConfiguration = new HttpConfiguration();
httpConfiguration.setAuthMethod(AuthMethod.Digest);
httpConfiguration.setAuthUsername("xxxxx");
httpConfiguration.setAuthPassword("xxxxxx");
http.setHttpConfiguration(httpConfiguration);
}
}
Regards
Ram

Related

How to test Feign REST client without acces to servise?

I have simple REST client:
#FeignClient(name = "${service-parameters.name}", url = "${service-parameters.url}")
public interface ParametersClient {
#GetMapping("api/v1/parameters/by-site-id/{parameterName}/{siteId}")
Parameter getParameterBySiteId(
#PathVariable(name = "parameterName") final String parameterName,
#PathVariable(name = "siteId") final Long siteId,
#RequestParam(name = "validityDate", required = false) LocalDate validityDate);
#GetMapping("api/v1/parameters/by-client-id/{parameterName}/{clientId}")
Parameter getParameterByClientId(
#PathVariable(name = "parameterName") final String parameterName,
#PathVariable(name = "clientId") final Long clientId,
#RequestParam(name = "validityDate", required = false) LocalDate validityDate);
}
but I am not able to touch a service in my test. So I need to test request which my methods in client create. Everything else is tested on service side.
Those are correct requests for my servise:
http://localhost:8080/api/v1/parameters/by-site-id/PSEUDO_ONLINE_ROOT_PATH/3000001?validityDate=2018-07-18
http://localhost:8080/api/v1/parameters/by-client-id/KOMBI_MINIMUM_NUMBER_GROUP/10508078
What is the best way to test my client without running service? I spent a lot of time of searching but I did not find anything useful for my case :(.
Thanks a lot for any advice.
I have solved my problem with folowing code:
#AutoConfigureMockMvc
#SpringBootTest
#RunWith(JUnitPlatform.class)
#ExtendWith({ RestDocumentationExtension.class, SpringExtension.class })
public class ParameterClientTest {
private final RestTemplate restTemplate = new RestTemplate();
#Autowired
ParametersClient client;
private final MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).bufferContent().build();
#Test
public void getParameterBySiteId() {
mockServer.expect(once(), requestTo(REQUEST_BY_SITE_ID)).andRespond(withSuccess(RESPONSE_BY_SITE_ID, MediaType.APPLICATION_JSON));
Response result = client.getParameterBySiteId(PSEUDO_ONLINE_ROOT_PATH, SITE_ID, VALIDITY_DATE);
assertEquals(REQUEST_BY_SITE_ID, result.request().url());
}
#Test
public void getParameterByClientId() {
mockServer.expect(once(), requestTo(REQUEST_BY_CLIENT_ID)).andRespond(withSuccess(RESPONSE_BY_CLIENT_ID, MediaType.APPLICATION_JSON));
Response result = client.getParameterByClientId(KOMBI_MINIMUM_NUMBER_GROUP, CLIENT_ID, VALIDITY_DATE);
assertEquals(REQUEST_BY_CLIENT_ID, result.request().url());
}
}

Jersey client. MultivaluedMap goes empty

My RESTful client has this method:
public void testGetCateogrywiseData() {
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
client.addFilter(new LoggingFilter(System.out));
WebResource service = client
.resource("http://localhost:8080/MyApp/rest/publicdata");
#SuppressWarnings("rawtypes")
MultivaluedMap queryParams = new MultivaluedMapImpl();
queryParams.add("latitude", "18.522387");
queryParams.add("longitude", "73.878437");
queryParams.add("categoryID", "2");
service.queryParams(queryParams);
ClientResponse response = service.get(ClientResponse.class);
System.out.println(response.getStatus());
System.out.println("Form response " + response.getEntity(String.class));
}
On the server side the method looks like this:
#Path("publicdata")
#GET
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String getPublicData() throws JSONException {
MultivaluedMap<String, String> valueMap = uriInfo.getQueryParameters();
Long latString = Long.parseLong(valueMap.getFirst("latitude"));
Long lonString = Long.parseLong(valueMap.getFirst("longitude"));
Long categoryId = Long.parseLong(valueMap.getFirst("categoryID"));
// Do necessary stuff and return json string
return null;
}
My problem is the valueMap at the server end is always empty. It never gets the three parameters that I have sent from the client code. What am I missing?
The problem happens on this line:
service.queryParams(queryParams);
It successfully adds the query params, but it does not change the original service, it returns a new one to you. To make it work you need to change to this:
service = service.queryParams(queryParams);

How to access http session object in jersey REST service?

Hi i want to access data to anf from http session object in rest service i have googled a lot and find that #context of javax.ws.rs.core.Context gives HttpServlet object but as it is interfaec i always get it null. my code is as following
#Context
private HttpServletRequest request;
private HttpSession session = request.getSession();
#Path(value = "/listAllQuestion")
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response listAllQuestion(){
int pgNo = 1;
int pgSize = 5;
IPResponse response = new IPResponse();
try {
if (session.getAttribute(IpConstants.TOPIC) != null
&& session.getAttribute(IpConstants.LEVEL) != null) {
session.removeAttribute(IpConstants.TOPIC);
session.removeAttribute(IpConstants.LEVEL);
}
session.setAttribute(IpConstants.PAGENO, pgNo);
session.setAttribute(IpConstants.PAGESIZE, pgSize);
quesList = questionService.listAllQuestion(pgNo, pgSize);
please try this:
Move your request.getSession() down inside your listAllQuestion() method, as so:
public Response listAllQuestion(){
HttpSession session = request.getSession():
I don't believe your request object will be populated outside the context of an actual request handler.

Why HandshakeRequest doesn't return HttpSession in my ServerEndpointConfig.Configurator?

There is a good example for sharing HttpSession between Websocket and Rest service. (Spring DispatchServlet cannot find resource within Jetty) But it doesn't work for me. I'm not sure is there any thing I'm missing?
I'm using Jetty as websocket server and also I created a WebApp as well which injected by SpringConfig.
private void init() throws Exception
{
Server server = new Server();
// Create SSL Connector
ServerConnector serverConnector = getSSLConnector(server);
// Bundle to server
server.setConnectors(new Connector[] { serverConnector });
// Create request handler collection
HandlerCollection handlers = new HandlerCollection();
// Add WebSocket handler
final ServletContextHandler servletContextHandler = getWebSocketContextHandler();
handlers.addHandler(servletContextHandler);
// Add Servlet handler
handlers.addHandler(getWebAppServletContextHandler());
server.setHandler(handlers);
// Initial WebSocket
WebSocketServerContainerInitializer.configureContext(servletContextHandler);
// Start Jetty
server.start();
server.join();
}
Both WebSocket and Rest are working under same port perfectly, of course, with different context paths.
Now, I created a Rest service:
#RequestMapping(value = "/login", method = RequestMethod.POST)
#Consumes({ MediaType.APPLICATION_JSON_VALUE })
#Produces({ MediaType.APPLICATION_JSON_VALUE })
public #ResponseBody Message login(#RequestBody Credential credential, #Context HttpServletRequest servlerRequest)
{
...
HttpSession session = servlerRequest.getSession(true);
session.setAttribute("userName", credential.getUserName());
...
Message message = new Message();
...
return message;
}
In this service I created a HttpSession and stored something in. As I said, it works, and so does the session.
Rest client:
public void login() throws KeyManagementException, NoSuchAlgorithmException
{
final String loginServiceUri = HTTP_SERVICE_BASE_URI + "/login";
ClientConfig clientConfig = new DefaultClientConfig();
...
Client client = Client.create(clientConfig);
WebResource webResource = client.resource(loginServiceUri);
ClientResponse response = webResource
.type("application/json")
.post(ClientResponse.class, new Credential("user","pass"));
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
List<NewCookie>cookies = response.getCookies();
ClientEndpointConfigurator.setCookies(cookies); <== Store cookies as well as session to ClientEndpointConfigrator class
Message message = response.getEntity(Message.class);
...
}
ClientEndpointConfigrator class has a static list for all cookies which like this:
public class ClientEndpointConfigurator extends ClientEndpointConfig.Configurator {
private static List<NewCookie> cookies = null;
public static void setCookies(List<NewCookie> cookies) {
ClientEndpointConfigurator.cookies = cookies;
}
...
#Override
public void beforeRequest(Map<String, List<String>> headers) {
...
if(null != cookies)
{
List<String> cookieList = new ArrayList<String>();
for(NewCookie cookie: cookies)
{
cookieList.add(cookie.toString());
}
headers.put("Cookie", cookieList);
}
...
}
}
beforeRequest() method will put all cookies to request header. If you inspect the cookieList, you will see:
[JSESSIONID=tvum36z6j2bc1p9uf2gumxguh;Version=1;Path=/rs;Secure]
Things looks prefect.
Finally, create a server end ServerEndpointConfigurator class, and override the modifyHandshake() method to retrieve the session and cookies
public class SpringServerEndpointConfigurator extends ServerEndpointConfig.Configurator {
#Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
super.modifyHandshake(sec, request, response);
httpSession = (HttpSession)request.getHttpSession(); <== **It returns null here!**
...
}
}
}
I can't get my HttpSession back! and if you print headers out, you will see the cookie has been changed:
Cookie: JSESSIONID="tvum36z6j2bc1p9uf2gumxguh";$Path="/rs"
Any one knows what's the reason?
All right, I figured it out, it's because I put WebSocket and Rest to different context handler. Jetty keeps handlers isolate to each other. To share session information, you have to put them together.
But if someone does want to separate them, it is still possible done by sharing SessionManager or SessionHandler. There are many ways to achieve this, you can inject SessionHandler to each ServletContext or just define it as a static variable and put it on somewhere every one can reach, each way works.

Spring 4 Restfull Service with bean

I am trying to create a simple Server / Client application that can send a bean as parameter instead of String but failing below is my code
Server
#Controller
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping(method=RequestMethod.POST,value="/returnGreet")
public #ResponseBody Greeting returnGreet(
#RequestBody(required=false) Greeting greet) {
if(greet == null)
return new Greeting(counter.incrementAndGet(),
String.format(template, greet));
else
return new Greeting(0,"Testing");
}
}
Client
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String,Greeting> greet = new LinkedMultiValueMap<String, Greeting>();
greet.add("greet", new Greeting(0,"XOXO"));
greeting = restTemplate.postForObject("http://localhost:8080/returnGreet",greet, Greeting.class,greet);
System.out.println("Content: " + greeting.getContent());
System.out.println("Id: " + greeting.getId() );
The result is always null for the object greet at the server side.
Any Idea ?
You're not using the RestTemplate correctly. Why are you passing a MultiValueMap as the Entity to be sent? This won't get serialized the way your Server expects.
Just use the Greeting object directly.
restTemplate.postForObject("http://localhost:8080/returnGreet", new Greeting(0, "XOXO"), Greeting.class);
Also, the last argument is not necessary, you don't have any URI variables.