Options vs Query Parameters in Apache Camel - apache-camel

Apache camel components page have fields under option and query parameters but no clear path position for parameters , from samples I was able to make out they go along options .
I would like to know the difference between options and query parameters.

When an application with Apache Camel starts, it registers the routes in the Camel Context, and once the context is started, components present in from () and to () cannot be modified, for example:
String param = "a = xxxx & y = bbb";
...
to ("http4: //api.xxx.yy?" + stop)
...
It will only be evaluated at startup, so even if the value of the string in the param variable changes, the route will always use a=xxxx&y=bbb as the default since it has already been initialized in the context of Camel (you can see Camel recording the routes in the logs during application startup).
The options can undergo changes not only in construction, depending on the design of the component in question, but can also be exposed for configuration via starters using application.yml or application.properties or via java as in the example below:
application.properties
camel.component.http.http-configuration=br.com.pack.impl.MyHttpConfiguration
In java
HttpConfiguration config = new HttpConfiguration();
config.setProxyAuthMethod("Digest");
config.setProxyAuthUsername("myUser");
config.setProxyAuthPassword("myPassword");
HttpComponent http = context.getComponent("http", HttpComponent.class);
http.setHttpConfiguration(config);
from("direct:start")
.to("http4://www.google.com/search");
I hope it helped to clarify a little more

Options are used to configure Component and Query Parameters are used while creating endpoints.

Related

404 page not found error when passing getMapping( value="/") and requestParameters

Myapp is java springboot microservice deployed in kubernetes. In local it works fine since I do not need proxy and kubernetes.yml, however when I deploy to int environment, I run into "404 page not found" error.
Please advice if there is any other way to call the service endpoint with this path /api/v1/primary-domain/domain-objects?parameter1=645&parameter2=363&parameter3=2023-02-01
Why is it not able to find the resource? Are there any options to make this work still with same naming pattern for path?
application.properties
server.servlet.context-path=/api/v1/primary-domain/domain-objects management.endpoints.web.base-path=/ management.endpoint.health.show-details=always management.endpoints.web.path-mapping.health=health
#API Registry
springdoc.api-docs.path=/doc
controller:
`#GetMapping(value="", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<DomainObjectsMsResponseDTO>> getDomainObjects(
#RequestParam(name = "parameter1", required = false) String parameter1,
#RequestParam(name = "parameter2", required = false) String parameter2,
#RequestParam(name = "parameter3", required = false) String parameter3,
) throws Exception{..}`
The path variable in proxy is /v1/primary-domain/domain-objects
proxy.yml
.
.
spec: path: /v1/primary-domain/domain-objects target: /api/v1/primary-domain/domain-objects
.
.
Due to the architecture direction the path for health, doc and actual service endpoint should follow certain naming convention, hence running this issue.
If I use proxy.yml path variable v1/primary-domain and getMapping( value="/domain-objects"..) then it works fine but the domain-objects/doc endpoint returns sever array with url: api/v1/primary-domain, which is not what I want. Since under primary-domain multiple microservices will be created which will be in their own gitRepos and they will path like /primary-domain/points and /primary-domain/positions
I tried getMapping( value="/"..) and removing value variable entirely from getMapping, but still getting same error
I tried changing the Label variables, path target and paths in kube and proxy and matched the app.proeprties and controller to go with it. However with every approach one thing gets broken. None of the approach satisfies endpoint, health endpoint, doc endpoint( open api)

How to dynamically return a from endpoint in apache camel DSL

Here is my code
from("google-pubsub:123:subscription1?maxMessagesPerPoll=3 & concurrentConsumers=5" ).routeId("myroute")
.process(new ProducerProcessor())
to("google-pubsub:123:topic1")
;
In my code above ,the from channel I want to make it generic.Basically it should be able to consume data from good-pubsub or may be from a file or from a JMS queue.Hence depending upon a parameter I want to return
a different from channel.Something like below
private RouteDefinition fromChannel(String parameter) {
if (parameter is "google" then
return from("google-pubsub:123:subscription1?maxMessagesPerPoll=3 & concurrentConsumers=5" )
if (parameter is "file" then
return from(/my/fileFolder/)).split(body().tokenize("\n")).streaming().parallelProcessing();
}
I tried this but I am getting null pointer exception in the fromChannel method.Please let me know if you have better ideas.
Rewrite based on comment
You can for example create a (static) template route for every input type and generate the routes based on a configured endpoint list.
I described such an endpoint configuration and route generation scenario in this answer.
Like this you can generate the split part for every file route and any other specialty for other route types.
All these input routes are routing at their end to a common processing route
.from(pubsubEndpoint)
.to("direct:genericProcessingRoute")
.from(fileEndpoint)
.split(body()
.tokenize("\n"))
.streaming()
.parallelProcessing()
.to("direct:genericProcessingRoute")
.from("direct:genericProcessingRoute")
... [generic processing]
.to("google-pubsub:123:topic1")
The multiple input (and output) routes around a common core route is called hexagonal architecture and Camel fits very well into this.

Undertow ResourceHandler to return the same file when a path cannot be found

I am using undertow to statically serve a react single page application. For client side routing to work correctly, I need to return the same index file for routes which do not exist on the server. (For a better explanation of the problem click here.)
It's currently implemented with the following ResourceHandler:
ResourceHandler(resourceManager, { exchange ->
val handler = FileErrorPageHandler({ _: HttpServerExchange -> }, Paths.get(config.publicResourcePath + "/index.html"), arrayOf(OK))
handler.handleRequest(exchange)
}).setDirectoryListingEnabled(false)
It works, but it's hacky. I feel there must be a more elegant way of achieving this?
I could not find what I needed in the undertow documentation and had to play with it to come to a solution. This solution is for an embedded web server since that is what I was seeking. I was trying to do this for an Angular 2+ single page application with routing. This is what I arrived at:
masterPathHandler.addPrefixPath( "/MY_PREFIX_PATH_", myCustomServiceHandler )
.addPrefixPath( "/MY_PREFIX_PATH",
new ResourceHandler( new FileResourceManager( new File( rootDirectory+"/MY_PREFIX_PATH" ), 4096, true, "/" ),
new FileErrorPageHandler( Paths.get( rootDirectory+"/MY_PREFIX_PATH/index.html" ) , StatusCodes.NOT_FOUND ) ) );
Here is what it does:
the 'myCustomServiceHandler' provides the handler for server side logic to process queries sent to the server
the 'ResourceManager/FileResourceManager' delivers the files that are located in the (Angular) root path for the application
The 'FileErrorPageHandler' serves up the 'index.html' page of the application in the event that the query is to a client side route path instead of a real file. It also serves up this file in the event of a bad file request.
Note the underscore '_' after the first 'MY_PREFIX_PATH'. I wanted to have the application API URL the same as the web path, but without extra logic, I settled on the underscore instead.
I check the MIME type for null and serve index.html in such a case as follows:
.setHandler(exchange -> {
ResourceManager manager = new PathResourceManager(Paths.get(args[2]));
Resource resource = manager.getResource(exchange.getRelativePath());
if(null == resource.getContentType(MimeMappings.DEFAULT))
resource = manager.getResource("/index.html");
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, resource.getContentType(MimeMappings.DEFAULT));
resource.serve(exchange.getResponseSender(), exchange, IoCallback.END_EXCHANGE);
})

Modify default endpoint configuration

Example:
to("xslt:mapping.xsl?saxon=true&transformerCacheSize=5")
When I use Saxon, I will set this property all over the place. Having a String constant for them or creating my own xslt endpoint does not seem to be the proper way.
Is there something I can set those properties for all xslt endpoints?
You can configure it by subscribing to the CamelContext's startupListener and setting the XsltEndpoints' parameters (be careful, because the following example does set every XsltEndpoint endpoint's saxon and transformerCacheSize properties). Example (ctx is an instance of CamelContext):
ctx.addStartupListener((ctx, alreadyStarted) -> {
ctx.getEndpoints().forEach(e -> {
if(e instanceof XsltEndpoint) {
((XsltEndpoint) e).setTransformerCacheSize(5);
((XsltEndpoint) e).setSaxon(true);
}
});
});
In case of Spring Boot saxon=true can be configured using the application.properties file (XsltComponentConfiguration). AFAIK the transformerCacheSize cannot be configured from the properties file, because it is a parameter of the XsltEndpoint.
# application.properties
camel.component.xslt.saxon = true
If the configuration is always the same, you can declare a direct endpoint to handle all requests.
from("direct:my-xslt")
.to("xslt:mapping.xsl?saxon=true&transformerCacheSize=5")
And then from your other routes:
.to("direct:my-xslt")
Direct endpoints run in the same thread, so after all its just a way of isolating parts of the route that do a specific job.
As a bonus if you need to do any kind of transformation/log before/after your xslt that apply to all routes, you can simply do it in your direct route.

Make a solr query from Geotools through geoserver

I come here because I am searching (like the title mentionned) to do a query from geotools (through geoserver) to get feature from a solr index.
To be more precise :
I saw on geoserver user manual that i can do query on solr like this in http :
http://localhost:8080/geoserver/wfs?service=WFS&version=1.1.0&request=GetFeature
&typeName=mySolrLayer
&format="xxx"
&viewparams=q:"mySolrQuery"
The important part on this URL is the viewparams that I want to use directly from geotools.
I have already test this case (this is a part of my code):
url = new URL(
"http://localhost:8080/geoserver/wfs?request=GetCapabilities&VERSION=1.1.0";
);
Map<String, String> param = new HashMap();
params.put(WFSDataStoreFactory.URL.key, url);
param.put("viewparams","q:myquery");
Hints hints = new Hints();
hints.put(Hints.VIRTUAL_TABLE_PARAMETERS, viewParams);
query.setHints(hints);
...
featureSource.getFeatures(query);
But here, it seems to doesn't work, the url send to geoserver is a normal "GET FEATURE" request without the viewparams parameter.
I tried this with geotools-12.2 ; geotools-13.2 and geotools-15-SNAPSHOT but I didn't succeed to pass the query, geoserver send me all the feature in my database and doesn't take "viewparams" as a param.
I need to do it like this because actually the query come from another program and I would easily communicate this query to another part of the project...
If someone can help me ?
There doesn't currently seem to be a way to do this in the GeoTool's WFSDatastore implementations as the GetFeature request is constructed from the URL provided by the getCapabilities document. This is as the standard requires but it may be worth making a feature enhancement request to allow clients to override this string (as QGIS does for example) which would let you specify the additional parameter in your base URL which would then be passed to the server as you need.
Unfortunately the WFS module lives in Unsupported land at present so unless you have resources to work on this issue yourself and can provide a PR to implement it there is not a great chance of it being implemented.

Resources