Apache Camel routing API call to message queue - rest

I have two applications that talk to each other using a REST API.
I would like to know if I can use Apache Camel as a proxy that could "persist" the API calls, for example storing them as messages in ActiveMQ, and then later route the requests to the actual API endpoint.
Practically, I would like to use Apache Camel to "enhance" the API endpoints adding persistence, throttling of requests, etc...
What component do you suggest to use?

You can always try to bridge your HTTP request into a queue, but making the thread wait by forcing the exchangePattern to InOut.
See this example :
import org.apache.activemq.broker.BrokerService;
import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger logger = LoggerFactory.getLogger(SimpleRouteBuilder.class);
public static void main(String[] args) throws Exception {
org.apache.camel.main.Main main = new org.apache.camel.main.Main();
main.addRouteBuilder(new SimpleRouteBuilder());
logger.info("Next call is blocking, ctrl-c to exit\n");
main.run();
}
}
class SimpleRouteBuilder extends RouteBuilder {
private static final Logger logger = LoggerFactory.getLogger(SimpleRouteBuilder.class);
public void configure() throws Exception {
// launching an activemq in background
final BrokerService broker = new BrokerService();
broker.setBrokerName("activemq");
broker.addConnector("tcp://localhost:61616");
Runnable runnable = () -> {
try {
broker.start();
} catch (Exception e) {
e.printStackTrace();
}
};
runnable.run();
// receiving http request but queuing them
from("jetty:http://127.0.0.1:10000/input")
.log(LoggingLevel.INFO, logger, "received request")
.to("activemq:queue:persist?exchangePattern=InOut"); // InOut has to be forced with JMS
// dequeuing and calling backend
from("activemq:queue:persist")
.log(LoggingLevel.INFO, logger,"requesting to destination")
.removeHeaders("CamelHttp*")
.setHeader("Cache-Control",constant("private, max-age=0,no-store"))
.to("jetty:http://perdu.com?httpMethod=GET");
}
}
If you are using maven, here is the 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>be.jschoreels.camel</groupId>
<artifactId>camel-simple</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>2.19.2</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jms</artifactId>
<version>2.19.2</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jetty</artifactId>
<version>2.19.2</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-camel</artifactId>
<version>5.15.3</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.activemq/activemq-kahadb-store -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-kahadb-store</artifactId>
<version>5.15.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>

Related

RestClient Error javax.ws.rs.WebApplicationException: Unknown error, status code 404

I'm trying to request from a Quarkus's api to Jersey's api, but Jersey API returns a 404 error:
javax.ws.rs.WebApplicationException: Unknown error, status code 404
It looks like quarkus rest client doesn't recognize or can't parse the payload json.
Did you already get something like that?
the payload should be something like that:
{
"code": 404,
"description": "some description....",
"label": "API_ERROR_OBJECT_NOT_FOUND",
"message": "Requested Object not found"
}
The code:
#ApplicationScoped
public class MachineService {
#Inject
#RestClient
ICoreSummaryRest iCoreSummaryRest;
public Boolean transferDatacollector(ObjectNode transferDatacollector) {
try {
String resp = iCoreSummaryRest.updateDataCollectosTransfer
(transferDatacollector.toString());
return Boolean.valueOf(resp);
}catch (Exception e){
return null;
}
}
interface
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
#Path("/")
#RegisterRestClient(configKey="country-api")
#RegisterClientHeaders(CustomHeadersRest.class)
public interface ICoreSummaryRest {
#PUT
#Produces(MediaType.APPLICATION_JSON)
#Path("datacollectors/transfer/")
public String updateDataCollectosTransfer(String transferDatacollectorJSON);
}
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>
<!-- The Basics -->
<parent>
<groupId>com.mycompany</groupId>
<artifactId>my-project</artifactId>
<version>1.0.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>my-project-resource</artifactId>
<version>1.0.0</version>
<dependencies>
<!-- Dependências Gerais Quarkus BOM -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-jackson</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jsonb</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.ws.rs</groupId>
<artifactId>jboss-jaxrs-api_2.1_spec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
<scope>provided</scope>
</dependency>
<!-- <dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-graphql</artifactId>
</dependency> -->
<dependency>
<groupId>org.eclipse.microprofile.rest.client</groupId>
<artifactId>microprofile-rest-client-api</artifactId>
</dependency>
<!-- Dependências do Projeto -->
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>my-project-service</artifactId>
<scope>provided</scope>
</dependency>
<!-- Dependência JTS -->
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
</dependency>
<!-- Dependência mycompany -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
<!-- Build Settings -->
<build>
<plugins>
<plugin>
<groupId>org.jboss.jandex</groupId>
<artifactId>jandex-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
If you want to read the body you can catch the error like this:
try {
String resourceResponse = errorRestClient.getResource();
} catch (WebApplicationException e) {
String respStr = e.getResponse().readEntity(String.class);
LOGGER.error(respStr);
}
Which will print this for the following mockbin at http://mockbin.org/bin/3144eda0-9fa7-4893-90ee-5d624d51bcd2
2022-01-30 17:59:45,851 ERROR [org.acm.arc.ErrorHTTPrestAPI]
(vert.x-eventloop-thread-11) { "description": "some
description....",
"label": "API_ERROR_OBJECT_NOT_FOUND",
"message": "Requested Object not found" }
My interface looks like this
#ApplicationScoped
#Path("/")
#RegisterRestClient(baseUri="http://mockbin.org/bin/3144eda0-9fa7-4893-90ee-5d624d51bcd2")
public interface ErrorRestClient {
#GET
#Path("")
String getResource();
}
If I understood correctly this issue,
when RestClient receives one response different from 2xx it automatically throws this exception.
Perhaps you can disable the ResponseExceptionMapper or create one interceptor to handle this exception.
Below I just quote the answer from this issue
This exception is thrown by the default rest client ResponseExceptionMapper.
You should be able to disable it by adding the following property to application.properties:
microprofile.rest.client.disable.default.mapper=false
See the Default ResponxeExceptionMapper and ResponseExceptionMapper sections of the MicroProfile Rest Client specification.

Why do i get an error cannot find symbol , symbol:class Mongoclient?

I am trying to create new collection in existing database.
try {
MongoCollection collection = null;
MongoClient mongoClient = new MongoClient("127.0.0.1", 27017);
MongoTemplate mongoTemplate = new MongoTemplate(mongoClient, "udata");
collection = mongoTemplate.createCollection("MyNewCollection");
}
catch (Exception e) {
e.printStackTrace();
}
i am using spring boot and importing the following packages:
import com.mongodb.client.MongoClients;
import com.oegems.ems.EmsMongoOps;
import com.mongodb.client.MongoCollection ;
This is 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.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.oegems</groupId>
<artifactId>ems</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ems</name>
<description>Demo project for ..</description>
<properties>
<java.version>11</java.version>
</properties>
<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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Your import contains this:
import com.mongodb.client.MongoClients;
which is a valid class, a factory for MongoClient instances
Mind the extra s in the end
Then, you use:
MongoClient mongoClient
Note that the compiler has recognised MongoCollection from the line above which is the same package as MongoClient
So use one instead of the other:
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;

Rest app (Jersey/JAX-RS) runs in glassfish through eclipse but not when deployed in tomcat

I created a web app using eclipse and (Jersey/JAX-RS). Although when i "run on server" from eclipse in glassfish everything is ok when I deploy the war file I produce either from maven install or from eclipse "export war file" it is deployed succesfully but when i try to access the same rest resources that work in the first option described above, they are not available "404" error.
This is my web.xml file :
<?xml version = "1.0" encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns = "http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id = "WebApp_ID" version = "3.0">
<display-name>Rate it</display-name>
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
<listener>
<listener-class>
com.rateit.util.MyAppServletContextListener
</listener-class>
</listener>
<servlet>
<servlet-name>RateIt login services</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.rateit.login</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>RateIt login services</servlet-name>
<url-pattern>/loginServices/*</url-pattern>
</servlet-mapping>
</web-app>
This is my pom file :
<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>com.gamechangerapps</groupId>
<artifactId>rateit</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>rateit Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.22.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.eclipsesource.minimal-json/minimal-json -->
<dependency>
<groupId>com.eclipsesource.minimal-json</groupId>
<artifactId>minimal-json</artifactId>
<version>0.9.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.2.2</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.19</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
</dependencies>
<build>
<finalName>rateit</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>WebContent\WEB-INF\web.xml</webXml>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
and this is my project structure :
project structure
This is LoginServices class
package com.rateit.login;
import java.io.InputStream;
import java.util.List;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.UriBuilder;
import org.apache.log4j.Logger;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import com.rateit.causecodes.LoginCodes;
import com.rateit.inbox.InboxServices;
import com.rateit.mailing.MailServices;
import com.rateit.property.Building;
import com.rateit.property.PropertyDao;
import com.rateit.rating.RatingQueue;
import com.rateit.util.BaseUriProvider;
import com.rateit.util.FileOperations;
import com.rateit.util.GlobalVariables;
import com.rateit.util.JobIdGenerator;
#Path("/Welcome")
public class LoginServices {
UserDao userDao = UserDao.getInstance();
MailServices mailBot = MailServices.getInstance();
FileOperations fileManager = new FileOperations();
PropertyDao propDao = PropertyDao.getInstance();
InboxServices inServ = new InboxServices();
String baseUri = BaseUriProvider.getStreamInstance().getBaseUri();
static Logger logger = Logger.getLogger(LoginServices.class);
#Context
private ServletContext context;
/**
* Service for Login purposes
*
* #FormParam String user email
* #FormParam String user password
*
* #return LoginCodes LOGIN_SUCCESFUL/LOGIN_FAILURE_INVALID_EMAIL/LOGIN_FAILURE_INVALID_PASSWORD/LOGIN_FAILURE_GENERIC
*
*/
#Path("/login")
#POST
#Consumes("application/x-www-form-urlencoded")
public Response login(#FormParam("email") String e, #FormParam("password") String p) {
ResponseBuilder builder = null;
// get new JobId for this operation
int jobId = JobIdGenerator.getStreamInstance().getJobId();
// Create the user object
User userInput = new User(e,p);
String loginCheck = LoginCodes.LOGIN_FAILURE_GENERIC.getDescription();
User userFromDB = userDao.getUser(userInput.getEmail());
logger.info("JobID="+jobId+" for user with email "+userInput.getEmail()+" this user "+userFromDB.getEmail()+" was found in DB");
// login successful
if(userInput.getEmail().equals(userFromDB.getEmail()) && userInput.getPassword().equals(userFromDB.getPassword())){
loginCheck = LoginCodes.LOGIN_SUCCESFUL.getDescription();
builder = Response.seeOther(UriBuilder.fromUri(baseUri+"/login.html").queryParam("user", userFromDB.getEmail()).queryParam("loginCheck", loginCheck).build());
}
// invalid mail
else if(!userInput.getEmail().equals(userFromDB.getEmail())){
loginCheck = LoginCodes.LOGIN_FAILURE_INVALID_EMAIL.getDescription();
builder = Response.seeOther(UriBuilder.fromUri(baseUri+"/login.html").queryParam("loginCheck", loginCheck).build());
}
// invalid password
else if(userInput.getEmail().equals(userFromDB.getEmail()) && !userInput.getPassword().equals(userFromDB.getPassword())){
loginCheck = LoginCodes.LOGIN_FAILURE_INVALID_PASSWORD.getDescription();
builder = Response.seeOther(UriBuilder.fromUri(baseUri+"/login.html").queryParam("loginCheck", loginCheck).build());
}
// both password and mail invalid
else{
builder = Response.seeOther(UriBuilder.fromUri(baseUri+"/login.html").queryParam("loginCheck", loginCheck).build());
}
logger.info("JobID="+jobId+" Login attempt for user "+e+" "+loginCheck);
return builder.build();
}
The problem is the follwing :
The following test can not hit the rest api
#Test
public void loginUserSuccessTest()
{
// Create a user and add him to the DB
User testUser = new User("testuser#rateit.com","1234");
mockDaoObject.addnewUser(testUser);
// Create a HTTP request
Client client = ClientBuilder.newClient();
//WebTarget target = client.target(baseUri+"/loginServices/Welcome/login");
WebTarget target = client.target("http://localhost:8080/rateit/loginServices/Welcome/login");
target.property(ClientProperties.FOLLOW_REDIRECTS, false);
Builder basicRequest = target.request();
// Create a form with the front end parameters
Form form = new Form();
form.param("email", testUser.getEmail());
form.param("password", testUser.getPassword());
// Send the request and get the response
Response response = basicRequest.post(Entity.form(form), Response.class);
// Delete the user
mockDaoObject.deleteUser(testUser);
// Check that the response is success
boolean correctCause = response.getLocation().toString().contains("loginCheck=User+logged+in+successfully");
boolean correctUser = response.getLocation().toString().contains("user=");
assertEquals(true, correctCause);
assertEquals(true, correctUser);
assertEquals(303, response.getStatus());
}
Any advice will be helpful
After some investigation i found the issue. The problem was that some dependencies were missing and also a configuration in eclipse.
I found the error by checking the logs/localhost.date log in tomcat.
There i found the following exception :
15-Oct-2019 23:04:16.492 INFO [http-nio-8080-exec-42] org.apache.catalina.core.ApplicationContext.log Marking servlet [RateIt login services] as unavailable
15-Oct-2019 23:04:16.493 SEVERE [http-nio-8080-exec-42] org.apache.catalina.core.StandardWrapperValve.invoke Allocate exception for servlet [RateIt login services]
java.lang.ClassNotFoundException: org.glassfish.jersey.servlet.ServletContainer
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1365)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1188)
at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:540)
at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:521)
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:150)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1042)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:761)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:135)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1579)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
Based on this error i fixed the deployment issue with the 3 following steps :
I added the following dependencies in my pom.xml file
org.glassfish.jersey.containers
jersey-container-servlet
2.19
org.glassfish.jersey.core
jersey-server
2.19
I added the maven dependencies in WEB-INF/lib folder through eclipse
MyProject->Properties->Deployment Assembly->Add(Maven Dependencies:source and WEB-INF/lib:Deploy Path
I created the war file through export in eclipse and not through maven task

OSGI : CXF exception with Karaf JAX-RS: No resource methods have been found for resource

I am getting an exception while creating a simple CXF web service with OSGI and Karaf.
Would really appreciate any comments/suggestions for fix.
Here is the description of my project and steps I followed:
Downloaded the Apache Karaf-4.0.7
Run the “mvn clean install” in the command line with the path to my project
Started Karaf console, and run the following commands
feature:repo-add cxf 3.1.8
feature:install cxf/3.1.8
Interface:
public interface MyRestService {
String pingMe(String echo);
}
Implementation:
#Path("/")
public class MyRestServiceImpl implements MyRestService {
#GET
#Path("/{echo}")
#Produces(MediaType.APPLICATION_XML)
public String pingMe(#PathParam("echo") String echo) {
return "Knock Knock: " + echo + " !!";
}
}
OSGI blueprint.xml:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:cxf="http://cxf.apache.org/blueprint/core" xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://www.osgi.org/xmlns/blueprint-ext/v1.1.0 https://svn.apache.org/repos/asf/aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/blueprint-ext.xsd
http://cxf.apache.org/blueprint/jaxws http://cxf.apache.org/schemas/blueprint/jaxws.xsd
http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd
http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd
">
<cxf:bus id=”myBusId”>
<cxf:features>
<cxf:logging></cxf:logging>
</cxf:features>
</cxf:bus>
<jaxrs:server id="myRestService" address="/RestProject/SimpleRestCall">
<jaxrs:serviceBeans>
<ref component-id="myRestImpl" />
</jaxrs:serviceBeans>
</jaxrs:server>
<bean id="myRestImpl" class="com.rest.api.impl.MyRestServiceImpl" />
</blueprint>
Features.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0"
name="restAPI">
<repository>mvn:org.apache.cxf.karaf/apache-cxf/3.1.8/xml/features</repository>
<feature name="test" description="simple test" version="1.0.0-SNAPSHOT">
<details>A Rest server</details>
<!-- CXF and depdendencies -->
<feature version="3.1.8">cxf-jaxrs</feature>
<!-- Jackson and dependencies -->
<bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jsr339-api-2.0/2.6.0</bundle>
<bundle>mvn:com.github.fge/jackson-coreutils/1.8</bundle>
<bundle>mvn:com.fasterxml.jackson.core/jackson-core/2.7.4</bundle>
<bundle>mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/2.7.4</bundle>
<bundle>mvn:com.fasterxml.jackson.core/jackson-annotations/2.7.4</bundle>
<bundle>mvn:com.fasterxml.jackson.core/jackson-databind/2.7.4</bundle>
<bundle>mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/2.7.4</bundle>
<bundle>mvn:com.github.fge/msg-simple/1.1</bundle>
<bundle>mvn:com.google.guava/guava/16.0.1</bundle>
<bundle>mvn:com.github.fge/btf/1.2</bundle>
<bundle>wrap:mvn:com.google.code.findbugs/jsr305/2.0.1</bundle>
<!-- The myRest Server -->
<bundle>mvn:com.rest.ebb.test/myRest/1.0.0-SNAPSHOT</bundle>
</feature>
</features>
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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.rest.ebb.test</groupId>
<artifactId>myRest-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>com.rest.ebb.test</groupId>
<artifactId>myRest</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>MyRestServer</name>
<description>A server for test</description>
<url>.example.com</url>
<properties>
<cxf.version>3.1.8</cxf.version>
<skipTests>true</skipTests>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.4.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Activator>com.ebb.rest.Activator</Bundle-Activator>
<Embed-Dependency>!org.osgi.core,*</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
<Import-Package>
!com.google.protobuf,!com.google.protobuf.*,
!com.jcraft.*,
!com.ning.*,
!groovy.lang,
!javassist,
!lzma.*,
!net.jpountz.*,
!org.apache.*,
!org.bouncycastle.*,
!org.codehaus.*,
!org.eclipse.*,
!org.jboss.*,
!rx,
!sun.security.*,
!net.bytebuddy.*,
!org.HdrHistogram,
!org.slf4j.event,
!org.xerial.*,
!sun.reflect,
!sun.misc,
!sun.util.calendar,
!com.sun.jdi.*,
!jersey.repackaged.com.google.common.*,
!javax.servlet,
*
</Import-Package>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.24</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<version>2.24</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
<type>bundle</type>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-multibindings</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.threeten</groupId>
<artifactId>threetenbp</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
</dependency>
</dependencies>
</project>
Errors:
Am not able to deploy osgi bundles in Karaf, and getting the following errors:
2017-01-06 11:00:39,340 | WARN | pool-9-thread-1 | ResourceUtils | 141 - org.apache.cxf.cxf-rt-frontend-jaxrs - 3.1.8 | No resource methods have been found for reso
class com.rest.api.impl.MyRestServiceImpl
2017-01-06 11:00:39,373 | ERROR | pool-9-thread-1 | AbstractJAXRSFactoryBean | 141 - org.apache.cxf.cxf-rt-frontend-jaxrs - 3.1.8 | No resource classes found
2017-01-06 11:00:39,375 | WARN | pool-9-thread-1 | BeanRecipe | 33 - org.apache.aries.blueprint.core - 1.6.2 | Object to be destroyed is not an instance of Unwra
edBeanHolder, type: null
2017-01-06 11:00:39,385 | ERROR | pool-9-thread-1 | BlueprintContainerImpl | 33 - org.apache.aries.blueprint.core - 1.6.2 | Unable to start blueprint container for bundle mvn:com.abb.ecc.my/myRest/1.0.0-SNAPSHOT
org.osgi.service.blueprint.container.ComponentDefinitionException: Unable to initialize bean myRestService
at org.apache.aries.blueprint.container.BeanRecipe.runBeanProcInit(BeanRecipe.java:738)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BeanRecipe.internalCreate2(BeanRecipe.java:848)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:811)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.di.AbstractRecipe$1.call(AbstractRecipe.java:79)[33:org.apache.aries.blueprint.core:1.6.2]
at java.util.concurrent.FutureTask.run(FutureTask.java:266)[:1.8.0_51]
at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:88)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintRepository.createInstances(BlueprintRepository.java:255)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintRepository.createAll(BlueprintRepository.java:186)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintContainerImpl.instantiateEagerComponents(BlueprintContainerImpl.java:724)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:411)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:276)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:300)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:269)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:265)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BlueprintExtender.modifiedBundle(BlueprintExtender.java:255)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:500)[43:org.apache.aries.util:1.1.1]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:433)[43:org.apache.aries.util:1.1.1]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$AbstractTracked.track(BundleHookBundleTracker.java:725)[43:org.apache.aries.util:1.1.1]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.bundleChanged(BundleHookBundleTracker.java:463)[43:org.apache.aries.util:1.1.1]
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$BundleEventHook.event(BundleHookBundleTracker.java:422)[43:org.apache.aries.util:1.1.1]
at org.apache.felix.framework.util.SecureAction.invokeBundleEventHook(SecureAction.java:1179)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.util.EventDispatcher.createWhitelistFromHooks(EventDispatcher.java:731)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:486)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4541)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.Felix.startBundle(Felix.java:2172)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:984)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.karaf.features.internal.service.FeaturesServiceImpl.startBundle(FeaturesServiceImpl.java:1286)[10:org.apache.karaf.features.core:4.0.7]
at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:846)[10:org.apache.karaf.features.core:4.0.7]
at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1176)[10:org.apache.karaf.features.core:4.0.7]
at org.apache.karaf.features.internal.service.FeaturesServiceImpl$1.call(FeaturesServiceImpl.java:1074)[10:org.apache.karaf.features.core:4.0.7]
at java.util.concurrent.FutureTask.run(FutureTask.java:266)[:1.8.0_51]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)[:1.8.0_51]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)[:1.8.0_51]
at java.lang.Thread.run(Thread.java:745)[:1.8.0_51]
Caused by: org.apache.cxf.service.factory.ServiceConstructionException
at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:219)
at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.init(JAXRSServerFactoryBean.java:142)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.8.0_51]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)[:1.8.0_51]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.8.0_51]
at java.lang.reflect.Method.invoke(Method.java:497)[:1.8.0_51]
at org.apache.aries.blueprint.utils.ReflectionUtils.invoke(ReflectionUtils.java:299)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BeanRecipe.invoke(BeanRecipe.java:980)[33:org.apache.aries.blueprint.core:1.6.2]
at org.apache.aries.blueprint.container.BeanRecipe.runBeanProcInit(BeanRecipe.java:736)[33:org.apache.aries.blueprint.core:1.6.2]
... 34 more
Caused by: org.apache.cxf.service.factory.ServiceConstructionException: No resource classes found
at org.apache.cxf.jaxrs.AbstractJAXRSFactoryBean.checkResources(AbstractJAXRSFactoryBean.java:317)
at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:159)
... 42 more
Try to put the jax-rs annotations on the service interface.
Another possible cause is that the annotation package is not imported. You block a lot of imports in your pom. Can you check without these definitions.
On my side your code works but I had to change the following things:
Remove the cxf:bus from the blueprint
Remove the #Path on the implementation class
Change the import section in the pom.xml
Implementation:
package com.mycompany.testcxf;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
public class MyRestServiceImpl implements MyRestService {
#Override
#GET
#Path("/{echo}")
#Produces(MediaType.APPLICATION_XML)
public String pingMe(#PathParam("echo") String echo) {
return "Knock Knock: " + echo + " !!";
}
}
pom.xml:
<osgi.export.package>{local-packages}</osgi.export.package>
<osgi.import.package>
com.mycompany.testcxf*,
*
</osgi.import.package>
and I only import the dependency:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>2.7.13</version>
</dependency>
Note I cannot test the CXF version 3 as you because my OSGI container is bound to this version. However this setup works perfectly for me, then it could be an issue with the CXF version and some incompatibilities with the embedded http server (Jetty?).
My setup is ServiceMix 5.1.4 with:
Version 2.3.9 of Apache Karaf
Version 2.13.3 of Camel
Version 2.7.13 of CXF

spring boot with java + groovy _maven in embedded tomcat, controller but error

Sorry if this is already answered, I am not able to find it.
I have created new project using spring boot.
My requirements are that I have some java classes, some groovy classes and they should be able to call each others.
I am using maven and running my embedded tomcat by
mvn spring-boot:run
Problem is, RestController which is Java Class is there and I am able to call it REST URL.
But the controller which is in Groovy, is not able to be called and gives me error.
curl localhost:8080/
{"timestamp":1455913384508,"status":404,"error":"Not Found","message":"No message available","path":"/"}
Good part is that I am able to call groovy class from java.
Below are my files.
<?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>org.springframework</groupId>
<artifactId>gs-spring-boot</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.3.7</version>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<!-- 2.8.0-01 and later require maven-compiler-plugin 3.1 or higher -->
<version>3.1</version>
<configuration>
<compilerId>groovy-eclipse-compiler</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-compiler</artifactId>
<version>2.9.1-01</version>
</dependency>
<!-- for 2.8.0-01 and later you must have an explicit dependency on
groovy-eclipse-batch -->
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-batch</artifactId>
<version>2.3.7-01</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
app.groovy:
package hello
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
#RestController
class ThisWillActuallyRun {
#RequestMapping("/home")
String home() {
return "Hello World!"
}
}
Application.java
package hello;
import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
}
}
Controller class
package hello;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
#RestController
public class HelloController {
#RequestMapping("/hello")
public String index() {
ThisWillActuallyRun t = new ThisWillActuallyRun() ;
String v = t.home() ;
System.out.println("value from groovy="+v) ;
return "Greetings from Spring Boot!";
}
}
This works:
curl localhost:8080/hello
Greetings from Spring Boot!
Thanks a lot for the help.
I don't see a problem with your Groovy controller ThisWillActuallyRun
One concern I would have is that you have 2 separate controllers, but did not provide a #RequestMapping(path="controllerpath") at the top of your class on each controller. You did not specify a unique context (relative path) to your controller.
In addition, your curl command only goes to "/". I don't see any mapping for that.
It may work if you curl to "/home", just like you did for "/hello". Regardless, it is a better practice to give a controller level path as well.
An example of how the URL would look if you annotated the #RequestMapping at the top of your 2 controllers might look like:
#RestController
#RequestMapping(path="destination")
class ThisWillActuallyRun {
#RequestMapping("/home")
String home() { }
}
#RestController
#RequestMapping(path="greeting")
public class HelloController {
#RequestMapping("/hello")
public String index() {}
}
Then to reach the 2 endpoints would look like:
http://localhost:8080/destination/home
http://localhost:8080/greeting/hello