I have a few endpoints under "/rest/role/"whatever"
how do i catch bad requests for example "rest/role/dbbhwbhb/wdwdwed
if i use :
#GET
#Path("/{param}")
#Produces(MediaType.TEXT_PLAIN)
public Response badURLS() {
return Response.ok().entity("bad url").build();
}
this catches rest/roles/dfsdfsds but rest/roles/sdsasd/asdad is still not caught. How do I set up a method so if none of my endpoints are hit then return a default message ?
JBoss approach
https://docs.jboss.org/jbportal/v2.7.0.B1/referenceGuide/html/errorhandling.html
RESTeasy approach
https://docs.jboss.org/resteasy/docs/2.2.0.GA/userguide/html/ExceptionHandling.html
EDIT
As I sent to you before - second link does the trick.
Given the mapper and structure written in such way:
package atata;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
#Provider
public class _404Handler implements ExceptionMapper<NotFoundException> {
public Response toResponse(NotFoundException exception) {
return Response.status(500).entity(new ResponseEntity(333, "Got 404.")).type(MediaType.APPLICATION_JSON).build();
}
}
Config
package atata;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class EmployeeApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
public EmployeeApplication() {
singletons.add(new MessageRestService());
singletons.add(new _404Handler());
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
Pom:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.atata</groupId>
<artifactId>atata</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>atata Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.resteasy/resteasy-jaxrs -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.19.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-servlet-initializer</artifactId>
<version>3.0.4.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>3.0.14.Final</version>
</dependency>
</dependencies>
<build>
<finalName>atata</finalName>
</build>
Endpoint:
package atata;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("/roles")
public class MessageRestService {
#GET
#Path("/1")
#Produces(MediaType.APPLICATION_JSON)
public Response badURLS() {
return Response.ok().entity("OK").build();
}
}
You will get
Related
I am trying to implement Bucket4J rate limiter in Netflix Zuul Api Gateway. I have added Interceptor for Rate Limiting the requests using WebMvcConfigurer.
package com.rajkumar.apiigateway;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.rajkumar.apiigateway.ratelimit.interceptor.RateLimitInterceptor;
#SpringBootApplication
#EnableZuulProxy
public class ApiiGatewayApplication implements WebMvcConfigurer{
#Autowired
#Lazy
RateLimitInterceptor rateLimitInterceptor;
public static void main(String[] args) {
new SpringApplicationBuilder(ApiiGatewayApplication.class)
.run(args);
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(rateLimitInterceptor)
.addPathPatterns("/api/service_1/throttling/users");
}
}
And Interceptor for rate limiting looks like
package com.rajkumar.apiigateway.ratelimit.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import com.rajkumar.apiigateway.ratelimit.service.RateLimitService;
import io.github.bucket4j.Bucket;
import io.github.bucket4j.ConsumptionProbe;
#Component
public class RateLimitInterceptor implements HandlerInterceptor {
private static final String HEADER_API_KEY = "X-API-KEY";
private static final String HEADER_LIMIT_REMAINING = "X-RATE-LIMIT-REMAINING";
private static final String HEADER_RETRY_AFTER = "X-RATE-LIMIT-RETRY-AFTER-SECONDS";
#Autowired
RateLimitService rateLimitService;
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String apiKey = request.getHeader(HEADER_API_KEY);
if(apiKey == null || apiKey.isEmpty()) {
response.sendError(HttpStatus.OK.value(), HEADER_API_KEY+" request header is mandatory");
return false;
}
Bucket tokenBucket = rateLimitService.resolveBucket(request.getHeader(HEADER_API_KEY));
ConsumptionProbe probe = tokenBucket.tryConsumeAndReturnRemaining(1);
if(probe.isConsumed()) {
response.addHeader(HEADER_LIMIT_REMAINING, Long.toString(probe.getRemainingTokens()));
return true;
}
response.addHeader(HEADER_RETRY_AFTER, Long.toString(probe.getNanosToWaitForRefill()/1000000000));
response.sendError(HttpStatus.TOO_MANY_REQUESTS.value(),"You have exceeded your request limit");
return false;
}
}
and other dependent component
package com.rajkumar.apiigateway.ratelimit.service;
import java.util.concurrent.TimeUnit;
import org.springframework.stereotype.Component;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.rajkumar.apiigateway.ratelimit.RateLimit;
import io.github.bucket4j.Bucket;
import io.github.bucket4j.Bucket4j;
#Component
public class RateLimitService {
private LoadingCache<String, Bucket> cache = Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES)
.build(this::newBucket);
public Bucket resolveBucket(String apiKey) {
return cache.get(apiKey);
}
private Bucket newBucket(String apiKey) {
RateLimit plan = RateLimit.resolvePlanFromApiKey(apiKey);
Bucket bucket = Bucket4j.builder()
.addLimit(plan.getLimit())
.build();
return bucket;
}
}
package com.rajkumar.apiigateway.ratelimit;
import java.time.Duration;
import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Refill;
public enum RateLimit {
FREE(2L),
BASIC(4L),
PROFESSIONAL(10L);
private Long tokens;
private RateLimit(Long tokens) {
this.tokens = tokens;
}
public static RateLimit resolvePlanFromApiKey(String apiKey) {
if(apiKey==null || apiKey.isEmpty()) {
return FREE;
}
else if(apiKey.startsWith("BAS-")) {
return BASIC;
}
else if(apiKey.startsWith("PRO-")) {
return PROFESSIONAL;
}
return FREE;
}
public Bandwidth getLimit() {
return Bandwidth.classic(tokens, Refill.intervally(tokens, Duration.ofMinutes(1)));
}
}
and pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.rajkumar</groupId>
<artifactId>apii-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>apii-gateway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<!-- <version>2.5.5</version> -->
</dependency>
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-core</artifactId>
<version>4.10.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
and application.properties
server.port = 8080
spring.application.name = api-gateway
#routing for service 1
zuul.routes.service_1.path = /api/service_1/**
zuul.routes.service_1.url = http://localhost:8081/
#routing for service 2
zuul.routes.service_2.path = /api/service_2/**
zuul.routes.service_2.url = http://localhost:8082/
When I am trying to hit api gateway (http://localhost:8080/api/service_1/throttling/users): it is not passing through the interceptor. Any help is appreciated.
Thanks in advance.
I'm totally new to Resteasy and still learning how it works.
But I cannot work this code out.
I start the tomcat server and it should return fake users information, but somehow gets 404. (No error shown to Eclipse.) I already googled to figure out why this code doesn't work but I couldn't.
To get all users, the URI should be http://localhost:8080/api/v1/users
package com.demo.sprintSample.config;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import org.springframework.context.annotation.Configuration;
#Configuration
#ApplicationPath("/")
public class ResteasyConfig extends Application {
}
package com.demo.sprintSample.resource;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import com.demo.sprintSample.model.User;
import com.demo.sprintSample.service.UserService;
#Component
#Path("/api/v1/users")
public class UserResourceResteasy {
private UserService userService;
#Autowired
public UserResourceResteasy(UserService userService) {
this.userService = userService;
}
#GET
#Produces("application/json")
public List<User> getAllUsers() {
return userService.getAllUsers();
}
#GET
#Path("{userUid}")
#Produces("application/json")
public Response fetchUser(#PathParam("userUid") UUID userUid) {
Optional<User> userOptional = userService.getUser(userUid);
if(userOptional.isPresent()) {
return Response.ok(userOptional.get()).build();
}
return Response.status(Response.Status.NOT_FOUND)
.entity(new ErrorMessage("user"+userUid+"was not found."))
.build();
}
#POST
#Consumes("application/json")
#Produces("application/json")
public Response insertNewUser(#RequestBody User user) {
UUID uid = UUID.randomUUID();
int result = userService.insertUser(user);
return getIntegerResponseEntity(result);
}
#PUT
#Consumes("application/json")
#Produces("application/json")
public Response updateUser(#RequestBody User user) {
int result = userService.updateUser(user);
return getIntegerResponseEntity(result);
}
#DELETE
#Path("{userUid}")
public Response deleteUser(#PathParam("userUid") UUID userUid) {
int result =userService.removeUser(userUid);
return getIntegerResponseEntity(result);
}
private Response getIntegerResponseEntity(int result) {
if(result == 1) {
return Response.ok().build();
}
return Response.status(Response.Status.BAD_REQUEST).build();
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>sprintSample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sprintSample</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<rest.easy.client.version>4.5.6.Final</rest.easy.client.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.21.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.2.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>3.0.2.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId>
<version>3.0.2.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.0.2.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I'm trying to run spring boot with spring data as basically as possible with swing.
However, even though all seems to be properly configured, when I try to run it, I get an error message saying it couldn't find my Service bean.
package db.westworld.dao;
import db.westworld.entities.RobotEntity;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface RobotRepository extends CrudRepository<RobotEntity, Integer> {
}
package db.westworld.service;
import db.westworld.entities.RobotEntity;
import java.util.Optional;
public interface IRobotService {
Optional<RobotEntity> findById(int id);
}
package db.westworld.service;
import db.westworld.dao.RobotRepository;
import db.westworld.entities.RobotEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Optional;
#Service
public class RobotService implements IRobotService {
private final RobotRepository robotRepository;
#Autowired
RobotService(RobotRepository robotRepository) {
this.robotRepository = robotRepository;
}
#Override
public Optional<RobotEntity> findById(int id) {
return robotRepository.findById(id);
}
public void saveRobot(RobotEntity robot) {
robotRepository.save(robot);
}
}
package db.westworld;
import db.westworld.view.RegisterRobot;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import java.awt.*;
#SpringBootApplication
public class WestworldApplication {
public static void main(String[] args) {
var ctx = new SpringApplicationBuilder(RegisterRobot.class).headless(false).run(args);
EventQueue.invokeLater(() -> {
var ex = ctx.getBean(RegisterRobot.class);
ex.setVisible(true);
});
}
}
package db.westworld.view;
import db.westworld.entities.RobotEntity;
import db.westworld.service.RobotService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import javax.swing.*;
import java.awt.event.*;
import java.util.Date;
#Controller
public class RegisterRobot extends JDialog {
private RobotService robotService;
#Autowired
public void setRobotService (RobotService robotService) {
this.robotService = robotService;
}
private void onOK() {
RobotEntity robot = new RobotEntity();
robot.setCreatedAt(new Date());
robot.setId(1);
robotService.saveRobot(robot);
dispose();
}
}
Error message:
Parameter 0 of method setRobotService in db.westworld.view.RegisterRobot required a bean of type 'db.westworld.service.RobotService' that could not be found.
Action:
Consider defining a bean of type 'db.westworld.service.RobotService' in your configuration.
(the JDialog implementation just includes the basics)
The same also happens when I try to autowire the repository.
Also, in case needed, here's my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent> <groupId>db</groupId>
<artifactId>westworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>westworld</name>
<description>westworldSpringBoot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The parameter to new SpringApplicationBuilder() must be the class annotate with #SpringBootApplication, as shown in every Spring Boot example I've ever seen, e.g. Create an Application class in the "Getting Started - Building an Application with Spring Boot" guide.
I made two classes:
Main class with embedded Tomcat(8.5.20)
ServerEndpoint of Websocket
I run the main class on IntelliJ IDEA
and run this JavaScript: new WebSocket('ws://localhost:8080/ws')
in the console of Google Chrome.
I expected the response code is 200, but actually it is 404.
How can I fix this?
Main class:
package webapp;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
import javax.servlet.ServletException;
import java.io.File;
public class Main {
private static final String STATIC_DIR = "src/main/static/";
public static void main(String[] args) throws ServletException, LifecycleException {
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);
File staticDir = new File(STATIC_DIR);
tomcat.addWebapp("/", staticDir.getAbsolutePath());
tomcat.start();
tomcat.getServer().await();
}
}
ServerEndpoint:
package webapp.websocket;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
#ServerEndpoint("/ws")
public class SampleWebSocket {
#OnOpen
public void onOpen(Session session) {
System.out.println("open");
}
#OnClose
public void onClose(Session session) {
System.out.println("close");
}
#OnMessage
public String onMessage(String text) {
System.out.println("message:" + text);
return "Server:" + text;
}
}
Thank you.
I found a solution.
This question is dupricated.
I read Got 404 error on tomcat 7.0.47 websocket and editted my pom.xml.
Following is the whole of my pom.xml.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>websocket-sample</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>websocket-sample</name>
<properties>
<java.version>1.8</java.version>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.source>${java.version}</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>8.5.20</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-websocket</artifactId>
<version>8.5.20</version>
</dependency>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
</project>
Just add the following dependency to pom.xml
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-websocket</artifactId>
<version>8.5.20</version>
</dependency>
What solved the issue for me was switching from the javax.websocket-api dependency to the Tomcat-specific tomcat-embed-websocket dependency instead and switching all my imports (ServerEndpoint, onMessage, etc.) to the Tomcat-specific jakarta.websocket.* packages instead of the javax.websocket.x packages.
Here is the endpoint code that worked for me -- notice that there are no javax.websocket imports and instead I have jakarta.websocket imports:
import java.io.IOException;
import jakarta.websocket.EncodeException;
import jakarta.websocket.OnMessage;
import jakarta.websocket.Session;
import jakarta.websocket.server.ServerEndpoint;
#ServerEndpoint("/echo")
public class EchoEndpoint {
// Implementation.
#OnMessage
public void onMessage(
Session session,
String message)
throws
IOException,
EncodeException {
// Send the same message back.
session.getBasicRemote().sendText(message);
}
}
And my pom.xml file dependencies:
<!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-core -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>10.1.0-M8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-websocket -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>10.1.0-M8</version>
</dependency>
As far as I can tell, the pom.xml should not contain the javax.websocket dependency at all, to ensure there are no collisions/clashes between that one and the Tomcat-specific tomcat-embed-websocket dependency.
it is my first post here, till now I finally always found the solution for my dev problem, but now I am really exchausted. Maybe you can help me.
I am trying to setup simple Rest get web app basing on vaadin + spring boot +
maven on tomcat. In some combinations in .pom i received the get response : "sth else" but in such case the vaadin ui wasnt loaded. In such configuration I paste below I cannot obtain the get response:
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.drzinks</groupId>
<artifactId>site</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>Site</name>
<description>CRUD Vaadin Spring App</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<vaadin.version>7.7.3</vaadin.version>
<vaadin.plugin.version>7.7.3</vaadin.plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<!-- in order to have hot deploy in tomcat -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</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.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-bom</artifactId>
<version>7.7.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
web.xml:
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- Servlet declaration can be omitted in which case
it would be automatically added by Jersey -->
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
WelcomeController.java:
package com.drzinks;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.springframework.stereotype.Component;
#Component
#Path("/sth")
public class WelcomeController {
#GET
#Produces("text/plain")
public String getSthElse(){
return "sth elese";
}
}
SiteApplication:
package com.drzinks;
import javax.ws.rs.ApplicationPath;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SiteApplication {
public static void main(String[] args) {
SpringApplication.run(SiteApplication.class, args);
}
}
SiteUI.java:
package com.drzinks;
import org.springframework.beans.factory.annotation.Autowired;
import com.vaadin.annotations.Theme;
import com.vaadin.server.VaadinRequest;
import com.vaadin.spring.annotation.SpringUI;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
#SpringUI
#Theme("valo")
public class SiteUI extends UI {
#Autowired
private RestClient restClient;
private VerticalLayout layout;
#Override
protected void init(VaadinRequest request) {
setupLayout();
addHeader();
}
private void setupLayout() {
layout = new VerticalLayout(); //alt shift l extr local var
setContent(layout);
}
private void addHeader() {
// Label label1 = new Label(welcomeController.returnSth());
// layout.addComponent(label1);
Label label2 = new Label(restClient.getSthFromServer());
// Label label2 = new Label("restClient.getSthFromServer()");
layout.addComponent(label2);
}
}
RestClient.java:
package com.drzinks;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import org.springframework.stereotype.Component;
import com.vaadin.spring.annotation.UIScope;
#UIScope
#Component
public class RestClient {
private Client client = ClientBuilder.newClient();
private WebTarget webtarget = client.target("http://localhost:8080");
public String getSthFromServer() {
String response;
response = webtarget.path("sth")
.request().get(String.class);
return response;
}
}
folder_structure
If anyone could help, I would be very appreciated as I spent on this more than 12 hrs, breaking all night..