im using java/maven with microprofile to develop an api that will return information of a service that have #Queryparams, but the problem is that the provider of this service need that i sent an empty #Queryparam, like this emptyquery:
https://example.com/reports/server?emptyquery&report=12345
my client code is this:
package ca.com.td.woody.svc.client;
import ca.com.td.woody.svc.provider.UnknownUrlExceptionMapper;
import java.io.InputStream;
import java.net.URL;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
#RegisterRestClient()
#RegisterProvider(UnknownUrlExceptionMapper.class)
public interface IGuateFacturasClient {
#GET
#Produces("application/pdf")
InputStream getBill(
#QueryParam("emptyquery") String emptyquery,
#QueryParam("report") String report
);
}
And when i try to execute this client i use this command to do that:
InputStream inputStream = invoiceClient.getBill( null ,"12345");
But, doesnt matter what i sent, always the client says that the empty query is not empty.
What could i do?
Related
I created a RESTful application with jersey and now I'm trying to add a facebook authentication interface to my app and i'm kinda stuck how to connect authentication to my rest method .
package service;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import metier.Cours;
#Path("rs")
public class Formation {
#GET
#Produces(MediaType.TEXT_PLAIN)
#Path("/FraisAnnuelles/{code}")
public Double FraisInscription(#PathParam(value="code")int code) {
return (Double)(30000+(Math.random()*(30000-25000)));
}
#GET
#Path("/Cours/{code}")
#Produces(MediaType.APPLICATION_XML)
public Cours getCours(#PathParam(value="code")int code) {
return new Cours(code,"web semantique",30);
}
#GET
#Path("/ListeCours")
#Produces(MediaType.APPLICATION_XML)
public List<Cours> getAllCours(){
List<Cours> listeCours=new ArrayList<>();
listeCours.add(new Cours(1,"web semantique",30));
listeCours.add(new Cours(2,"web service",20));
listeCours.add(new Cours(3,"IAD",26));
return listeCours;
}
}
I am not sure if you will be able to do that. The protocol that is used for logging in with facebook/google/some_identity_provider is
OpenID connect. That itself is a big can of worms to dive into when starting from scratch, but the key element in why I have some doubts to the feasibility of what you are asking for is that for a login using openid connect to be successful, the identity provider has a database table with a list of allowed urls to log in from, and unless the url you try to log in from matches exactly 100% one of the values in that table, the login attempt will fail.
So in other words, in order to allow users to log in with facebook/google on https://myblog.example.com/blog you need to contact facebook/google and ask them "hey facebook/google, can you add https://myblog.example.com/blog to the list urls allowed to log in from pretty please?". I assume both companies require some (significant) minimum size of your web site before allowing logging in with them, and you will be absolutely at the whim of their terms and condition with zero negotiation possibilities. You might need to pay for the privileged to use them as identity providers.
when I use the RestTemplate and the Getforobject() method I get an error 500 code when running my spring boot. How can I consume this API using springboot?
package nl.qnh.qforce.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.List;
#RestController
public class PersonController {
private static String url = "https://swapi.co/api/people/";
#Autowired
private RestTemplate restTemplate;
#GetMapping("/people")
public List<Object> getPeople(){
Object[] people = restTemplate.getForObject(url, Object[].class);
return Arrays.asList(people);
}
}
I would advise first checking if manually calling provided url returns expected response. You can use curl, postman or any other similar tool. In case call on provided url returns response, provide us with more context from your application, so we can assess which part is responsible for 500 error.
When I try to reach the website from http://localhost:8080/Films/showAll i obtain the 404 http error. So I try to other address and from http://localhost:8080/showAll i see 406 http error.
The controller class looks like this:
package Films.controller;
import Films.dao.DirectorDAO;
import Films.dao.FilmDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Scanner;
#RestController
// klasa odpowiada za pobieranie oraz przsył danych wykorzystywanych w DAO
public class FilmOperationController {
......
// metoda zwraca listę wszystkich filmów bazie
#RequestMapping(value = "/showAll", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
#Transactional(readOnly = true)
public List<Object[]> showAll() {
return filmDao.getAllFilms();
}
....
}
Here is pom.xml and java config file.
https://github.com/lukasz-chojn/films_database/blob/master/pom.xml
https://github.com/lukasz-chojn/films_database/blob/master/src/main/java/Films/component/Config.java
Any ideas what can be wrong?
I spent few hours to debug your issue. There was lot of unused dependencies and code. I refactored the code, and resolved the issue.
Here is the link to download it
https://github.com/deepakjain0812/testrepo
Please run it on your local and let me know if you see any issue.
I will delete this repo once you confirm that you are no longer facing issues with status codes like 500, 401 or 406
http://localhost:8080/showAll
A #RestController is supposed to be consumed by a Rest Client, not a browser.
In order to test this kind of controller, you can use another tool like curl or Postman.
Here is an example of how you would use your API using curl with a terminal: curl http://localhost:8080/showAll
I'm getting started with Java so expect this to be a pretty amateur problem. I'm modifying Neo4j's unmanaged extension template.
I've defined an NTReport class, it is included, everything compiles happily. POSTing against the endpoint with content-type set to application/json returns the error in the subject.
I also have the getStatus method defined in the object.
package org.neo4j.example.unmanagedextension;
import org.codehaus.jackson.map.ObjectMapper;
import org.neo4j.cypher.javacompat.ExecutionEngine;
import org.neo4j.cypher.javacompat.ExecutionResult;
import org.neo4j.graphdb.*;
import org.neo4j.helpers.collection.IteratorUtil;
import org.neo4j.server.database.CypherExecutor;
import org.neo4j.example.unmanagedextension.NTReport;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
#Path("/service")
public class MyService {
#POST
#Consumes({MediaType.APPLICATION_JSON})
#Path("/reports")
public String getReportJava(NTReport report) {
return "Report params: " + report.getMetrics();
}
}
Here's NTReport:
package org.neo4j.example.unmanagedextension;
public class NTReport {
private String endpoints;
private String resolution;
private String metrics;
public String getEndpoints() {
return this.endpoints;
}
public String getResolution() {
return this.resolution;
}
public String getMetrics() {
return this.metrics;
}
}
My understanding is that by using #Consumes, it should map keys in JSON to variables of the same name in the class. Am I wrong there?
When I create basic endpoints using #GET, I get the expected responses.
ALSO, this post appears to describe the same exact problem, so I'll examine it.
I found another error log that seems to suggest it doesn't know how to handle JSON after all.
Feb 11, 2015 5:46:19 PM com.sun.jersey.spi.container.ContainerRequest getEntity
SEVERE: A message body reader for Java class org.neo4j.example.unmanagedextension.NTReport, and Java type class org.neo4j.example.unmanagedextension.NTReport, and MIME media type application/json was not found.
The registered message body readers compatible with the MIME media type are:
*/* ->
com.sun.jersey.core.impl.provider.entity.FormProvider
com.sun.jersey.core.impl.provider.entity.StringProvider
com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
com.sun.jersey.core.impl.provider.entity.FileProvider
com.sun.jersey.core.impl.provider.entity.InputStreamProvider
com.sun.jersey.core.impl.provider.entity.DataSourceProvider
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
com.sun.jersey.core.impl.provider.entity.ReaderProvider
com.sun.jersey.core.impl.provider.entity.DocumentProvider
com.sun.jersey.core.impl.provider.entity.SourceProvider$StreamSourceReader
com.sun.jersey.core.impl.provider.entity.SourceProvider$SAXSourceReader
com.sun.jersey.core.impl.provider.entity.SourceProvider$DOMSourceReader
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$General
com.sun.jersey.core.impl.provider.entity.EntityHolderReader
jersey-json provides a set of MessageBodyReader<T> and MessageBodyWriter<T>. You may add #XmlRootElement to your NTReport or choose any other option available for jersey 1.x since neo4j community server uses Jersey 1.9 at the moment
How can I view the actual request that Jersey generates and sends to the server? I am having issues with a particular request and the fellow running the webserver asked to see the full request (with headers and the such).
If you're just using Jersey Client API, LoggingFilter (client filter) should help you:
Client client = Client.create();
client.addFilter(new LoggingFilter(System.out));
WebResource webResource = client.resource("http://localhost:9998/");
ClientResponse response = webResource.accept(MediaType.APPLICATION_JSON)
.get(ClientResponse.class);
Otherwise, you can again log both request and response on server using other LoggingFilter (container filter).
Since Jersey 2.23, there's a LoggingFeature you could use. The following is a bit simplified example, please note that you can register the feature on WebTarget as well.
Logger logger = Logger.getLogger(getClass().getName());
Feature feature = new LoggingFeature(logger, Level.INFO, null, null);
Client client = ClientBuilder.newBuilder()
.register(feature)
.build();
Response response = client.target("https://www.google.com")
.queryParam("q", "Hello, World!")
.request().get();
JavaDoc of LoggingFeature says that the request "and/or" the response is logged lol. On my machine, both are logged.
#ivan.cikic's answer is for Jersey 1.x. Here's how you do it in Jersey 2.x:
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.filter.LoggingFilter;
import org.json.JSONException;
import org.json.JSONObject;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
...
ClientConfig config = new ClientConfig();
Client client = ClientBuilder.newClient(config);
client.register(new LoggingFilter());
This is irrelevant but I just have to complain: The new LoggingFilter is really annoying because it forces you to use Java Util Logging. It would be better if it gave me control over the logger. Seems like a step backwards in design.
All these answers are pretty close but they lack the setting to log the request and response body. At least with Jersey 2.30.1 this is how I accomplish logging the request and response including their respective bodies:
import javax.ws.rs.client.ClientBuilder;
import org.glassfish.jersey.logging.LoggingFeature;
import java.util.logging.Level;
import java.util.logging.Logger;
Logger logger = Logger.getLogger("LoggingFeature");
logger.setLevel(Level.ALL);
ClientBuilder.newClient()
.target("https://www.example.com")
.register(new LoggingFeature(
logger,
Level.ALL,
LoggingFeature.Verbosity.PAYLOAD_ANY,
8192))
.request()
.get();
Technically the Level.All and 8192 values could be null. I just provide them here to be concise.