I need to test different client against each other. for that i need to be able to open different html pages with spring boot.
i tried to do this:
Multiple index.html in spring boot
but it does only return a string "thick_client" on the webpage.
my controller looks like this:
#RestController
public class ApiController {
#Autowired
private StockRepository stockRepository;
#RequestMapping(value = "/", method = RequestMethod.GET)
public String index() {
return "thick_client";
}
#RequestMapping(value = "/anotherIndex", method = RequestMethod.GET)
public String anotherIndex() {
return "thin_client";
}
application.properties:
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.html
My Folder Structure looks like this:
pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
cheers!
Try returning the string without the extension.
For e.g return "thin_client";
Related
I'm facing a problem with Spring boot validation. Currently, I'm using Oracle JDK 11.0.12 and Spring boot 2.5.4 to build my project. I added constraints to validate the fields but it does not work. My code here:
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
#Data
public class LoginFormDTO implements Serializable {
private static final long serialVersionUID = 1L;
#NotBlank(message = "Login must not be blank")
private String login;
#NotNull(message = "Password must be provided")
private String password;
private boolean rememberMe = false;
}
#RestController
#RequestMapping("/api")
public class AccountResource {
// Logger and autowired components
#PostMapping("/authenticate")
#ResponseBody
public ResponseEntity<JWTToken> authorize(#Valid #RequestBody LoginFormDTO account) {
// Some code lines
return ResponseEntity.ok().body(new JWTToken(jwt));
}
}
Dependencies in pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.googlecode.libphonenumber</groupId>
<artifactId>libphonenumber</artifactId>
<version>8.12.31</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
I expect when I send POST request with body
{
"login": null, // or empty string "", or blank string " "
"password": "string",
"rememberMe": true
}
then the server should validate fields then throw exceptions or errors (because of null constraint violation) before executing code in my authorize(#Valid #RequestBody LoginFormDTO account) function, but it does not. So what's wrong with spring validation or am I missing something?
You can simplify your Controller. You have way too many annotations doing the same thing and even some weird stuff (you return ResponseEntity but then you tell Spring that the return of the method should be the Response Body).
This may not fix the #Valid issue but for sure will make it simpler:
#RestController
#RequestMapping("/api")
public class AccountResource {
// Logger and autowired components
#PostMapping("/authenticate")
#ResponseStatus(HttpStatus.OK)
public JWTToken authorize(#Valid #RequestBody LoginFormDTO account) {
// Some code lines
return new JWTToken(jwt);
}
}
#RestController is itself annotated with #Controller and #ResponseBody, which means that #RequestMapping methods assume #ResponseBody semantics by default, so you don't need to explicitly add it.
I found out that my SwaggerConfig class should use BeanValidatorPluginsConfiguration.class instead of SpringValidatorAdapter.class in #Import({}). Now my validator works normally. Thank João Dias for supporting me in figuring it out.
I am creating a rest service and providing json to our consumer.
I have two fields cardType, cardDetails ( i have more fields but these are what relevant).
If cardType is credit card then only I want to send another field cardDetails in json.
If cardtype is something else, Then I don't want to send card details(not even empty data) .
I am not getting how can i achieve solution for this.
Which language do you use?
In spring framework you can do it very easy.
You can add if condition in your controller.
#RestController
public class YourController {
#Autowired
YourRepository yourRepository;
#RequestMapping("/creaditCardsInfo")
public String sendCreditCardToCustomer(#RequestParam(value = "creditCardType", defaultValue = "none") String cardType,#RequestParam(value = "cardDetails", default = "someInfo") String cardDetails) {
if("credit".equals(cardType.trim()) && !(cardDetails.isEmpty())){
return new RequredCreditInfoObject();
}
if you use maven your pom.xml should contain required libs
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JPA Data (if We are going to use Repositories, Hibernate, etc...) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<!-- for JSon marshaling -->
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
Good luck,
I am writing a Java Spring REST server using Spring Boot.
This is the dependency list:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
</dependencies>
This is a part of my a controller class:
#RequestMapping(path = "/", method = RequestMethod.GET)
public GenericResponse<List<Trip>> getUserTrips(Pageable pageable , #RequestParam("owner") String owner) {
List<Trip> trips = tripRepository.findByOwner(owner , pageable);
for (Trip trip : trips) {
Link link = linkTo(methodOn(TripController.class).getTripInfo(trip.getTripId())).withSelfRel();
trip.add(link);
}
return new GenericResponse<List<Trip>>(200, "Success", trips);
}
When compiled, I got the following error:
method getUserTrips in class com... cannot be applied to given types
required org.sptringframework.data.domain.Pageable, java.lang.String
found: java.lang.String
reason: actual and formal argument lists differ in length
I don't understand. I thought Pageable automatically parse the ?page=x&pageSize=y to the pageable var.
Do I forget to add any dependencies? What is wrong?
I do not use WebMv (it's not in my dependency list) Is it why this does not work?
When i return my POJO from RestController it's transforms in JSON object.
But when i try to return new ResponseEntity<>("success", HttpStatus.CREATED);
controller returns plain-text. What's wrong?
My RestController:
#RequestMapping(value = "/register", method = RequestMethod.POST,consumes = "application/json", produces="application/json")
public ResponseEntity<?> registerUser(#RequestBody User user) throws MessagingException {
if(registrationService.canRegister(user.getEmail())){
registrationService.registerUser(user);
logger.info("Registered user "+user.getEmail());
return new ResponseEntity<>("success", HttpStatus.CREATED);
}
return new ResponseEntity<>(HttpStatus.CONFLICT);
}
My dependencies:
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-java8</artifactId>
<version>5.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Spring Boot version 1.4.1
"success" as a String cannot be cast to JSON format. Hence, spring controller returns plain/text.Generally, for any object to be cast as JSON, it must be in the format of a key value pair, so all POJOs can be converted to corresponding key-value pairs where key is the property name and value is property's value. You can have a look at this page to validate what constitutes a valid json.
https://jsonformatter.curiousconcept.com/
Just had the same Problem and found a decent way to solve it:
KeyValuePair value = new KeyValuePair("additionalAdress", user.getAdditionalEmail());
return new ResponseEntity<>(value, HttpStatus.OK);
And on frontend (in my case it's Angular 2 / Typescript) you can get the value the following way:
this.userService.updateAdditionalEmailOfCurrUser(this.additionalEmail).subscribe( (res: any) => {
// handle success case here
this.additionalEmail = res.value;
},
() => {
// handle error case here
});
I have implemented a REST API using Spring Boot (version 1.3.6.RELEASE), which is working as expected. However I would like to add JSON API support to my application.
The problem is that I get a 404 when trying to execute a GET on a Katharsis resource.
The dependencies in pom.xml look as follows (I use Spring Security too):
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
<version>4.4.1</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>${hsqldb.version}</version>
</dependency>
<!--SpringFox dependencies -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-tools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>dumbster</groupId>
<artifactId>dumbster</artifactId>
<version>1.6</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.katharsis</groupId>
<artifactId>katharsis-spring</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.9</version>
</dependency>
</dependencies>
My application initialisation class is as follows:
#SpringBootApplication
#Configuration
#EnableAutoConfiguration(exclude = WebMvcAutoConfiguration.class)
#EnableSwagger2
#ComponentScan(basePackages = "com.myapp")
#Import({KatharsisConfigV2.class})
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
The resource class:
#ApiModel(description = "")
#JsonApiResource(type = "foo-data")
public class FooData extends DomainRepresentation {
#JsonApiId
private String id = null;
#JsonProperty
private String name = null;
// .... getters & setters
}
ResourceRepository class:
#JsonApiResourceRepository(FooData.class)
#Component
public class FooDataKatApi extends MyApi {
#Autowired
private FooDataService fooDataService;
#JsonApiFindOne
public FooData foodataIdGet(String id, QueryParams requestParams) {
FooData result = fooDataService.getFooDataById(id);
return result;
}
}
If I add Spring #ResourceMappings than I get data back but without Katharsis additions like "link", etc. It's as if the API call is not being picked up by Katharsis, but it's handled by Spring.
Any help would be appreciated.
-- EDITTED --
The FooDataService is as follows:
#Service
public class FooDataService extends MyService {
#Autowired
private FooDataRepository fooDataRepository;
public FooData getFooDataById(String id) {
FooDataEnt fooDataEnt = fooDataRepository.findByFooDataId(id);
if (fooDataEnt != null) {
return convertFooDataEntToFooData.apply(fooDataEnt);
}
throw new NotFoundException("Foo not found");
}
}
The FooDataRepository extends Spring's PagingAndSortingRepository.
Katharsis config in application.yaml:
katharsis:
resourcePackage: com.my.package
domainName: http://localhost:8080
pathPrefix: /api/kat
The request and response from PostMan
-- UPDATE 1 --
Apparently the configured value for katharsis.pathPrefix was not correct. Web application's context-root is "/api" and the value of katharsis.pathPrefix should be only "/kat".
My next problem is that a RepositoryNotFoundException is being throw while handling the request, while the Resource class is found already.
I don't see your foo data service implementation anywhere. However, I am 99% sure you're not passing the json api accept type.
Accept: application/vnd.api+json
I solved the riddle by debugging the code and finding out that my Katharsis config was not correct. Katharsis only picked up the resource classes but not the resource repository classes. When I changed the katharsis.resourcePackage to a higher level where the resource repositories resided, the problem got solved and Katharsis picked up all related annotated classes.