I have a REST API defined in a SpringBoot application and I'm trying to access this via POST using a different application deployed on a Tomcat 8 server. Upon doing a POST from the other application, I get the following error in the SpringBoot logs:
Request method 'POST' not supported.
Here is my Rest Controller class:
#Controller
public class RestApiController {
#RequestMapping(value="/cancel", method=RequestMethod.GET)
public #ResponseBody String CancelJobEndPointInfo() {
return "A job can be cancelled by POSTing to this URL";
}
#RequestMapping(value="/cancel", method=RequestMethod.POST)
public #ResponseBody DataPost CancelJobEndPoint(#RequestParam("username") String name,
#RequestParam(name = "passPhrase", defaultValue = "null") String passPhrase,
#RequestParam("jobnumber") String jobNumber, #RequestParam("file") MultipartFile file){
UserDetails userObject = new UserDetails();
CancelJob job = new CancelJob();
DataPost dpc = new DataPost();
if (!file.isEmpty()) {
try {
/*
* Write private key
*/
byte[] ppkBytes = file.getBytes();
BufferedOutputStream ppkStream =
new BufferedOutputStream(new FileOutputStream(new File(file.getOriginalFilename())));
ppkStream.write(ppkBytes);
ppkStream.close();
userObject.setKeyPath(file.getOriginalFilename());
userObject.setUserName(name);
userObject.setPassphrase(passPhrase);
job.getCancelJob(userObject, jobNumber);
dpc.setMessage("Job:" + jobNumber + " Cancelled successfully");
return dpc;
} catch (IOException e) {
dpc.setMessage("Could not cancel the job:" + jobNumber + " ERROR => " + e.getMessage());
return dpc;
// return "Could not cancel the job:" + jobNumber + " ERROR => " + e.getMessage();
} catch (JSchException e){
// return "Could not cancel the job:" + jobNumber + " ERROR => " + e.getMessage();
dpc.setMessage("Could not cancel the job:" + jobNumber + " ERROR => " + e.getMessage());
return dpc;
}
} else {
dpc.setMessage("Private Key file for user: " + name + " is empty");
return dpc;
// return "Private Key file for user: " + name + " is empty";
}
}
I could see that a GET request is going through successfully, but I'm not sure what is wrong with the PUT request.
Also, I am able to invoke the API via POST by using html files within the application that has the REST methods.
I am facing this issue while trying to invoke it from a different application.
Following is the form that I am using:
<form action="http://localhost:8080/cancel" enctype="multipart/form-data"
method="post" accept-charset="utf-8" id="jobCancelForm"
name="job">
<h4 class="section-heading">User Details:</h4>
<fieldset class="form-group">
<label for="UserID">User Name</label> <input type="username"
class="form-control" id="canceluser"
placeholder="Enter SSH User ID" name="username">
</fieldset>
<fieldset class="form-group">
<label for="passPhrase">PassPhrase :</label> <input
type="password" class="form-control" id="cancelpass"
placeholder="Private Key PassPhrase" name="passPhrase">
</fieldset>
<fieldset class="form-group">
<label for="PrivateKeyFileInput">Private Key File</label> <input
type="file" class="form-control-file"
id="cancelPrivateKeyFileInput" name="cFile"> <small
class="text-muted">Select the pre-configured private
key file to be used for SSH authentication.</small>
</fieldset>
<a role="separator" class="divider"></a>
<hr>
<h4 class="section-heading">Job Details:</h4>
<fieldset class="form-group">
<label for="jobID">Job ID :</label> <input type="number"
class="form-control" id="canceljobID"
placeholder="Enter the job ID Ex: 1242254" name="jobNumber">
</fieldset>
<button type="submit" class="btn btn-primary"
id="jobMonitorButton">Cancel Job</button>
</form>
<a role="separator" class="divider"></a>
<!-- response div -->
<div style="word-wrap: break-word;" id="cancelResponse"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default"
data-dismiss="modal" id="jobCancelFormCloseButton">Close</button>
</div>
</div>
Any pointers please?
It seems to me the same issue for what the solution is provided here
Add #RequestMapping("YOUR-CONTEXT-VALUE") on the controller's class and remove value from #RestController annotation.
Related
Using #ModelAttribute I am able to post form-data to my backend without issue, however when I try to include a multipart file the server returns a 500 error. There are no console warnings or stack traces thrown, and the POST request endpoint is never hit according to my debugger.
I've tried working backwards, and replacing the MultiPartFile with just a String and changing the file attribute in the HTML to text, and it works just find sending Strings and ints to the back end, but when I add the file type back in and switch the model to MultipartFile, it breaks...
The html form fragment, the submit button triggers the POST request to /new:
<form method="POST" enctype="multipart/form-data" th:action="#{/release/new}" class="mx-auto w-50" th:object="${package}">
<th:block th:include="fragment/error-message.html"></th:block>
<fieldset>
<legend>Release Package Information</legend>
<div class="row">
<div class="col-sm-6 mb-3">
<label>Release Package ID</label>
<input type="text" class="form-control" placeholder="Enter the release package ID" th:field="*{releasePackageId}">
</div>
</div>
<div class="row">
<div class="col-sm-12 mb-3">
<label>Nomenclature</label>
<input type="text" class="form-control" placeholder="Enter the part nomenclature" th:field="*{nomenclature}">
</div>
</div>
<div class="row">
<div class="col-sm-12 mb-3">
<label>File</label>
<input type="file" class="form-control" placeholder="Select the part to upload" th:field="*{file}">
</div>
</div>
</fieldset>
<div class="row">
<div class="col-sm-6">
<a th:href="#{/release}" class="btn btn-outline-secondary w-100">
Back
</a>
</div>
<div class="col-sm-6">
<button type="submit" class="btn btn-outline-success w-100">
Submit
</button>
</div>
</div>
</form>
And here are the controller endpoints for /release/new:
#GetMapping("/new")
public ModelAndView showCreateReleasePackageForm()
{
return new ModelAndView("new-release").addObject("package", new CreateReleasePackageDTO());
}
#PostMapping("/new")
public String createReleasePackage(#ModelAttribute("package") CreateReleasePackageDTO releasePackageDTO, BindingResult result, RedirectAttributes attributes)
{
if (result.hasErrors())
{
return "new-release";
}
String response = "a response";
System.out.println(releasePackageDTO.getReleasePackageId() + releasePackageDTO.getNomenclature() + releasePackageDTO.getFile());
// TODO: Exception handling
// try
// {
// response = this.fileService.save(ReleasePackageMapper.toEntity(releasePackageDTO));
// } catch (JsonProcessingException e)
// {
// response = e.getMessage();
// e.printStackTrace();
// }
attributes.addFlashAttribute("message", response);
return "redirect:/release";
}
Here is the DTO, the model object I am calling "package":
#Getter
#Setter
public class CreateReleasePackageDTO
{
#NotNull(message = "{NotNull.releasePackageId}")
private int releasePackageId;
#NotEmpty(message = "{NotEmpty.nomenclature}")
private String nomenclature;
#NotEmpty(message = "{NotEmpty.multipartFile}")
private MultipartFile file;
}
I'm trying to create new user. i want to send user information with image to mysql database. I'm sending a user object with form data .
this is my component.ts
subscribeUser() {
this.errorMessage = "";
if (this.subscribeForm.invalid) {
this.errorMessage = "cannot create user with empty fields";
return;
}
this.userService.createUser(this.user, this.selectedFile)
.subscribe(data => {
console.log(data);
this.router.navigate(['/login']);
}, error => {
console.log(error);
});
}
public onFileChanged(event) {
console.log(event);
this.selectedFile = event.target.files[0];
console.log(this.selectedFile);
}
this my service.ts
createUser(user: User,file : File) { let formdata: FormData = new FormData(); const userBlob = new Blob([JSON.stringify({"firstname":user.firstname,"lastname":user.lastname,"mail":user.mail,"password":user.password})],{ type: "application/json"});formData.append('file', file); formData.append('user', userBlob);return this.http.post<User>(AppSettings.APP_URL + "/users/new", formData,{responseType:'text' as 'json'});}
this is my controller.java
#PostMapping(value="/",
produces = MediaType.APPLICATION_JSON_VALUE,
consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE,"multipart/form-data"}))
public ResponseEntity createUser(#RequestPart("file") MultipartFile file, #RequestPart("user") User user) throws IOException {
if(user == null){
return ResponseEntity.badRequest().body("cannot create user with empty fields");
}
User createdUser = userRepository.save(user);
return ResponseEntity.ok(createdUser);
}
this is my component.html
<form [formGroup]="subscribeForm" (ngSubmit)="subscribeUser()" novalidate>
<div class="form-group">
<label for="formGroupExampleInput">Nom</label>
<input type="text" class="form-control" id="firstname" [(ngModel)]="user.firstname" name="firstname" placeholder="Nom" formControlName="nom">
</div>
<div class="form-group">
<label for="formGroupExampleInput2">Prénom</label>
<input type="text" class="form-control" id="lastname" [(ngModel)]="user.lastname" name="lastname" placeholder="Prenom" formControlName="prenom">
</div>
<div class="form-group">
<label for="formGroupExampleInput3">Email</label>
<input type="text" class="form-control" id="mail" [(ngModel)]="user.mail" placeholder="Email" name="mail" formControlName="mail" >
</div>
<div class="form-group">
<label for="formGroupExampleInput4">Password</label>
<input type="text" class="form-control" id="password" [(ngModel)]="user.password" placeholder="Password" formControlName="password" >
</div>
<div class="form-group">
<input type="file" [(ngModel)]="user.photo" (change)="onFileChanged($event)"></div>
<button class="btn btn-primary" type="submit">Register</button>
</form>
I get this error
"Content type 'application/octet-stream' not supported"
Thank you
Have you consider changing image type from File to BLOB.
And in REST Controller you can treat it as MultipartFile
Edit: the error you get
"Content type 'application/octet-stream' not supported"
I think it's your header mime type (see this mime type )
I can't send parameters from view to control using Spring thymeleaf. This is my controller:
#GetMapping(value="/adminP")
public String adminParameter(
#RequestParam(value = "p", required = false) String p,
Model model) {
model.addAttribute("p", p);
System.out.println("The parameter is " + p);
return "adminPage";
}
And this is the form (I'm using a bootstrap modal):
<div id="modalBody" class="modal-body">
<form th:action="#{/adminP}" method="get">
<input type="text" th:name="p">
</div>
<div class="modal-footer">
<button type="submit" th:name="action" class="btn btn-default" data-dismiss="modal">Confirm</button>
</form>
</div>
When I send the form, the console doesn't print.
Do you know where's the problem?
Thank you all
I have an html page (format - FTL) in which I am trying to send data to a controller method. I am only trying to print the items that the user typed, nothing fancy for the beginning. I get the error - Required String parameter 'user_id' is not present
I work with spring mvc and freemarker.
This is the signup.ftl file -
<form method="POST", action="GET">
<div class="container">
<h1>Register</h1>
<p>Please fill in this form to create an account.</p>
<hr>
<label for="email" id="email"><b>Email</b></label>
<input type="text" placeholder="Enter Email" name="email" required>
<label for="password" id="password"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="password" required>
<label for="user_id" id="user_id"><b>User ID</b></label>
<input type="text" placeholder="user_id" name="user_id" required>
<hr>
<p>By creating an account you agree to our Terms & Privacy.</p>
<button type="submit" class="registerbtn">Register</button>
</div>
<div class="container signin">
<p>Already have an account? Sign in.</p>
</div>
</form>
</body>
</html>
This is the controller -
#RequestMapping(value = "/signup", method = RequestMethod.GET)
public String signup(#RequestParam("user_id")String user_id, #RequestParam("password")String password, #RequestParam("email")String email, Model model) {
System.out.println("coming in controller" + user_id + " " + password);
return "signup";
}
You are passing wrong action method and value.
You have to match the controller method signature which is
#RequestMapping(value = "/signup", method = RequestMethod.GET)
Change form tag to below line of code.
<form method="GET", action="signup">
I'm new to Struts2 framework and I found a problem when I try to edit an object.
The code of my modification action:
#Action(value = "modifyServer", results = {
#Result(name = "success", location = Location.MAIN_PAGE),
#Result(name = "error", location = Location.LOGIN_PAGE) })
public String modifyServer() {
em = DbConnexion.getEntityManager().createEntityManager();
String id=request.getParameter(sssid);
logger.info("id serveur = "+request.getParameter("id"));
try {
em.getTransaction().begin();
Simserver server = em.find(Simserver.class, id);
server.setSssServer(request.getParameter("sssServer"));
server.setSssIp(request.getParameter("sssIp"));
server.setSssPort(request.getParameter("sssPort"));
em.getTransaction().commit();
System.out.println("modification done !!!");
em.close();
return SUCCESS;
} catch (Exception e) {
return ERROR;
}
}
The JSP:
<form class="form-horizontal" action="modifyServer" role="form"
name="form_message" method="get">
<div id="elmsg"></div>
<div class="panel panel-info">
<div class="panel-heading expand" id="second-level">
<h6 class="panel-title">Modification du Serveur</h6>
</div>
<div class="panel-body">
<div class="form-group">
<label class="col-sm-2 control-label"> Id du Serveur : <span
class="mandatory">*</span></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="sssId"
disabled="disabled" id="sssId"
value="<s:property value="#request.curentserver.sssId" />">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"> Nom du Serveur : <span
class="mandatory">*</span></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="sssServer"
id="sssServer"
value="<s:property value="#request.curentserver.sssServer" />">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"> Adresse IP : <span
class="mandatory">*</span></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="sssIp" id="sssIp"
value="<s:property value="#request.curentserver.sssIp" />" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"> Port : <span
class="mandatory">*</span></label>
<div class="col-sm-10">
<input type="text" class="form-control" name="sssPort" id="sssPort"
value="<s:property value="#request.curentserver.sssPort" />" />
</div>
</div>
<div class="form-actions text-right">
<button type="submit" value="Envoyer" class="btn btn-success"
>Modifier le serveur</button>
<a role="button" href="gestionServeurList" class="btn btn-danger">Retour
à la list des serveurs</a>
</div>
When I execute my action the request.getParameter returns null.
I think the issue is in the parameter!
There are issues with code:
In Java code you are trying to print a request parameter with name as "id" instead of "sssId".
Also you are trying to use a variable called "sssid" that is no where defined in your question.
String id=request.getParameter(sssid);
logger.info("id serveur = "+request.getParameter("id"));
In JSP the sssId element is disabled, when you submit a form the disabled elements are ignored.
<input type="text" class="form-control"
name="sssId" disabled="disabled" id="sssId"
value="<s:property value="#request.curentserver.sssId" />">
So to get its value, create a hidden element in your jsp and on form submission update the hidden element with the required value using JavaScript.
<input type="hidden" name="sssId" value=""/>
In Javascript it will be like:
document.getElementById("sssId").value = 123; // Give value here
document.getElementById("myForm").submit(); // Give an Id to your form, say "myForm"
Finally the Action code looks like this :
public class MyAction extends ActionSupport implements ServletRequestAware {
#Action(value = "modifyServer", results = {
#Result(name = "success", location = Location.MAIN_PAGE),
#Result(name = "error", location = Location.LOGIN_PAGE) })
public String modifyServer() {
String id = request.getParameter("sssId");
System.out.println("id serveur = " + id);
return null;
}
private HttpServletRequest request;
#Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
}
If the input element has disabled="disabled" attribute it won't include as parameter when your form is submitted. Also rename the input element name that correspond to a parameter name. Struts2 getter/setter can be used to populate the action bean.
public void setSssId(String id){
this.id = id;
}
I'd suggest checking value of sssId being passed to the action through javascript.
<button onclick='javascript:submitMyForm();' type="button" value="Envoyer" class="btn btn-success"
>Modifier le serveur</button>
write the following javascript
function submitMyForm(){
var sssIdElement = document.getElementById("sssId");
document.form_message.action = "modifyServer.action?sssId="+sssIdElement;
document.form_message.submit();
}