Modify default endpoint configuration - apache-camel

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.

Related

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.

Options vs Query Parameters in 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.

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);
})

Get security config in Symfony2?

I'd like to access the security config as it's configured (by default) in security.yml, and in particular actually I need the route name or (even better) generated URL to login. When using FOS User (which I'm using right now) its called "fos_user_security_login" with "/login" URL. I need it to compare with an event's request's (requsted) URL on Kernel's listened events.
I could hardcode this setting check in my Kernel Listener class, like this:
public function onKernelResponse(\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event)
{
if ($originalResponse->headers->has('location')
&& $originalResponse->headers->get('location') === $router->generate('fos_user_security_login', array(), true))
{
//...
}
}
But what if I changed this setting in future to some another one, e.g. to some "/user/login" path with my custom login handler? This is why I'd like to read the security setting for login.
How can I do this in Symfony?
If I were you I would refrain from reading the security settings for this as you can have multiple firewalls with multiple logins and your listener would thus have to listen to all of these (which might not be what you want) or artificially restrict to hardcoded firewalls. Also this will tie your implementation to Symfony's security-component, which you should avoid.
An easily reusable approach would be, to add the URL or route name you want to check for as argument to your listener and pass it via Symfony's Service Container and then just compare request with that value:
class LoginListener
{
/**
* #var string
*/
protected $loginUrl;
/**
* #param string $loginUrl
*/
public function __construct($loginUrl)
{
// You can even fallback to default if you like:
if (empty($loginUrl)) {
$loginUrl = '/login';
}
$this->loginUrl = $loginUrl;
}
// [...] your comparison just against $this->loginUrl
}
You can then use your bundle's configuration to pass the right argument to that listener.
This way you can easily reuse it outside of Symfony e.g. in Silex without being tied to Symfony's Security-component. Also if you want to check against multiple urls, you can just make it an array and specify the different login urls, e.g. when you have multiple login-mechanisms.
edit: In your bundle's Configuration you can check for parameters and define your fallbacks or an error message or whatever (see Getting and Setting Container Parameters).
edit:
in parameters.yml:
custom_login_path: /my_login
in security.yml:
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: security.csrf.token_manager # Use form.csrf_provider instead for Symfony <2.4
login_path: %custom_login_path%
in routing.yml:
fos_user:
resource: "#FOSUserBundle/Resources/config/routing/all.xml"
# Make sure this follows "fos_user" so it takes precendece over the default
fos_user_security_login:
path: %custom_login_path%
defaults: { _controller: FOSUserBundle:Security:login }
in config.yml:
# config for listener in your bundle
my_bundle:
login_path: %custom_login_path%

how to change the url for SolrNet Client

I am a newbie in solrnet and my question is how to change the url for SolrNet Client.
I found this on wiki
initailizing code
Startup.Init<Product>("http://localhost:8983/solr");
invoking code
var solr = ServiceLocator.Current.GetInstance<ISolrOperations<Product>>();
but I dont know how to change the url , could someone tell me how to do this, I am really thanks.
It cannot be changed with existing SOLRNet code as it is implemented on singleton pattern.
You have to download the code from github.
Currently following exception has been thrown
"Key ... already registered in container". You can change code in a way that it will always create new instance. (by pass Singleton pattern)
The default request handler is "/select". So SolrNet will send your requests to
http://localhost:8983/solr/select
If you wish to invoke a different request handler, you will need to get a instance of the SolrQueryExecuter and set the Handler property, accordingly.
Assuming you have a request handler named "/browse":
Startup.Init<Product>("http://localhost:8983/solr");
var executor = ServiceLocator.Current.GetInstance<ISolrQueryExecuter<Product>>() as SolrQueryExecuter<Product>;
if (executor != null)
{
executor.Handler = "/browse";
}

Resources