apache-camel file2 antInclude ignore-case - file

I need to poll a directory and narrow the files with a case insentive expression.
With version 2.10 camel adds support for antInclude which is what I look into, unfortunately antInclude is case sensitive, so are other filtering expressions. Implementing GenericFileFilter is not an option, since the filtering patterns are not known at compile time as I read them from database at runtime and I have multiple file rules each with a different pattern.
I programmatically create several routes in a loop, where each file route has a different case insensitive filtering pattern. I would appreciate if camel file component supports case insensitive expressions, or is there any other way without creating myself a new file component in camel?
public class MyRouter extends RouteBuilder {
#Override
public void configure() throws Exception {
Vector<FileTransferEntity> list = TransferDAO.getTransferList();
for(FileTransferEntity t : list) {
fromF("ftp://ftpuser#ftpserver/some-directory?antInclude=%s", t.getFileMask()).
toF("mock:result");//depending on t, action will change.
}
}

should be able to use a custom filter instead...see camel-file2 for information or see this example...
https://svn.apache.org/repos/asf/camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileConsumerFileFilterTest.java

Related

State Schema Evolution with POJOs

I'm using flink 1.11 with Scala and i have a question regarding the schema evolution using a POJO.
In the documentation is written, that POJOs are supported for state schema evolution (with some limitations).
Are Scala case clases also considered as POJO and therefore supported?
case class WordCount(word: String, count: Int)
Or have i to write something like this:
class WordCount(var word: String, var count: Int) {
def this() {
this(null, -1)
}
}
Case classes are not POJOs. In particular, they do not satisfy:
The class has a public no-argument constructor
All non-static, non-transient fields in the class (and all superclasses) are either public (and non-final) or have a public getter- and a setter- method that follows the Java beans naming conventions for getters and setters. (afaik case classes have final fields with getters in the generated JVM class)
You can implement all required things in a normal scala class but your IDE might not support you well. An option is to create your class in Java, let your IDE beanify it and convert it to scala (or use it directly).
There is also the option to create evolution support for case classes with a custom serializer. That will eventually be available by Flink. (You could also go ahead and contribute it).

Apache Camel - java DSL - transform body to one of its fields

First, I'm fairly new to Camel so if what (or how) I'm trying to do here is dumb, let me know.
CODE:
from("direct:one")
.to("mock:two")
.process(new Processor(){
#Override
public void process(Exchange exchange)throws Exception{
MyCustomObject obj = exchange.getIn().getBody(MyCustomObject.class);
exchange.getOut().setBody(obj.getOneOfTheFields());
}
})
.to("mock:three");
QUESTION:
This processor transforms an object to one of it's fields. I know that I could replace it with simple expression but that would require me to put 'oneOfTheFields' in a string and I don't want to do that.
Is there a shorter way to do this using java code only?
This can be easily achieved using setBody and Camel simple:
from("direct:one")
.to("mock:two")
.setBody(simple("${body.fieldName}"))
.to("mock:three");
You specify the name of the field, and Camel will use the standard accessor mechanism to set the body appropriately.
Can you not simply do this:
from("direct:one")
.to("mock:two")
.setBody(body().getOneOfTheFields())
.to("mock:three");
Let me know if this works.

Ignore field with annotation for JSON serialization but not for Mongo in MongoJack

Is there any possibility to ignore field for JSON serialization (for web display) but not for mongo (internal serialization) ?
I`ve tried so far all these methods but field was also ignored for Mongo, or not ignored in both in case of some variations
Jackson: how to prevent field serialization
Ok, I finally solved this.
objectMapper.writerWithView(Views.Public.class).writeValueAsString(lo));
writeValueUsingView is from another version of Jackson, so it wasn't working
Custom serialization for web/mongo can be solved by using #JsonView annotations, try along these lines:
class Views {
static class OnAllViews {}
static class OnlySomeViews extends OnAllViews {}
...
}
public class Thing {
#JsonView(Views.OnAllViews.class) Integer id;
#JsonView(Views.OnlySomeViews.class) String name;
}
and then you can call the appropriate level of serialization through writeValueUsingView method.
objectMapper.writeValueUsingView(out, beanInstance, ViewsPublic.class);
You can read more about it here.

solr: read stopword.txt in Custom Handler

I want to read stopword.txt in my custom handler. How to do that ? I know that this is used in Filtering and can be done from there. But I need to read that list in my Custom UpdateRequestProcessorFactory. Also can I read any other custom file created by me.
I was aware that limitation. I overlooked that you are using about update processor.
I looked into the code, here is an existing code you can use as example. SolrCoreAware is the interface you are after.
public class StatelessScriptUpdateProcessorFactory extends UpdateRequestProcessorFactory implements SolrCoreAware
#Override
public void inform(SolrCore core) {
resourceLoader = core.getResourceLoader();
}
Classes that implement org.apache.lucene.analysis.util.ResourceLoaderAware can read files under conf directory. However what it your use case anyway?
looks like xy problem

Camel - extend Java DSL?

I've got a repeating pattern in my routes - a certain Processor needs the same 3 Headers set every time I call it, so I've got the following code in my routes about 10+ times:
.whatever()
.setHeader("foo1", "bar1")
.setHeader("foo2", "bar2")
.setHeader("foo3", "bar3")
.processRef("processorBazThatNeedsHeaders")
.whatever()
The headers are populated differently every time, so abstracting this out into a subroute doesn't really buy me anything.
What I love to be able to do is subclass RouteDefinition to have another method in my DSL that would allow me to do this:
.whatever()
.bazProcessor("bar1", "bar2", "bar3")
.whatever()
and in 'bazProcessor', set the headers and call the processor.
I've tried to do this but it seems that it's only possible with some serious probably-not-future-proof surgery, and it seems that others have had similar luck.
I need them to be set as headers as opposed to passing them as parameters directly to the processor because the values are also used after the processor for routing.
Is there some hidden facility to achieve something like this?
By subclassing the RouteDefinition your extension will only be visible direct after from(...). This could be a limitation if you would like to use the DSL extension for example after the filter(...) DSL.
A simpler approach would be to encapsulate the logic somewhere, and use it in a class that implements the org.apache.camel.Processor interface, and then call an overload of .process(...), or bean(...) in the route to use the logic. You will be actually very closed to a DSL extension if you use a meaningful name for the Processor instance or a method, that returns that Processor instance. Here is an example of the suggested approach. At the end, your code could look like:
.whatever()
.process(setTheHeadersForBaz)
.whatever()
Just for reference: if you really need to do a DSL, there is a project that extends the Camel DSL based on Groovy. I guess a Scala way based on the Camel Scala DSL could be also an option.
Though slightly irrelevant, following is an example of extending Scala DSL.
We can create an implicit methods to DSL trait via an implicit class.
object DSLImplicits {
implicit class RichDSL(val dsl: DSL) {
def get = dsl.setHeader(Exchange.HTTP_METHOD, _ => HttpMethods.GET.name)
def post = dsl.setHeader(Exchange.HTTP_METHOD, _ => HttpMethods.POST.name)
}
}
And use it like this.
import DSLImplicits.RichDSL
//----------------------------
from("someWhere")
//Do some processing
.get.to("http://somewhere.com")
More details #
http://siliconsenthil.in/blog/2013/07/11/apache-camel-with-scala-extending-dsl/
So you only set the headers because you want the Processor to have access to those values?
If so then a simple example using a Factory could look like this:
whatever()
.process(BazProcessorFactory.instance("bar1", "bar2", "bar3"))
.whatever()
Where the BazProcessorFactory is just a wrapper around your Processor:
public class BazProcessorFactory {
public Processor instance(final String...vals) {
return new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
//access your array of values here
System.out.println("Foo1 = "+vals[0]);
}
}
}
}

Resources