I am trying to access the swagger URL from my Spring-Boot application using the post request. But getting a 400-Bad request and it says the request body is missing. But the same request works fine in Postman.
Controller:
#RestController
public class IdVController {
#Autowired
private IdService idService;
#Autowired
protected FileUtility util;
/** The Constant STATUS. */
private static final String STATUS = "status";
/** The Constant SUCCESS. */
private static final String SUCCESS = "success";
/** The Constant SYSTEM. */
private static final String SYSTEM = "SYSTEM";
#RequestMapping(value ="/idApi")
public ResponseEntity<MarketPlaceResponse>
validateIdData(#RequestBody VerifyIdDTO verifyIdDTO) throws Exception {
JSONObject rawResponse = idService.validateId(verifyIdDTO);
IdVerifyEntity DTOResponse = (IdVerifyEntity)util.convertToEntity(rawResponse.toString(), IdVerifyEntity.class);
if (rawResponse.get(STATUS).equals(SUCCESS)) {
DTOResponse.setCreated_by(SYSTEM);
DTOResponse.setCreated_date(new
java.sql.Date(System.currentTimeMillis()).toString());
}
//return ResponseBuilder.buildResponse(DTOResponse);
MarketPlaceResponse response = new MarketPlaceResponse();
response.setResponse(DTOResponse);
return new ResponseEntity<MarketPlaceResponse>(response,HttpStatus.OK);
}
}
Request DTO:
public class VerifyIdDTO {
#NotBlank(message="Owner ID should not be empty")
private String id;
private String citizenship;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCitizenship() {
return citizenship;
}
public void setCitizenship(String citizenship) {
this.citizenship = citizenship;
}
}
I am contacting an external service by building URL and using GET from this POST method
this is the swagger URL
localhost:8080/idvalidationservice/swagger-ui.html
You can see the error message in this screenshot.
Related
I'm sending a post request from the client to the server. The body of the post request looks like this:
...
body: JSON.stringify
({
command: 'someString',
dataFields: setDataList()
})
...
while the "setDataList()" returns the following structure:
[ {…}, {…}, {…}, ..., {…} ]
[0: {type: "_header_", label: "upload"}
1: {type: "_image_", name: "data:image/jpeg;base64", value: "base64 encoded string", label: "someImage.JPG"}
2: {...}]
I'm having issues processing the content of the "dataFields" key at the server. Currently, the SpringBoot applicaiton looks like this:
#PostMapping(
consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE})
public void postBody(#RequestBody ManageRequest manageRequest) {
...
}
and "ManageRequest" like this:
import java.util.List;
public class ManageRequest {
private String accountId;
private String command;
private String transactionId;
private List<String> dataFields;
public String getAccountId() {
return accountId;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
public List<String> getDataFieldList() {
return dataFields;
}
public void setDataFieldList(List<String> dataList) {
this.dataFields = dataList;
}
}
I'm not experienced in handling such requests with Java. My goal would be to extract the content of the "dataFields" like this: "dataFields[0], dataFields[1], ..." and allocate them to a new List to add to a post request.
At the moment, the list seems to be empty when arriving at the end point.
Your problems is with the List.
The server is waiting for a List of Strings but you are sending a List of objects with fields that are Strings.
private List<String> dataFields; // This property is a List of string not a list of "dataFields"
You should create a class DataField and it would looks like this
public class DataField{
private String type;
private String label;
private String name;
.
.
.
}
And then in your ManageRequest class you should do like this:
public class ManageRequest {
private String accountId;
private String command;
private String transactionId;
private List<DataField> dataFields;
//Getter and setters
}
I'm doing an API that consumes an external API (https://swapi.dev/), but I'm receving this error when I try to return the JSON converted to Object.
I'm trying to solve this for almost 12 hours without any success x_x
Error while extracting response for type [class [Lcom.starwarsapi.filmsapi.model.FilmModel;] and content type [application/json]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `[Lcom.starwarsapi.filmsapi.model.FilmModel;` from Object value (token `JsonToken.START_OBJECT`);
FilmController:
#RestController
#RequestMapping("/films")
public class FilmController {
#Autowired
private FilmService filmService;
#GetMapping
public List<FilmModel> getAllFilms() {
List<FilmModel> response = filmService.getAllFilms();
return response;
}
FilmModel:
#Data
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
public class FilmModel {
private FilmResultModel[] results;
}
FilmResultModel
#Data
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
public class FilmResultModel {
private String title;
#JsonProperty("episode_id")
private Integer episodeId;
#JsonProperty("opening_crawl")
private String description;
private String director;
private String producer;
#JsonProperty("release_date")
private String releaseData;
private String[] characters;
private String[] planets;
private String[] starships;
private String[] vehicles;
private String[] species;
private String created;
private String edited;
private String url;
FilmService:
public interface FilmService {
public List<FilmModel> getAllFilms();
}
FilmServiceImpl:
#Service
public class FilmServiceImpl implements FilmService {
#Value("${external.api.url}")
private String filmBaseUrl;
#Autowired
private RestTemplate restTemplate;
#Override
public List<FilmModel> getAllFilms() {
FilmModel[] result = restTemplate.getForObject(filmBaseUrl, FilmModel[].class);
List<FilmModel> films = Arrays.asList(result);
System.out.println(films);
return films;
}
PS¹: external.api.url = https://swapi.dev/api/films/?format=json
PS²: When I return getAllFilms as String, the program works:
#Override
public String getAllFilms() {
String result = restTemplate.getForObject(filmBaseUrl, String.class);
System.out.println(result);
return result;
}
But I need it to return as an object because later I'll try to create a PUT method to change the description of the movie.
try using FilmModel result = restTemplate.getForObject(filmBaseUrl, FilmModel.class);
FilmModel is just the outer wrapper object and contains the list of films.
I have a final class Constants, which holds some final data.
#Component
public final class Constants {
public final String TOKEN;
public final String HOST;
public final String TELEGRAM;
public Constants(#Value("${myapp.bot-token}") String token,
#Value("${myapp.host}") String host) {
this.TOKEN = token;
this.HOST = host;
this.TELEGRAM = "https://api.telegram.org/bot" + TOKEN;
}
}
The problem is that, when I want to use a variable as #PostMapping path, I faced this error:
Attribute value must be constant
#RestController
#RequestMapping
public class Controller {
private final Constants constants;
#Autowired
public Controller(Constants constants) {
this.constants = constants;
}
#PostMapping(constants.TOKEN)// Problem is here
public ResponseEntity<?> getMessage(#RequestBody String payload) {
return new ResponseEntity<HttpStatus>(HttpStatus.OK);
}
}
I've tried to load TOKEN in my controller class but faced the same issue.
#RestController
#RequestMapping
public class Controller {
#Value("${myapp.bot-token}") String token
private String token;
#PostMapping(token)// Problem is here
public ResponseEntity<?> getMessage(#RequestBody String payload) {
return new ResponseEntity<HttpStatus>(HttpStatus.OK);
}
}
When I do something like this the problem will gone. But I don't want to declare my token in source-code.
#RestController
#RequestMapping
public class Controller {
private final String TOKEN = "SOME-TOKEN";
#PostMapping(TOKEN)// No problem
public ResponseEntity<?> getMessage(#RequestBody String payload) {
return new ResponseEntity<HttpStatus>(HttpStatus.OK);
}
}
Can anyone please give me a solution to this?
Try to paste string with property path inside #PostMapping annotation. Like this
#GetMapping(value = "${app.path}")
public String hello() {
return "hello";
}
You can only use a constant (i.e. a final static variable) as the parameter for an annotation.
Example:
#Component
class Constants {
public final static String FACEBOOK = "facebook";
}
#RestController
class Controller {
#PostMapping(Constants.FACEBOOK)
public ResponseEntity<ResponseBody> getMessage(#RequestBody String payload) {
return new ResponseEntity<>(HttpStatus.OK);
}
}
You must use builder pattern(use Lombok for ease) and freeze the value that you are getting from the properties and then use that in your program.
I am trying to send one json from my frontend angular project to the backend which is springboot.
It is the first time I am using these 2 technologies so I lack in experience.
I am not quite sure if my http post method in Angular is wrong or if my backend isn't listening to the data which are supposed to come.
I will attach both code parts so that you can help me. Thank you in advance!
Here is a picture of the chrome console:
Http Errorcode 404
http error image
Backend:
#RestController
#RequestMapping
#CrossOrigin(origins = "http://localhost:4200")
public class RequestController {
private RolesRequestRepository rolesRequestRepository;
#PostMapping("/sendrolesrequest")
void addRequest(#RequestBody RolesRequest rolesRequest) {
rolesRequestRepository.save(rolesRequest);
}
#GetMapping("/sendrolesrequest")
public List<RolesRequest> getRequests() {
return (List<RolesRequest>) rolesRequestRepository.findAll();
}
}
#Entity
public class RolesRequest {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String requester = "";
private String recipient = "";
public RolesRequest(String recipient, String requester) {
this.recipient = recipient;
this.requester = requester;
}
public RolesRequest(){
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getRequester() {
return requester;
}
public void setRequester(String requester) {
this.requester = requester;
}
public String getRecipient() {
return recipient;
}
public void setRecipient(String recipient) {
this.recipient = recipient;
}
}
Here is the angular frontend part:
#Injectable()
export class RequestService {
sendRolesRequestUrl = 'sendrolesrequest'; // URL to web api
private handleError: HandleError;
constructor(
private http: HttpClient,
httpErrorHandler: HttpErrorHandler) {
this.handleError = httpErrorHandler.createHandleError('RequestService');
}
sendRolesRequest (rolesRequest: RequestModel): Observable<RequestModel> {
//console.log("addRolesRequest try post:" + rolesRequest.print());
return this.http.post<RequestModel>(this.sendRolesRequestUrl, rolesRequest, httpOptions)
.pipe(
catchError(this.handleError('sendRolesRequest', rolesRequest))
);
}
testPost() {
const headers = new Headers();
headers.append('Content-Type', 'application/json; charset=utf-8');
this.http.post(this.sendRolesRequestUrl, {'key1': 'value1', 'key2': 'value2'}, httpOptions)
.subscribe(() => {}, err => console.error(err));
}
}
export class RequestFormulaComponent implements OnInit {
onSendRequest() {
this.requestService
.sendRolesRequest(this.rolesRequest)
.subscribe();
}
}
I would be very happy if someone helps me out here. I am struggling on this topic over a week.
Is that even the way how a backend application should communicate with the webpage? If not, how can I do it otherwise?
You're using JPA entity as DTO, and have no setters/getters, also there is no default constuctor, modify your RolesRequest like this:
#Entity
public class RolesRequest {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String requester = "";
private String recipient = "";
public RolesRequest() { }
public RolesRequest(String recipient, String requester) {
this.recipient = recipient;
this.requester = requester;
}
public String getRequester() { return this.requester; }
public void setRequester(String r) { this.requester = r;}
public String getRecipient() { return this.recipient; }
public void setRecipient(String r) { this.recipient = r;}
Are your backend and angular app running on the same port? (backend and frontend are combined in the same application)
You are calling http://localhost:4200/sendrolesrequest and I think that's a request on the Angular app itself. You get a HTTP 404 error code (NOT FOUND)
You should call the endpoint of the backend application. It's running on port 8080 for example so call http://localhost:8080/sendrolesrequest (or with other port if backend is running on another port)
Change:
sendRolesRequestUrl = 'sendrolesrequest';
to:
sendRolesRequestUrl = 'http://localhost:8080/sendrolesrequest';
I have use case were I need to get requestBody based on selection of field.below is same code which I was able get the dynamic responseBody Based on selection ProtocolType.Is there is any way that swagger can read the RequestBody Dynamically.
Controller.Java
#ApiOperation(value = "Protocol Account", tags = {"ProtocolAccount"})
#RequestMapping(value = "/protocolAccount/{protocolName}",
method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody public ProtocolAccount getProtocol(#PathVariable String protocolName)
{
return service.getProtocol(protocolName);
}
Service.Java
public ProtocolAccount getProtocol(String protocolName){
ProtocolAccount protocolAccount=new ProtocolAccount();
Object object=ProtocolType.fromMap(protocolName);
protocolAccount.setProtocol(object);
return protocolAccount;
}
POJOs
public class ProtocolAccount
{
String Id;
private Object protocolType
}
public class Protocol{
private String port;
}
public class FTPProtocol extends Protocol{
/*Some Fields*/
}
public class SFTPProtocol extends Protocol{
/*Some Fields*/
}
Enumeration
public enum ProtocolType
{
SFTP("SFTP"), FTPS("FTPS"), AS2("AS2"), FTP("FTP");
private final String value;
private static final EnumMap<ProtocolType,
Object>map = new EnumMap<ProtocolType, Object>(ProtocolType.class);
static{
map.put(ProtocolType.SFTP, new SFTPProtocol());
map.put(ProtocolType.FTP, new FTPProtocol());
map.put(ProtocolType.FTPS,new FTPSProtocol());
}
ProtocolType(String v){
value=v;
}
public static ProtocolType fromValue(String val){
return EnumSet.allOf(ProtocolType.class)
.stream().filter(e->e.value.equals(val))
.findFirst().orElseThrow(()->new IllegalArgumentException(val));
}
public String value(){
return value;
}
public static Object fromMap(String value)
{
return map.get(ProtocolType.fromValue(value));
}
}