I am new at Spring and Rest.
I wrote a simple rest like this:
#RequestMapping(value = "/loginTest", method = RequestMethod.POST)
#ResponseBody
public Response loginTest(#RequestBody LoginRequest request) {
System.out.println("enter loginTest.");
String account = request.getAccount();
String password = request.getPassword();
Response res = new Response();
return res;
}
And the LoginRequest is like this:
public class LoginRequest {
private String account;
private String password;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
When I test this via command:
curl -X POST "{"account": "aaa","password": "bbb"}" -H "Content-type:application/json" http://localhost:8080/user/loginTest
But I got the result:
[1/2]: account: aaa --> <stdout>
--_curl_--account: aaa
curl: (6) Could not resolve host: account; nodename nor servname provided, or not known
{
"timestamp" : "2015-12-30T16:24:14.282+0000",
"status" : 400,
"error" : "Bad Request",
"exception" : "org.springframework.http.converter.HttpMessageNotReadableException",
"message" : "Bad Request",
"path" : "/user/loginTest"
}
And also in eclipse console:
Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.test.response.Response com.test.service.UserService.loginTest(com.test.model.request.LoginResquest)
Does the class LoginRequest need an annotation? Because the Jason cannot be converted to a class?
Would anyone help me figure this out?
Request body should be sent in --data switch, in curl.
See this https://superuser.com/questions/149329/what-is-the-curl-command-line-syntax-to-do-a-post-request
So your request should now become
curl -X POST --data '{"account": "aaa","password": "bbb"}' -H "Content-Type:application/json" http://localhost:8080/user/loginTest
Also if you can run a browser on the machine where you're sending the requests from, then you can try some REST client plugins. They're way easier to use and provide saving requests and history features.
Check this plugin
Related
I have a java application that calls another application it works well for the exist get function my generate this error 400 BAD_REQUEST when I try to create with a Put function.
curl -XPUT URLSERVER2/users/usernameToBeUsed \
-d '{"password":"passwordToBeUsed"}' \
-H "Content-Type: application/json"
#Service
public class Server2Api {
#Value("${source.server2.base.url}")
private String baseUrl;
Logger log = LoggerFactory.getLogger(getClass());
private static final Duration REQUEST_TIMEOUT = Duration.ofSeconds(1);
private final WebClient localApiClient;
public Server2Api(WebClient.Builder localApiClient) {
this.localApiClient = localApiClient.baseUrl(baseUrl).build();
}
public ResponseEntity<Void> creatUser(String username, String pwd){
String body = "{'password':'"+ pwd +"'}";
return localApiClient
.put()
.uri(baseUrl+"/users/"+username )
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(body)
.exchangeToMono(
response -> response.toBodilessEntity()
)
.block(REQUEST_TIMEOUT);
}
}
I just try to change "{'password':'"+ pwd +"'}" to "{password:'"+ pwd +"'}".
with Postman resquest works. URL is ok work on get function
I have a rest API implemented in Java (MSF4J codegen from swagger) and a swagger 2 definition that describes it.
A swagger UI is hosted on a web server. The API is deployed on a VM somewhere on the internet.
My Problem is that the "try it out" function of the swagger UI doesn't work. I always get a "401 Unauthorized". When I take the curl command from the UI and paste it into my terminal it works.
Last week I didn't have HTTPS or Basic Authentication - just HTTP - and it worked fine. Now I don't know why it doesn't work.
Since I changed the swagger definition to https the UI makes an OPTIONS request. I implemented that, but I get 401 responses.
The certificate comes from Lets Encrypt and is used by an apache web server. The apache is a proxy to the rest api on the same machine.
Here is my authentication interceptor:
public class BasicAuthSecurityInterceptor extends AbstractBasicAuthSecurityInterceptor {
#Override
protected boolean authenticate(String username, String password) {
if (checkCredentials(username, password))
return true;
return false;
}
private boolean checkCredentials(String username, String password) {
if (username.equals("testuser"))
return BCrypt.checkpw(password, "$2a$10$iXRsLgkJg3ZZGy4utrdNyunHcamiL2RmrKHKyJAoV4kHVGhFv.d6G");
return false;
}
}
Here is a part of the api:
public abstract class DeviceApiService {
private static final Logger LOGGER = LogManager.getLogger();
public abstract Response deviceGet() throws NotFoundException;
public abstract Response deviceIdAvailableLoadGet(Integer id, Long from, Long to, String resolution)
throws NotFoundException;
public abstract Response deviceIdGet(Integer id) throws NotFoundException;
protected Response getOptionsResponse() {
String allowedOrigin = "";
try {
allowedOrigin = PropertyFileHandler.getInstance().getPropertyValueFromKey("api.cors.allowed");
} catch (IllegalArgumentException | PropertyException | IOException e) {
LOGGER.error("Could not get allowed origin.", e);
}
Response response = Response.ok().header("Allow", "GET").header("Access-Control-Allow-Origin", allowedOrigin)
.header("Access-Control-Allow-Headers", "authorization, content-type").build();
return response;
}
}
public class DeviceApi {
private final DeviceApiService delegate = DeviceApiServiceFactory.getDeviceApi();
// #formatter:off
#GET
#Produces({ "application/json" })
#io.swagger.annotations.ApiOperation(
value = "Get devices",
notes = "",
response = Device.class,
responseContainer = "List",
authorizations = { #io.swagger.annotations.Authorization(value = "basicAuth") },
tags = { "Device", }
)
#io.swagger.annotations.ApiResponses(
value = { #io.swagger.annotations.ApiResponse(
code = 200,
message = "200 OK",
response = Device.class,
responseContainer = "List")
})
public Response deviceGet() throws NotFoundException {
return delegate.deviceGet();
}
#OPTIONS
#Consumes({ "application/json" })
#Produces({ "application/json" })
#io.swagger.annotations.ApiOperation(value = "CORS support", notes = "", response = Void.class, authorizations = {
#io.swagger.annotations.Authorization(value = "basicAuth") }, tags = { "Device", })
#io.swagger.annotations.ApiResponses(value = {
#io.swagger.annotations.ApiResponse(code = 200, message = "Default response for CORS method", response = Void.class) })
public Response deviceOptions() throws NotFoundException {
return delegate.getOptionsResponse();
}
}
EDIT:
This are the headers of the request the swagger ui creates:
Accept: text/html,application/xhtml+xm…plication/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: de,en-US;q=0.7,en;q=0.3
Access-Control-Request-Headers: authorization
Access-Control-Request-Method: GET
Connection: keep-alive
DNT: 1
Host: api.myfancyurl.com
Origin: http://apidoc.myfancyurl.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; …) Gecko/20100101 Firefox/61.0
It seems that the authorization header is missing. When I edit the request and resend it with the authorization header and encoded credentials it works.
But I don't know why swagger doesn't add this header. Should one accept all options requests without authorization?
My POJO/data model:
public class CanResendResponse {
#JsonProperty(value = "canResend")
#NotEmpty
public Boolean canResend;
// getters, setters & ctors
}
My Spring Boot controller & method:
#RestController
#RequestMapping("v1/data/fizzes")
class FizzResource {
#GetMapping(value = "{fizzId}/canResend")
public void canResendVerifications(#PathVariable(value = "fizzId") String fizzId) {
Fizz fizz = fizzRepository.findById(fizzId);
Boolean canResend;
System.out.println("Fizz name:" + fizz.getName());
if(fizz.canResend()) {
canResend = Boolean.TRUE;
} else {
canResend = Boolean.FALSE;
}
return new ResponseEntity<CanResendResponse>(new CanResendResponse(canResend), HttpStatus.OK);
}
}
My curl command:
curl -H "Content-Type: application/json" -X GET https://localhost:9200/v1/data/fizzes12345/canResend
When I run the curl command I don't see any exceptions/error on the server side and the curl completes without error but I do not see the expected HTTP response entity, like:
{
"canResend" : "true"
}
However I do see the Fizz name: Joe message in STDOUT.
I've confirmed the same behavior in a browser (I punch https://localhost:9200/v1/data/fizzes12345/canResend) into a browser and the response/page is empty. Any ideas as to what I can do to fix this?
Your method has VOID return type. Try this:
#GetMapping(value = "{fizzId}/canResend")
public ResponseEntity canResendVerifications(#PathVariable(value = "fizzId") String fizzId) {
Your method code goes here...
}
Change
public void canResendVerifications(#PathVariable(value = "fizzId") String fizzId) {
to
public ResponseEntity<> canResendVerifications(#PathVariable(value = "fizzId") String fizzId) {
... and make sure you return that ResponseEntity.
I work with an Apache Cxf, Spring Jax-rs service and I have the following service definition and the implementations provided,
THE DEFINITION
#POST
#Path("/generateAddress")
#Consumes(MediaType.APPLICATION_JSON)
#Produces({MediaType.APPLICATION_JSON})
WalletInfo generateAddress(final String walletName, String currencyName);
THE IMPLEMENTATIONS
public synchronized WalletInfo generateAddress(final String walletName, String currencyName) {
WalletInfo walletInfo = IWalletInfoDao.getWalletInfoWithWalletNameAndCurrency(walletName, currencyName);
return walletInfo;
}
When I do the POST request with the cURL like
curl -H "Content-Type: application/json" -X POST -d '{"walletName":"Icecream5500","currencyName":"Bitcoin"}' http://localhost:8080/api/rest/wallet/generateAddress
I get the JSON response back,
{
"msg" : "Stream closed",
"date" : "2017-08-28T09:22:027Z"
}
I'm pretty sure that the generateAddress method works fine. What is
the issue here and particularly, when you would get the message Stream closed in the Spring Apache Cxf project while doing the POST requests? Obviously, I can provide more info if required. The server log is normal and I see nothing unusual.
The POST body doesn't match with the parameters of the method and this created the issue in the first place. I have solved the problem in the following options.
I created a new class
public class CreateWalletWithNameAndCurrency {
String walletName;
String currencyName;
public CreateWalletWithNameAndCurrency(String walletName, String currencyName) {
this.walletName = walletName;
this.currencyName = currencyName;
}
public CreateWalletWithNameAndCurrency() {
}
public String getWalletName() {
return walletName;
}
public String getCurrencyName() {
return currencyName;
}
public void setCurrencyName(String currencyName) {
this.currencyName = currencyName;
}
public void setWalletName(String walletName) {
this.walletName = walletName;
}
}
I changed the definition of the POST request like this,
#POST
#Path("generateAddress")
#Consumes(MediaType.APPLICATION_JSON)
#Produces({MediaType.APPLICATION_JSON})
WalletInfo generateAddress(CreateWalletWithNameAndCurrency createWalletWithNameAndCurrency);
The implementation is provided below,
public synchronized WalletInfo generateAddress(CreateWalletWithNameAndCurrency createWalletWithNameAndCurrency) {
String walletName = createWalletWithNameAndCurrency.getWalletName();
String currencyName = createWalletWithNameAndCurrency.getCurrencyName();
WalletInfo walletInfo = iWalletInfoDao.getWalletInfoWithWalletNameAndCurrency(walletName, currencyName);
// some more code
}
Finally, I can do the POST request like this,
curl -H "Content-Type: application/json" -X POST -d '{"walletName":"Copenhangen","currencyName":"Bitcoin"}' http://localhost:8080/rest/wallet/generateAddress
I google this matter for hours but I still cannot find solution.
Here is my java code
#POST
public String doLogin(User user) {
System.out.println(" = " + user.getUsername());
return "";
}
and
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class User {
String username;
String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
and here is my AngularJs code
angular.module('notesApp', []).controller('MainCtrl', ['$http', function($http) {
var self = this;
self.submit = function() {
$http({
method: 'POST',
url: 'http://127.0.0.1:8080/Test/app/login',
headers : {'Content-Type': 'application/json'},
data: self.user //forms user object
})
.then(function(response) {
console.log(response.data);
return response.data;
}, function(response) {
});
}
}]);
My error message was:
SEVERE: A message body reader for Java class entity.User, and Java type class entity.User, and MIME media type application/json; charset=UTF-8 was not found, as I could not access 'user' Object in java code.
Could you please figure out which part I do wrong? Thank you so much.
You need to read from POST body and not Query Params.
You can use this:
#POST
public String doLogin( User user) {
System.out.println(" = " + user.getUsername());
return "";
}
#QueryParam is used to the queryparams which you'll pass as ?user=xyz#gmail.com
Remove query param You will get a serialized string. deSerialize it to User.
#POST
public String doLogin(User user) {
System.out.println(" = " + user.getUsername());
return "";
}
You are setting the data field on your POST. This sets the HTTP Body, not an HTTP query param.
Check the browser debugger networking panel to ensure that you are sending what you expect to the server. will open it and then 'send' your user and look at what is sent. Does this object look exactly like what User in java expects?