I am using Spring MVC in my project and while mapping user request to a URI, I get the 404 error. But there are other controllers where i'm able to access it.
Working controller
#RequestMapping(value = "groupview.htm", method = RequestMethod.GET)
public String showGroups(
#ModelAttribute("groupRegistrationDTO") GroupRegistrationDTO groupRegistrationDTO,
BindingResult result, Model model,
HttpServletRequest httpServletRequest) {
GroupsResultDTO groupsResultDTO = manageGroupBusiness.getGroups(
groupRegistrationDTO, result, model);
return "showGroups";
}
Testing with java class showing desired output
private static void wsRequest(String jsonInput) {
try {
URL url = new URL("http://localhost:5080/myservlet/groupview.htm");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept","*/*");
conn.setRequestProperty("Authorization", "Basic "
+ getBasicAuthenticationEncoding());
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Now i have another controller which is a restful service when i try to test that using poster plugin or through java net URL connection(using requestmethod post). I get 404 response code.
Trying to access with URL :
http://localhost:5080/myservlet/authAndRegDevice.htm
Rest Service Controller
#RequestMapping(value = "authAndRegDevice.htm", method = RequestMethod.POST)
#ResponseBody
public String authenticateAndRegisterDevice(
#RequestBody String notificationJsonRequest){
return "success";
}
Why would the second controller give the 404 error while the first one working.
Can some one please help me to get out of this issue
This issue can be closed here as i have raised another post with detailed question and with the exact failure where i was facing.
Bypass spring security with java URL connection
Related
I have a spring boot server running that accepts http request.
I have tested it extensively with curl and it works perfectly.
However when I try to send a request and receive a response in a java client I get:
java.io.IOException: Server returned HTTP response code: 400 for URL:
and on the server side I get:
[org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'Username' is not present]
Here is the spring boot method I am trying to use:
#PostMapping(path="/CreateAccount") // Map ONLY POST Requests
public #ResponseBody String CreateUser (#RequestParam String Username
, #RequestParam String Password) {
// #ResponseBody means the returned String is the response, not a view name
// #RequestParam means it is a parameter from the GET or POST request
//make sure the username and password is valid input
if (!validateInput(Username) || !validateInput(Password))
{
return "Username and Password cannot be blank";
}
//make sure the username is unique
//check if Username is equal to any other User's username
User u = findByUsername(Username);
//if a user was found in the table
if ( !(u == null) )
{
return "Username already taken\nPlease choose another";
}
//if we are here we are clear to make a new user
User n = new User();
n.setUsername(Username);
n.setPassword(Password);
n.setRole("Player");
userRepository.save(n);
//THIS CAUSES AN ERROR
//create a stat object to be added to the table
Stats s = new Stats();
s.setUsername(Username);
statRepository.save(s);
//create a token for the user
String usrToken = createToken(tokenSize);
//add the username and token to hashmap
userTokens.put(Username, usrToken);
//return this user's token
return usrToken;
}
And here is my client:
public static void CreateAccount(String username, String password)
{
try
{
String s = serverURL + "/CreateAccount";
URL url = new URL(s);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Content-Type", "application/json; utf-8");
connection.setDoOutput(true);
String json = "[{\n\"Username\"=\"Jake\",\"Password\"=\"123\"\n}]";
System.out.println(json);
OutputStream os = connection.getOutputStream();
DataOutputStream out = new DataOutputStream( os );
byte[] input = json.getBytes("utf-8");
out.writeUTF(json);
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response = br.readLine();
System.out.println(response);
}
catch (Exception e)
{
System.out.println("#");
System.out.println(e);
}
}
I thought it had to do with my json formatting but I've tried over and over and no matter how I format it I get the same error.
If you want send json object, use this code for example:
#PostMapping(path="/CreateAccount")
public #ResponseBody String CreateUser (#RequestBody User user) {
if (user == null)
{
return "User cannot be blank";
}
User u = findByUsername(user.Username);
// your code...
return usrToken;
}
I have a Spring Boot application written in Java that is a REST API. This service (Svc A) calls a REST API service (Svc B) with is also a Spring Boot Application written in Java. Svc B returns a 404 status code when no data was found. I need to change this response to a 200 status code and return an empty response object. I am not sure if or how to do this.
I can catch the error and determine if the 404 is this no data found error. However, I don't know how to change the response to a 200 empty response.
I am using a FeignClient to call the service. This is the error code that catches the 404:
#Component
public class FeignErrorDecoder implements ErrorDecoder {
Logger logger = LoggerFactory.getLogger(this.getClass());
#Override
public Exception decode(String methodKey, Response response) {
Reader reader = null;
String messageText = null;
switch (response.status()){
case 400:
logger.error("Status code " + response.status() + ", methodKey = " + methodKey);
case 404:
{
logger.error("Error took place when using Feign client to send HTTP Request. Status code " + response.status() + ", methodKey = " + methodKey);
try {
reader = response.body().asReader();
//Easy way to read the stream and get a String object
String result = CharStreams.toString(reader);
logger.error("RESPONSE BODY: " + result);
ObjectMapper mapper = new ObjectMapper();
//just in case you missed an attribute in the Pojo
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
//init the Pojo
ExceptionMessage exceptionMessage = mapper.readValue(result,
ExceptionMessage.class);
messageText = exceptionMessage.getMessage();
logger.info("message: " + messageText);
} catch(IOException ex) {
logger.error(ex.getMessage());
}
finally {
try {
if (reader != null)
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return new ResponseStatusException(HttpStatus.valueOf(200), messageText);
}
default:
return new Exception(response.reason());
}
}
}
I can change the status code to a 200 and it returns a 200 but I need to the response to have an empty response object.
The above code will return this response body of an error response object:
{
"statusCd" : "200",
"message" : "The Location not found for given Location Number and Facility Type Code",
"detailDesc" : "The Location not found for given Location Number and Facility Type Code. Error Timestamp : 2020-01-31 18:19:13"
}
I need it to return a response body like this:
200 - Empty Response
{
"facilityNumber": "923",
"facilityTimeZone": null,
"facilityAbbr": null,
"scheduledOperations": []
}
In case 404 just try
return new ResponseStatusException(HttpStatus.valueOf(200));
For anyone that has to do something this crazy...here is my solution:
Removed the FeignErrorCode file.
Added an exception to ControllerAdvice class like this:
#ExceptionHandler(FeignException.class)
public ResponseEntity<?> handleFeignException(FeignException fe, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), HttpStatus.valueOf(fe.status()), fe.getMessage(), request.getDescription(false));
String response = fe.contentUTF8();
if(response != null) {
ScheduledOperationsViewResponse scheduledOperationsViewResponse = new ScheduledOperationsViewResponse();
if (response.contains("Scheduled") || response.contains("Location")) {
HttpHeaders headers = new HttpHeaders();
scheduledOperationsViewResponse.setFacilityNumber(request.getParameter("facilityNumber"));
return new ResponseEntity<ScheduledOperationsViewResponse>(scheduledOperationsViewResponse, headers, HttpStatus.OK);
}
}
return new ResponseEntity<>(errorDetails, errorDetails.getStatus());
}
I know we can use the /graphiql endpoint to test the created or deployed GraphQL API.
I need to consume a GraphQL API which is already there using a Java code. How can I do it.
How can I test a GraphQL end-point using a postman like application, or is it even possible.
Depending on your situation, utilizing Spring RestTemplate might be simplest thing to do.
public class Person {
#JsonProperty("query")
public final String query = "mutation($name:String, $gender:String, $age:Int) { updateDetails (name: $name, gender: $gender, age: $age) }";
#JsonProperty("variables")
public final Map<String, String> variables;
...
}
...
(new RestTemplate()).postForEntity("http://example.com/graphql", new Person("David", "male", 12));
Could go even simpler by avoiding Spring and using HttpClient, building same JSON document using StringBuilder.
Alternatively Apollo Andoid can autogenerate client code for you.
An example, to work for me...
username and password are wrong :) But, URL is ok...
with that, I don't use RestTemplate, any jars, etc..
private static void test_LivePharma() {
try {
URL url = new URL("https://stores-hml.funcionalmais.com/graphql");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("GET");
conn.setRequestProperty("Content-Type", "application/json");
String input="{\"query\":\"mutation{createToken(login:\\\"112233\\\",password:\\\"112233\\\"){ token}}\\n\"}";
OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Consuming graphql API in your backend code, will require multiple steps such as.
Defining the schema
Installing the dependencies
Defining the graphql endpoint
import com.coxautodev.graphql.tools.SchemaParser;
import javax.servlet.annotation.WebServlet;
import graphql.servlet.SimpleGraphQLServlet;
#WebServlet(urlPatterns = "/graphql")
public class GraphQLEndpoint extends SimpleGraphQLServlet {
public GraphQLEndpoint() {
super(SchemaParser.newParser()
.file("schema.graphqls") //parse the schema file created earlier
.build()
.makeExecutableSchema());
}
}
Here is a detailed guide to do the same : Graphql-java-backend-implementation
Yes, it is possible to send the request using postman. You can simply copy the schema in the body.
Doing GraphQL request using Postman
I am requesting for put operation and after request performed I am redirecting to GET service URL.Here, I am facing the issue of 405 HTTP error code. However, same code works for me in the case of POST operation.
Below code is EndPoint:
#PUT
#Produces({ MediaType.APPLICATION_JSON })
public Response put(InputStream objInputStream) {
// System.out.println("AckService.put()");
String strOutput = "";
Status objStatus = Status.OK;
URI objRedirectionURI = null;
try {
this.submitRequest(objInputStream);
objRedirectionURI = new URI("https://local.test.com:8443/Reply/fetch");
System.err.println("\n\nredirecting the put request...... to get operation\n\n");
return Response.seeOther(objRedirectionURI).build();
} catch (Exception e) {
e.printStackTrace();
objStatus = Status.INTERNAL_SERVER_ERROR;
}
}
Client:
ClientResponse response = null;
try {
response = objWebResource.accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON)
.put(ClientResponse.class, strInputData);
}catch (Exception e) {
blnIsOk = false;
if(null != e.getMessage())
lstExceptionMessage.add(e.getMessage());
e.printStackTrace();
}
Please let me know how I can resolve this.
In that question I think you can find the answer:
PUT-POST Rest Information
I am programming a jax-rs webservice which I want to contact from a java-program. I defined a #POST method which receives a String-array as input and is supposed to return a boolean value.
But really, how can i access this return value in java? I've been searching the web for several hours now, everybody writes example methods which return Strings or something else, but nobody shows how to access the returned value from another java program.
Here is the code from the program that contacts the #POST method:
ObjectOutputStream oos = null;
String[] login = {"XXXXXX","XXXXXXX"};
try {
login[1] = PasswordGenerator.hashPassword(login[1]);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
URL url = new URL("XXXXX/XXXXXXX/XXXXXX/users/login/1");
try {
// creates a HTTP connection
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true);
httpConn.setRequestMethod("POST");
httpConn.setRequestProperty("Boolean", "application/xml");
OutputStream outputStream = httpConn.getOutputStream();
oos = new ObjectOutputStream(outputStream);
outputStream.close();
System.out.println();
} finally {
if (oos != null) {
oos.close();
}
}
}
What I want to know is: What happens after I closed my outputStream? I mean, i started the POST method, but it is supposed to return a boolean value. Where is this value? How can I access it???
JAX-RS 2.0 has a Client API that provides you with a fluent API to retrieve the content of the response:
Client client = ClientBuilder.newClient();
Boolean result = client.target("http://localhost:8080/xxx/")
.path("user/login/1")
.request(MediaType.TEXT_PLAIN_TYPE)
.post(Entity.entity(login, MediaType.APPLICATION_XML) , Boolean.class);
But unfortunately, you'll need a custom MessageBodyWriter to convert the String[] into an XML document. Maybe you should change your server-side method (and client) to manipulate a DTO - a POJO with 2 fields, username and password - and annotated with #XmlRootElement ?
something like that:
(client-side)
Credentials credentials = new
credentials.setUsername("foo");
credentials.setUsername("hashedPwd");
Client client = ClientBuilder.newClient();
Boolean result = client.target("http://xxxxx")
.path("/user/login/1")
.request(MediaType.TEXT_PLAIN_TYPE)
.post(Entity.entity(credentials, MediaType.APPLICATION_XML) , Boolean.class);
System.out.println("Result: " + result);
(server-side)
#Path("/login/{id}")
#POST
public Boolean test(#PathParam("id") String login, Credentials credentials) {
...
}