Cannot set protocol version on Camel http component URI - apache-camel

To disable HTTP connection persistency I would like to enforce HTTP protocol 1.0 on one of my Apache Camel routes using the http component.
Following Camel's http component documentation I tried to use the following URI:
http://localhost:8888/foo?httpClient.protocolVersion=HTTP/1.0
However, the camel context initialization fails with a ResolveEndpointFailedException with message:
Unknown parameters=[{protocolVersion=HTTP/1.0}]
I assumed that the protocol version parameter is available due to the HttpClientParam documentation. Interestingly, the soTimeout example from the Apache Camel documentation works fine.
I tried both the http and http4 components. I use Apache Camel 2.10.4. The http component has the user agent Jakarta Commons-HttpClient/3.1.
I know that I could also try to use the httpClientConfigurer and/or clientConnectionManager parameters of the http components, but would rather use a solution that does not require custom code.
Thanks in advance for any help!

I came up with the following solution.
On the http-component URL I set a custom httpClientConfigurer:
http://localhost:8080/foo?httpClientConfigurer=myHttpClientConfigurer
where myHttpClientConfigureris a bean with an implementation similar to this:
public class Http10ClientConfigurer implements HttpClientConfigurer {
#Override
public void configureHttpClient(HttpClient httpClient) {
if (httpClient.getParams() != null) {
httpClient.getParams().setVersion(new HttpVersion(1, 0));
} else {
// Could not set HTTP 1.0 version on httpClient
}
}
}

Related

Axios API request from React Native frontend to local spring backend service not working

I develop a React Native mobile app and for the backend I want to use Java Spring.
Now I have a standalone backend server running locally on port 8080 and my react native app is runned via Expo Go app with npm start.
For this question I have built a very simple example.
In the frontend application I want to do a GET request to retrieve a string back from the backend and I am using axios to send API requests.
The problem is that I get a Network Error error whenever I send the GET request to http://localhost:8080/
// dont bother func name
const loginUser = () => {
axios.get("http://localhost:8080/").then(value => {
console.log(value)
}).catch(err => {
console.log("REQUEST FAILED")
console.log(err)
})}
This is the handler when user presses a button axios request is send, Expected output: "Hello World"
output:
REQUEST FAILED
Network Error
at node_modules\axios\lib\core\createError.js:17:22 in createError
at node_modules\axios\lib\adapters\xhr.js:120:6 in handleError
at node_modules\event-target-shim\dist\event-target-shim.js:818:20 in EventTarget.prototype.dispatchEvent
at node_modules\react-native\Libraries\Network\XMLHttpRequest.js:600:10 in setReadyState
at node_modules\react-native\Libraries\Network\XMLHttpRequest.js:395:6 in __didCompleteResponse
at node_modules\react-native\Libraries\vendor\emitter\EventEmitter.js:189:10 in emit
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:416:4 in __callFunction
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:109:6 in __guard$argument_0
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:364:10 in __guard
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:108:4 in callFunctionReturnFlushedQueue
#RestController
//#CrossOrigin(origins = "*")
public class TestController {
#GetMapping("/")
public String hello(){
return "Hello World";
}
}
Simple Spring REST Controller
#SpringBootApplication
public class JpaApplication {
public static void main(String[] args) {
SpringApplication.run(JpaApplication.class, args);
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("GET","POST","PUT","DELETE").allowedHeaders("*").allowedOrigins("*");
}
};
}
}
CORS Config just allowing all
I have tried putting the annotation #CrossOrigin(origins = "*") above the controller but it did not help (seen from: React and Axios : Axios Can't Access Java/SpringBoot REST Backend Service Because of CORS Policy). I have allowed all access from all locations in the CORS config but I get the same output. The example is very simple. I just want to get a simple string back and the solution is probably also very simple but after so many tries I can't come up with a solution. If I visit the URL on the browser I get the expected value, but via axios request it does not seem to work.
After some more searching I found it is not possible to send requests directly to localhost on a Android emulator, on IOS there is no problem. So the problem was after all on the React Native side.
So the fix was relatively easy and also found on stackoverflow, the following thread helped a lot: React Native Android Fetch failing on connection to local API.
I Installed ngrok and this generates a URL which I can use to temporary test my backend till I have hosted it.

Exception in FluentProducerTemplate in Apache Camel after upgrade to 3.7.2

I've the following dependency to 3.7.2:
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-dependencies</artifactId>
<version>3.7.2</version>
I've this in the code:
fluentProducerTemplate.to("direct:myenpoint");
fluentProducerTemplate.send();
This code was working until the upgrade, but now it throws:
java.lang.IllegalArgumentException: No endpoint configured on FluentProducerTemplate. You can configure an endpoint with to(uri)`
Now I'm not able to figure why it's complaining about configuring endpoint as endpoint is clearly set in to(endpoint) call. I couldn't find anything in their documentation.
It's a fluent builder, so you should use it in a style like this:
template.to("xxx").send()
I found that endpoint has to be set at fluentProducerTemplate.setDefaultEndpoint(startingEndpoint);
The error message was misleading. And, I am not sure why to (endpoint) is still there.

Keycloak CORS issue associated with login redirect

Similar questions here and here have not helped me resolve the problem.
I am using Keycloak 4.4.0 to secure my REST service, which is implemented using Spring Boot and I am using React for the front end.
I get a CORS error when the front end (running on localhost:3000) makes an API call to localhost:8080/login and is redirected to the Keycloak login page.
The error is:
localhost/:1 Failed to load http://localhost:8080/login: Redirect from 'http://localhost:8080/login' to 'http://localhost:9080/auth/realms/hbs/protocol/openid-connect/auth?response_type=code&client_id=hbs&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Flogin&state=ab5034a9-4baa-4be3-9ec1-feefbe5f9c0b&login=true&scope=openid' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
I have added a single value of '*' to the Web Origins config section in the Keycloak client.
I have annotated my REST controller as follows:
#RestController
class MyController
{
#CrossOrigin
#GetMapping("/login")
public ResponseEntity<Foo> getFoo(Principal principal)
{
return ResponseEntity.ok(new Foo("blah"));
}
}
I have enabled Keycloak and CORS in the application properties:
keycloak.cors = true
keycloak.enabled = true
If I disable Keycloak and CORS, problem goes away.
As described here, I suspect the issue is to do with the Keycloak server not responding with any Access-Control-Allow-Origin headers despite Web Origins being correctly configured in the Keycloak admin portal. But I'm not completely sure how to confirm this.
Imagine the following json below is your Keycloak configuration:
{
"realm" : "cors",
"resource" : "cors-database-service",
"auth-server-url": "http://localhost-auth:8080/auth",
"bearer-only" : true,
"ssl-required": "external",
"enable-cors": true
}
Try adding the last line to your configuration file.
Let me know if it worked for you!
OBS: I'm facing the same issue, but I'm using Wildfly/JBOSS adapters and making this configuration inside the application server.
#EDIT:
This worked fine for me.
Try changing the "Access Type" to bearer-only inside your REST Client on Keycloak.
Also, don't forget to add the parameter {"{"Authorization" : "bearer " + $TOKEN} when sending HTTP requests from your client to your RESTful API.
For those encountering this error with spring. Just add this class to your project to allow cors:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
public class CorsConfig implements WebMvcConfigurer {
String[] origins = new String[] { "http://localhost:8081"};
#Override
public void addCorsMappings(CorsRegistry registry) {
System.out.println("TEST TEST");
registry.addMapping("/**")
.allowedOrigins("*");
// .allowedOrigins(origins);
}
}
The asterisk allows all origins, which may not be secure for productive systems. A string array can be used to specify more than one origin.

Interceptors and Apache Camel

I am new to camel so my question is how to get request and responce values that is displayed on saop UI to the log file using Interceptors configuration. I need to apply some interceptor configuration before the request hit to camel so that we can filter the request object and same with the responce.
Look at logging interceptors in camel cxf endpoint declaration : inInterceptors
http://camel.apache.org/cxf.html
Or
You can just print the request inside your route as well using ${body}
Add this to your route configuration:
interceptFrom()
.when(exchange -> isToBeIntercepted(exchange)) //which routes are to be intercepted
.process(doSomeStuffHere());

How can I configure the JAX-RS base path in TomEE+?

I have a WAR with some JAX-RS services, deployed into TomEE Plus. Given a service annotated with #Path("myservice"), TomEE+ publishes it to localhost:8080/mywebapp/myservice.
However, that also makes accessing a JSP at localhost:8080/mywebapp/index.jsp impossible - JAXRSInInterceptor complains that No root resource matching request path has been found, Relative Path: /index.jsp.
So I would like to configure a path prefix api to all services, which changes the myservice URL to localhost:8080/mywebapp/api/myservice. Doing so would be trivial if I had configured CXF on my own (with or without Spring), because I could simply change the URL pattern of the CXF Servlet - but I am relying on the default settings where I don't configure anything besides the annotations. So how do I do that in this case?
Note that I don't want to alter the #Path annotations to include the prefix, because that does not fix the issue with the JSP.
Create an extension of javax.ws.rs.core.Application and annotate it with #ApplicationPath where value would be api in your case:
#ApplicationPath("/api")
public class MyApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<Class<?>>();
// register root resource
classes.add(MyServiceResource.class);
return classes;
}
}
This way a Servlet 3 container would find your application and map your resource to /mywebapp/api/myservice while making your web resources (.jsp) available at /mywebapp.
TomEE trunk supports these configurations: cxf.jaxrs.staticSubresourceResolution & cxf.jaxrs.static-resources-list
but the #ApplicationPath is the more relevant solution IMO
Using -Dopenejb.webservice.old-deployment=true can help too in some cases

Resources