Request method 'GET' not supported There was an unexpected error (type=Method Not Allowed, status=405) - spring-boot

My scenario is as follows:
There are several entities, and I need to send custom designed email for each entity "by Id". For example, I am trying to send the email by this URL for "babs" entity:
http://localhost:8081/api/v1/test/babss/sendmail/b1d0c331-35ac-430d-87ca-1718b06351c3
Sample entity for BaBS:
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*;
import javax.persistence.*;
import java.util.UUID;
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Builder
#Entity
#Table(name = "babs")
public class BaBs {
#Id
#Column(name = "id")
private UUID id;
#Column(name = "accountCode")
private String accountCode;
#Column(name = "accountName")
private String accountName;
#Column(name = "eMail")
private String eMail;
#ManyToOne
#JsonBackReference
#JoinColumn(name = "accountid")
private Account account;
}
email Sending Service
import gokhan.mutabakatcore.models.BaBs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
#Component
public class SentBaBsEmail {
#Autowired
private JavaMailSender sender;
public HttpStatus mailBaBs(BaBs baBs) throws MailException {
SimpleMailMessage mail = new SimpleMailMessage();
mail.setTo(baBs.getEMail());
mail.setSubject("Trial Mail for Sending BaBs");
mail.setText("Normally Details from Object ");
sender.send(mail);
System.out.println("eMail sent");
return HttpStatus.GONE;
}
}
Corresponding part of BaBS Controller
import gokhan.mutabakatcore.models.BaBs;
import gokhan.mutabakatcore.services.BaBsService;
import gokhan.mutabakatcore.utils.SentBaBsEmail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;
#RestController
#RequestMapping("/api/v1/test/babss")
public class BaBsController {
private final BaBsService baBsService;
public BaBsController(BaBsService baBsService) {
this.baBsService = baBsService;
}
#Autowired
SentBaBsEmail baBsEmail;
#RequestMapping(value = "/sendmail/{Id}", method = { RequestMethod.GET, RequestMethod.POST })
public ResponseEntity<?> eMailBaBsByCustomerId(#PathVariable("Id") UUID uuid){
try{
if (!baBsService.findById(uuid).equals(Optional.empty())){
// Converts Optional Object to Normal Object
BaBs baBs = (BaBs) toList(baBsService.findById(uuid));
baBsEmail.mailBaBs(baBs);
return new ResponseEntity(baBs ,HttpStatus.CREATED);
}
return new ResponseEntity<>("Unrecorded BaBS!", HttpStatus.BAD_REQUEST);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
}
Application.properties Mailing part
#SMTP Email Properties
spring.mail.host=mail.xyz.com
spring.mail.port=587
spring.mail.username=info#xyz.com
spring.mail.password=password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.starttls.enable=true
spring.mail.properties.mail.starttls.required=true
Relavant POM.xml dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
The error I got:
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sat Aug 06 08:39:31 EET 2022
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'GET' not supported
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported
I'll appreciate if you can show me the issue...

Related

Validate input inside embedded lists using #DecimalMin and #Valid

So what I am trying to do is to create embedded classes with validation in each class and then get the desired error message when I enter an illegal value. When I have embedded classes, validation suddenly stops working for some reason. I have extracted the core of the problem in the classes below
UserController Class:
// UserController.java
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
#RestController
public class UserController {
public void printUsers(#Valid List<User> users) {
System.out.println(users.get(0).getPeople().get(0).getAge());
}
#GetMapping("/")
public void getUser() {
List<User> users = new ArrayList<>();
Person person = new Person();
person.setAge(-10.0);
person.setFirstName("Test");
person.setLastName("Embedded Validation");
List<Person> persons = new ArrayList<>();
persons.add(person);
User user = new User(persons);
users.add(user);
printUsers(users);
}
}
User Class:
// User.java
package com.example.demo;
import lombok.Builder;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
#Data
#Builder
public class User {
#NotNull
private List<Person> people;
}
Person Class:
// Person.java
package com.example.demo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotNull;
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class Person {
#NotNull
#DecimalMin("0.0")
private double age;
#NotNull
private String firstName;
#NotNull
private String lastName;
}
If you run this it will print -10.0, but I have explicitly told the Person class to have a min DecimalVal of 0.0, so my assignment of person.setAge(-10.0); in the UserController class should not be allowed.
How come validation on embedded classes do not work?

Swagger-UI (v3) with org.springdoc does show and interpret enums incorrectly

I have a problem with my Swagger-UI: It does show Enums as intended.
Instead of a simple representation like CATEGORY1 it shows the full class like CATEGORY1(name=Cat 1) and also uses it in the requests like http://localhost:8080/file/byCategory?category=Category.CATEGORY1%28name%3DCat%201%29
I figured that I can send Requests (e.g. with Postman) with the correct Enum-descriptions and the server would respond, so the api itself works.
The dependencies important for this issue:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-data-rest</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webmvc-core</artifactId>
<version>1.5.0</version>
</dependency>
I also use Spring Boot (2.4.0) and some other dependencies which shouldn't be part of the issue.
My Controller:
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
#Slf4j
#RestController
#RequestMapping("/file")
#CrossOrigin(origins = "http://localhost:4200")
#Tag(name = "Files")
public class GridFSController {
private final GridFsService service;
#Autowired
public GridFSController(GridFsService service) {
this.service = service;
}
#PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
#Operation(summary = "Upload a document")
#ResponseBody
public ResponseEntity<String> upload(#RequestParam("file") MultipartFile file, #RequestParam("category") Category category) {
try {
if (ObjectUtils.isEmpty(file)) {
return ResponseEntity.ok().body("The uploaded file cannot be empty");
} else {
return ResponseEntity.ok().body(service.saveFile(file, category.getName()));
}
} catch (Exception e) {
log.error("[Upload Failed]", e);
return ResponseEntity.badRequest().body(e.getMessage());
}
}
#GetMapping(value = "/download", produces = MediaType.MULTIPART_FORM_DATA_VALUE)
#Operation(summary = "Download a document by its name")
public ResponseEntity<String> download(HttpServletResponse response, #RequestParam("fileName") String fileName) {
try {
service.downLoad(response, fileName);
return ResponseEntity.ok().body("SUCCESS");
} catch (Exception e) {
log.error("[Download Failed]", e.getMessage());
return ResponseEntity.badRequest().body(e.getMessage());
}
}
#GetMapping("/byCategory")
#Operation(summary = "Get information about all documents in a category")
public ResponseEntity<List<FileMetaDomain>> getByCategory(#RequestParam("category") Category category) {
List<FileMetaDomain> allFilesForCategory = service.getAllFilesForCategory(category.getName());
return ResponseEntity.ok(allFilesForCategory);
}
}
My Enum:
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
#ToString
#AllArgsConstructor(access = AccessLevel.PRIVATE)
#Getter
public enum Category {
CATEGORY1("Cat 1"),
CATEGORY2("Cat 2"),
CATEGORY3("Cat 3");
private final String name;
}
My Swagger-UI however looks like this:
As mentioned, it works with Postman (even though at this point the response is just an empty array):
The point is the toString() method overriding. Try to remove the #ToString annotation.
Your Category should be:
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
#AllArgsConstructor(access = AccessLevel.PRIVATE)
#Getter
public enum Category {
CATEGORY1("Cat 1"),
CATEGORY2("Cat 2"),
CATEGORY3("Cat 3");
private final String name;
}
And then the swagger-ui will show the enum values dropdown list:
Update:
If you need to keep the toString() method, you have to enrich the category parameter description on your controller. Your GET /byCategory endpoint code should look like:
#GetMapping("/byCategory")
#Operation(summary = "Get information about all documents in a category")
public ResponseEntity<List<FileMetaDomain>> getByCategory(#Parameter(name = "category", in = ParameterIn.QUERY, schema = #Schema(type = "string", allowableValues = {"CATEGORY1", "CATEGORY2", "CATEGORY3"})) Category category) {
List<FileMetaDomain> allFilesForCategory = service.getAllFilesForCategory(category.getName());
return ResponseEntity.ok(allFilesForCategory);
}

Failed to create query for method public abstract

Simple I want test my application to connect with database to insert
some record statically.
it properly work or not.but it throws this type of error that i
mentioned below;
I donot know where i make mistake,I define everything properly
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'turistRepo': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract com.main.ToursTravels.model.Turist com.main.ToursTravels.repo.TuristRepo.findByName(java.lang.String)! No property name found for type Turist!
turistrepo.java
package com.main.ToursTravels.repo;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.main.ToursTravels.model.Turist;
#Repository
public interface TuristRepo extends CrudRepository<Turist, Long> {
Turist findByName(String turistname);
}
vechiletyperepo.java
package com.main.ToursTravels.repo;
import java.util.List;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.main.ToursTravels.model.Turist;
import com.main.ToursTravels.model.VechileType;
#Repository
public interface VechileTypeRepo extends CrudRepository<VechileType, Long> {
List<VechileType> findByTurist(Turist turist , Sort sort);
}
mainclasss.java
package com.main.ToursTravels;
import java.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.main.ToursTravels.model.Turist;
import com.main.ToursTravels.model.VechileKind;
import com.main.ToursTravels.model.VechileType;
import com.main.ToursTravels.repo.TuristRepo;
import com.main.ToursTravels.repo.VechileTypeRepo;
#SpringBootApplication
public class ToursTravelsApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(ToursTravelsApplication.class, args);
}
#Autowired
TuristRepo trp;
#Autowired
VechileTypeRepo vtrp;
#Override
public void run(String... args) throws Exception {
// TODO Auto-generated method stub
Turist trs = new Turist();
trs.setTuristname("NewsWels");
trs.setTravelkm(100);
trs.setTraveldate(LocalDate.of(2020, 20, 11));
trs.setDrivername("prabhka5r");
VechileType vtp= new VechileType();
vtp.setVechilekind(VechileKind.SEDAN);
vtp.setRateperkm(6);
vtp.setMinprice(2530.00);
trs.setVechileno("GJ05K2619");
trs.setTotalamount(15186.00);
trs.setBookingstatus(true);
trs.setVechiletype(vtp);
vtp.setTurist(trs);
trp.save(trs);
}
}
turist.java
package com.main.ToursTravels.model;
import java.math.BigDecimal;
import java.time.LocalDate;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import lombok.Data;
#Entity
#Table(name="turist")
#Data
public class Turist {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="truist_id")
private Long truistid;
#Column(name="turistname")
private String turistname;
#Column(name="travel_km")
private int travelkm;
#Column(name="travel_date")
private LocalDate traveldate;
#Column(name="drivername")
private String drivername;
#OneToOne(fetch=FetchType.LAZY,cascade=CascadeType.ALL)
#JoinColumn(name="booking_id")
private VechileType vechiletype;
#Column(name="vechileno")
private String vechileno;
#Column(name="total_amount")
private Double totalamount;
#Column(name="BOOKING_status")
private boolean bookingstatus;
public Turist(){}
public Turist(String turistname, int travelkm, LocalDate traveldate, String drivername, VechileType vechiletype,
String vechileno, Double totalamount, boolean bookingstatus) {
super();
this.turistname = turistname;
this.travelkm = travelkm;
this.traveldate = traveldate;
this.drivername = drivername;
this.vechiletype = vechiletype;
this.vechileno = vechileno;
this.totalamount = totalamount;
this.bookingstatus = bookingstatus;
}
}
VechileType.java
package com.main.ToursTravels.model;
import java.math.BigDecimal;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import lombok.Data;
#Entity
#Table(name="vechiletype")
#Data
public class VechileType {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="booking_id")
private Long bookingid;
#OneToOne(fetch=FetchType.LAZY,cascade=CascadeType.ALL,mappedBy="vechiletype")
private Turist turist;
#Enumerated(EnumType.STRING)
#Column(name="vechilekind")
private VechileKind vechilekind;
#Column(name="rate_per_km")
private int rateperkm;
#Column(name="miniprice")
private Double minprice;
public VechileType(){}
public VechileType(Turist turist, VechileKind vechilekind, int rateperkm, Double minprice) {
this.turist = turist;
this.vechilekind = vechilekind;
this.rateperkm = rateperkm;
this.minprice = minprice;
}
}
Your Repository method references a name field for your Turist class, but none exists. You have turistname available to query.
So your method name should be this:
Turist findByTuristname(String turistname);

No instance(s) of type variable(s) T exist so that Flux<T> confirms to Mono<? extend R)

I am implementing Spring webflux demo application and have written my demo application as like that
package com.abcplusd.application;
import com.abcplusd.domain.Event;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import java.util.Collections;
import java.util.Date;
import java.util.stream.Stream;
#SpringBootApplication
public class ReactiveClientApplication {
#Bean WebClient webClient() {
return WebClient.create("http://localhost:8080");
}
#Bean CommandLineRunner demo(WebClient webClient) {
return args -> {
webClient.get()
.uri("/events")
.accept(MediaType.TEXT_EVENT_STREAM)
.exchange()
.flatMap(clientResponse -> clientResponse.bodyToFlux(Event.class))
.subscribe(System.out::println);
};
}
public static void main(String[] args) {
new SpringApplicationBuilder(ReactiveClientApplication.class)
.properties(Collections.singletonMap("server.port", "8081"))
.run(args);
}
}
It shows the following error
Error:(29, 41) java: incompatible types: no instance(s) of type variable(s) T exist so that reactor.core.publisher.Flux<T> conforms to reactor.core.publisher.Mono<? extends R>
The above error is at this line:
.flatMap(clientResponse -> clientResponse.bodyToFlux(Event.class)))
Event Class
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Date;
#Data
#AllArgsConstructor
public class Event {
private long id;
private Date when;
}
Can anybody help me to solve the error?
It works me after i have done these changes in my code
.flatMap(clientResponse -> clientResponse.bodyToFlux(Event.class)))
to
.flatMapMany(clientResponse -> clientResponse.bodyToFlux(Event.class))
and
#NoArgsConstructor annotation in Event.Class
as follows:
import java.util.Date;
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Event {
private long id;
private Date when;
}
flatMapMany instead of flatMap works.
However when you add property spring.main.web_environment=false to application.properties file, webClient simply doesn't work.

Error 415 Web service Rest with Spring

i'm having a problem with my service. I'm trying to send the datas to the database. However, i'm receiving this message:
Error 415
The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.
I'm using Postman to sendo the code below:
Postman
Controller:
package br.com.standard.controller;
import java.util.List;
import br.com.standard.bean.Client;
import br.com.standard.service.ClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class ClientController {
#Autowired
ClientService clientService;
#RequestMapping(value = "/addClient", method = RequestMethod.POST, headers = "Accept=application/json")
public void addClient(#RequestBody Client client) {
clientService.addClient(client);
}
}
Model
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="client")
public class Client {
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
int id;
#Column(name="name")
String nome;
public Client() {
super();
}
public Client(int id, String nome) {
super();
this.id = id;
this.nome = nome;
}
public long getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
I know that it probably is a simple question, but i tried a lot of ways without success.
Thanks in advance.
Two (alternative) solution proposals:
Be sure to send the header: Accept=application/json! (with your client.)
...or change headers = "Accept=application/json" to
consumes = org.springframework.http.MediaType.APPLICATION_JSON (leaving everything else as is)

Resources