How to setup Swagger with Spring Boot Camel for REST messaging - spring-boot

I'm following Swagger Java example, but can't make it work with Spring Boot Camel.
I'm running Spring Boot Camel 3.4.0, and have next dependencies in pom.xml:
<!-- Spring Boot -->
<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>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Camel -->
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-stream-starter</artifactId>
</dependency>
<!-- REST -->
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-rest-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-servlet-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jackson-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jaxb-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-netty-http-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-http-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jetty-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-undertow-starter</artifactId>
</dependency>
<!--<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-rest-swagger-starter</artifactId>
</dependency>-->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-swagger-java</artifactId>
<version>3.4.0</version>
</dependency>
My Router.java is next:
String listenAddress = "192.168.0.100";
int listenPort = 8080;
restConfiguration()
.component("netty-http")
.scheme("http")
.host(listenAddress)
.bindingMode(RestBindingMode.auto)
.dataFormatProperty("prettyPrint", "true")
.port(listenPort)
.contextPath("/")
// add swagger api-doc out of the box
.apiContextPath("/api-doc")
.apiProperty("api.title", "User API").apiProperty("api.version", "1.2.3")
// and enable CORS
.apiProperty("cors", "true");
// this user REST service is json only
rest("/user").description("User rest service")
.consumes("application/json").produces("application/json")
.get("/{id}").description("Find user by id").outType(User.class)
.param().name("id").type(path).description("The id of the user to get").dataType("int").endParam()
.log("Swagger REST header id: ${header.id}");
If trying to GET http://192.168.0.100:8080/api-doc I'm getting 404.
This route above should print log in Camel terminal when using REST GET with http://192.168.0.100:8080/user/123 or am I wrong? Can't see what's missing.

The context path by default is set to /camel/, which means if rest of your configuration is correct, you should be able to see your api-docs at http://192.168.0.100:8080/camel/api-doc
To override it, you need to set the following property in your application.properties file.
camel.component.servlet.mapping.context-path= /*

For me adding the configuration :
In routes
String listenAddress = "localhost";
int listenPort = 8003;
restConfiguration()
.component("servlet")
.scheme("http")
.host(listenAddress)
.bindingMode(RestBindingMode.auto)
.dataFormatProperty("prettyPrint", "true")
.port(listenPort)
.contextPath("/")
// add swagger api-doc out of the box
.apiContextPath("/api-doc")
.apiProperty("api.title", "User API").apiProperty("api.version", "1.2.3")
// and enable CORS
.apiProperty("cors", "true");
In application.properties
server.port=8003
camel.component.servlet.mapping.context-path=/**
URI
http://localhost:8003/api-doc
I am using camel version : 3.9.0
This solution works fine !!!!

Related

SpringBoot Upgrade 2.3.7 to 2.5.4 - Issue with KafkaStreamsAutoConfiguration

These are the Dependencies in the pom.xml. spring-cloud.version is 2020.0.3
<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>
<dependencies>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-streams</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka-streams</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-spring-web</artifactId>
<version>5.6.10</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-kotlin</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-web</artifactId>
</dependency>
...Rest omitted
Application fails to start due to
Description:
Parameter 0 of method kafkaStreamsFunctionProcessorInvoker in org.springframework.cloud.stream.binder.kafka.streams.function.KafkaStreamsFunctionAutoConfiguration required a bean named '&getRestTemplate_registration' that could not be found.
Action:
Consider defining a bean named '&getRestTemplate_registration' in your configuration.
This is the weird part - i do have a Bean defined
/**
* Functional bean which gets / builds the RestTemplate for the given request
* #return the rest template or null if no configuration exists
*/
#Bean
fun getRestTemplate(): (RestCallRequest) -> RestTemplate? {
return { restCallRequest -> getRestTemplateNameForUrl(restCallRequest.url)?.let(::getOrBuildRestTemplate) }
}
and it's being Autowired like shown below in another Class
#Autowired
private lateinit var getRestTemplate: (RestCallRequest) -> RestTemplate?
Works in SpringBoot 2.3.7 but not now after the update. Can anyone please give me a hint how to resolve this.
Why is the Bean getting prefixed with an & and postfixed with _registration? I'm not using that Term in the whole application.
Desperatly i defined a Bean as suggested. Outcome was:
Consider defining a bean named '&getRestTemplate_registration_registration' in your configuration.
After a lot of debugging, the only workaround we were able to find is:
#SpringBootApplication(exclude =[KotlinLambdaToFunctionAutoConfiguration::class])
A Bug report containing a small sample project to reproduce the problem is written: https://github.com/spring-cloud/spring-cloud-function/issues/735.

Spring Boot REST endpoints not working , if add own dependencies in maven file

I developed spring boot application (name as App1) with that app i'm connecting to the MQs( messaging queues ex: IBM MQ), App1 maven dependencies i'm added to the App2 and calling the App1 methods for connecting to the MQ's, but here i'm facing problem whenever add App1 dependencies into App2 then App2 REST endpoints are not working(giving 404 response), could you please help me what might be the problem
Note: if i remove the App1 dependencies in App2 then ,here REST controllers are working
App2 REST Controller Code:
#RestController
#RequestMapping("/accept")
public class RequestController {
#Autowired
private Connector connector;
#PostMapping
public ResponseEntity<String> sendRequestTransactionEvent(#RequestBody TEvent tEvent) {
//System.out.println("Received tEvent) request: " + tEvent)
System.out.println("rquest came to the controller");
connector.sendRequestTransactionEvent(tEvent);
return new ResponseEntity<String>("message successfully sent ", HttpStatus.OK);
}
}
App1 pom.xml file:
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel-version}</version>
</dependency>
<dependency>
<groupId>com.ibm.mq</groupId>
<artifactId>mq-jms-spring-boot-starter</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jms</artifactId>
<version>${camel-version}</version>
</dependency>
</dependencies>
App2 pom.xml file
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.app1</groupId>
<artifactId>Env4x1-Mqjms</artifactId>
<version>1.0</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>
</dependencies>

Spring Boot Google App Engine security annotation?

I'm currently working on a Spring Boot project with Google App Engine & I'm trying to check if my user is logged in on my controller actions thanks to annotations, like #PreAuthorize(isAuthenticated()). This annotation would return a HTTP 403 error if false.
Currently, my users are logged in with the Google App Engine basic UserService & I already tried to use this annotation without success (it does nothing).
Here is my pom file :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.1.3.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.1.3.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud</artifactId>
<version>0.47.0-alpha</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1-2</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>materializecss</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-1.0-sdk</artifactId>
<version>1.9.71</version>
</dependency>
I'm trying to make my code more readable currently I'm doing this on my controller :
private UserService userService = UserServiceFactory.getUserService();
#GetMapping("/pizza/create")
public String createPizza(Model model) {
if (!userService.isUserLoggedIn()) { // used in every actions that need an authentication check
return "error";
}
model.addAttribute("pizza", new Pizza());
return "create";
}
But I'd like to have this :
#PreAuthorize(isAuthenticated())
#GetMapping("/pizza/create")
public String createPizza(Model model) {
model.addAttribute("pizza", new Pizza());
return "create";
}

Maven Module with Spring Boot

I am trying to configure Maven to use Spring Boot with multi modules, this is my structure:
- Parent
------ WebClient
------------ scr/main/java/config ---> Config Files
------------ scr/main/java/resources/WEB-INF ---> Template Files
------ Core
------ Services
------ Server
I have a config file where I put my ViewResolver:
#Configuration
#EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver setupViewResolver() {
// View Resolver
UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
viewResolver.setPrefix("/WEB-INF/");
viewResolver.setSuffix(".jsp");
viewResolver.setViewClass(JstlView.class);
return viewResolver;
}
Here is my parent pom.xml modules and dependencies:
<modules>
<module>core</module>
<module>services</module>
<module>server</module>
<module>webclient</module>
</modules>
<dependencyManagement>
<dependencies>
<!-- =========================== Spring ======================= -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
<!-- Spring Security and MVC dependences -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.1.0.RC1</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.1.0.RC1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>8.5.0</version>
</dependency>
</dependencies>
</dependencyManagement>
At my Server's POM file I have this dependencies:
<dependencies>
<dependency>
<groupId>mygroup</groupId>
<artifactId>core</artifactId>
</dependency>
<dependency>
<groupId>mygroup</groupId>
<artifactId>services</artifactId>
</dependency>
<dependency>
<groupId>mygroup</groupId>
<artifactId>webclient</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
</dependency>
My SpringBootApplication looks like this:
#SpringBootApplication
#ComponentScan({"config"})
public class ServerRunner {
public static void main(String [] args) {
SpringApplication.run(ServerRunner.class, args);
}
}
When I start my application, I see my mapping working and it seems that everything works well but the problem is that Spring does not find my templates:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
There was an unexpected error (type=Not Found, status=404).
/WEB-INF/index.jsp
What is wrong with my config? Where should I put my template files?
Thanks for your help!
EDITED:
If I put my template files at Server Project (server\src\main\webapp) it works! So... How do I make the server to read webclient project templates? I need the templates in that submodule.
EDITED 2:
Solved avoid "jsp" files, see answer and comments
I think this is related to JSP limitations described in Boot reference documentation - you can't just read JSPs from anywhere in the classpath (whereas this works with other templating engines).

jersey skip filtering on specific resource

I have REST API application running in Jetty + Jersey, all the requests will be filtered by some security filter,which is provided some excluded paths defined in config file. With old version Jersey 2.5 the API works fine, now i upgraded Jersey to 2.22.1, the excluded paths are subjected to filtering too and failed because no authentication token were provided.
here is my filter:
#Provider
#Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter extends AbstractAuthenticationFilter implements ContainerRequestFilter, DynamicFeature {
...
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
if (getExcludeUrlPatterns() != null) {
for (String urlPattern : getExcludeUrlPatterns()) {
Pattern p = Pattern.compile(urlPattern);
Matcher m = p.matcher(requestContext.getUriInfo().getPath()); <-- here went wrong
if (m.matches()) {
// skip filtering
}
}
}
// continue filtering.
}
}
here is my resource:
#Path("/version")
public class VersionResource {
...
#GET
#ResponseClass(AppVersion.class)
public Response getVersion() {
AppVersion version =
new AppVersion()
.withBuildPlan(BUILD_PLAN_SETTING)
.withBuildNumber(BUILD_NUMBER_SETTING)
.withBuildTimestamp(BUILD_TIMESTAMP_SETTING)
return Response.ok(version).build();
}
}
Excluded url paths:
/status,/status/?.*,/version,..
as I debugged the code, i noticed for an excluded request context "/myresources/version", requestContext.getUriInfo().getPath() return 'version', however the Pattern is like '/version', thus it doesn't match the pattern and continue the authentication process, and further failed. anyone understand why it works like this?
I use Jersey 2.22.1 and jetty-maven-plugin 9.2.1.v20140609, here is my pom.xml
<jersey.version>2.22.1</jersey.version>
<jetty.version>9.2.1.v20140609</jetty.version>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.connectors</groupId>
<artifactId>jersey-jetty-connector</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.connectors</groupId>
<artifactId>jersey-apache-connector</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${jetty.version}</version>
</dependency>

Resources