Azkaban Property evaluation - azkaban

We have an Azkaban property in our project that looks something like this date" : "$(new("org.joda.time.DateTime").parse(...).toString("yyyy-MM-dd")) which is used as an argument to a spark job. The command (in the flow log) has the expression already evaluated but the generated Azkaban file (because this is defined in gradle) still contains the code string.
I couldn't find anything about how this works. Googling didn't help. There is no mention of this functionality in the docs (about $(...) params).

If you look at the PropsUtils.java file you can see the method resolveVariableExpression(final String value, final int last, final JexlEngine jexl) actualy evaluates the prop using the JexlEngine.
I think this fucntionality should be added to the docs.

Related

Date not resolving in camel simple expression

New to Camel. I'm trying to get the current DateTime to be a part of a filename. The key bit is here:
.to(s"sftp://$sftpStr/&fileName=MyFile_${date:now:yyyyMMdd}.csv&noop=true")
sftpStr contains the relevant path. But the Date expression throws an error on compilation. I'm sure it's something simple and stupid I'm doing, but it's not clear to me why this doesn't work.
There is a related thing I don't understand, which might help give context to my confusion. I tried this:
.log(LoggingLevel.INFO, LOG.getName, s"Route Started! Time = ${date:now:dd-MM-yyyy HH:mm:ss z}")
which threw an error. But I took away the s tag in the string, and it worked fine. I thought the s just signaled to read the string that follows as a simple expression.
To reiterate, basically just looking to capture the current date/time in a filename (and I can't just create a variable using, say, java.time.LocalDateTime.now() or whatever for reasons too annoying to get into). I included the bit about the log to hopefully contextualize my confusion.
Thanks!
In the statement that you write the problem i believe is $sftpStr. I think that this cannot be resolved.
If $sftpStr is a property then you should use {{$sftpStr}}.
If it is header then you should use ${header.sftpStr}.
I propose to use headers for both folder and file name. Something like:
from(...)
...
.setHeader("folder", constant("the value"))
.setHeader("CamelFileName", simple("${date:now:yyyyMMdd}"))
.to("sftp:username:password#{{ftp.server}}/${header.folder}&noop=true");
In the above ftp.server is a property that holds the SFTP host.
Hope that will help.

Uglifyjs unexpected token name error

Attached is an image of what I am receiving when I try to bundle my project for production. I am receiving a Unexpected token name <<Object>>, expected punc <<,>> message as shown in the image.
Terminal output of error
Not sure what the issue is but I have tried to use uglify-es and uglify-js and get the same error. I even attempted to make a simple app using es6+ code to see if uglify-js worked and it did. So some of the older threads on the internet mentioning that uglify-js won't handle es6+ code might be irrelevant now. I also read somewhere that the newest version (3.x) does support it but haven't been able to confirm that.
I would love to show some code but not sure what relevant piece of code I need to show. As per the image it also mentions the line, col, pos etc... but the code on that line does not start at the col number mentioned.
I will definitely update this post as I investigate but any tips or ideas would be great!
So the issue is now resolved after some thorough research. It looks like the line 1665 I was looking at in my non-optimised bundle app.js was not what I needed to look at (obvious since the column index was way off).
So instead I decided to output the bundle generated code that FuseBox was working on and it was in-fact different. This is the line I added in node_modules/fuse-box/quantum/plugin/BundleWriter.js inside the uglifyBundle function to output the content so I could read it clearly.
fs.writeFile('bundle.txt', bundle.generatedCode);
The output in bundle.txt that was the issue and my actual TypeScript code is shown here:
// bundle.txt line 1665
this.wholesalerSettings = [object Object]
// actual project code
constructor() {
this.wholesalerSettings = process.env.WHOLESALERSETTINGS;
this.API = this.setHostUrl();
}
So I took a look in my fuse.ts file and noticed I was not parsing the json object correctly.
public get wholesalerSettings()
{
const wholesaler = require(`./src/~/wholesalers/${this.wholesaler}/config.json`);
return JSON.stringify(wholesaler);
}
// then down in the environment plugin
EnvPlugin({
WHOLESALERSETTINGS: this.wholesalerSettings,
IMAGE_PATH: this.imagePath
}),
Once I parsed the object correctly with JSON.stringify it worked perfectly as process.env.WHOLESALERSETTINGS was now a JSON string instead of an Object.
First time I really dealt with devops stuff but was fun and at the same time highly stressful. I guess the main thing I learned is when you are dealing with tooling and third party tools (FuseBox uses uglify-js) then you need to take a closer look at the input that is being given to that tool rather than the output like I was at first.
UglifyJS says it sees Object where it's expecting a ,, so we can infer:
The code you wrote (or generated by some other tool right before uglifyJS processes it, e.g. babel? Though you probably don't use babel since your uglifyJS deals with es6 directly) is "Object" where the error occurs.
It's expecting a ,, so the error is occuring at some place like multiple variable declaration, let foo, bar, or object/array definition, [1, 2] {foo: 1, bar: 2}

How to query solr field for a substring

My use case:
I have a single-valued field called cqpath. This is a textfield and has a values that look something like the following:
"/content/domain/en/path/to/some/page"
"/content/domain/en/path/to/another/page"
"/content/domain/en-us/path/to/some/page"
"/content/domain/en-us/path/to/another/page"
I wanted to form a query that would return me 1. and 2. I'd been trying along the lines of writing:
cqpath: "/content/domain/en"
which has been discovered to be erroneous, since it retrieves items 3. and 4. as well. Could any of you think of a way to write a query that returns only 1. and 2. and not 3. and 4.?
This is a normal textfield field-type. Really do appreciate your help.
Starting from Solr 4.0 you can use a regex query. You can find some useful examples here.
In your case, you can get the results that you're looking for using something like:
cqpath:/.*content/domain/en.*/
It looks like you are trying to match partial paths here with boundaries on path elements (slashes). The usual generic solution is to tokenize during index to generate all alternative completions and not tokenize during query. So, the field type declaration is not symmetric. There are examples of that in Solr distribution. And you would look at using something like (index-time only) EdgeNGramFilterFactory instead of much more expensive regex matching.
For your specific case, you may want to look at testPathHierarchyTokenizer which does that for you automatically.
And if your content were more like full URLs than just path, you could also be interested by a custom update request processor chain that includes URLClassify URP. It is not very documented, but mentions generating url parts, which is what I think you would want.

How to use $header in routes

I'm creating a route using the Java DSL in Camel.
I'd like to perform a text substitution without creating a new processor or bean.
I have this:
.setHeader(MY_THING,
constant(my_template.replace("{id1}", simple("${header.subs_val}").getText())))
If I don't add 'constant' I get type mismatch errors. If I don't put getText() on the simple() part, I get text mismatch answers. When I run my route, it replaces {id} with the literal ${header.subs_val} instead of fetching my value from the header. Yet if I take the quotes off, I get compile errors; Java doesn't know the ${...} syntax of course.
Deployment takes a few minutes, so experiments are expensive.
So, how can I just do a simple substitution. Nothing I am finding on the web actually seems to work.
EDIT - what is the template? Specifically, a string (it's a URL)
http://this/that/{id1}/another/thing
I've inherited some code, so I am unable to simply to(...) the URL and apply the special .tof() (??) formatting.
Interesting case!
If you place my_template in a header you could use a nested simple expression(Camel 2.9 onwards) like in the example below. I am also setting a value to subs_val for the example, but I suppose your header has already a value in the route.
.setHeader("my_template", constant("http://this/that/{id1}/another/thing"))
.setHeader("subs_val",constant("22"))
.setHeader("MY_THING",simple("${in.header.my_template.replaceAll(\"\\{id1.?\",${in.header.subs_val.toString()})}"))
After this step header MY_THING has the value http://this/that/22/another/thing.
1)In this example I could skip to_String() but I do not know what's the type of your header "subs_val" .
2) I tried first with replaceAll(\"\{id1\"}\") but it didn't work with } Probably this is a bug...Will look at it again. That's why in my regex I used .?
3) When you debug your application inside a processor, where the exchange is available you can use SimpleBuilder to evaluate a simple expression easily in your IDE, without having to restart your app
SimpleBuilder.simple("${in.header.url.replaceAll(\"\\{id1.?\",${in.header.subs_val.toString()})}").evaluate(exchange, String.class);
Hope it helped :)

Jackrabbit XPath Issue

I'm relatively new to Jackrabbit. In our application we never turned on SearchIndex section within repository.xml (so as workspace.xml) files because we always go directly to a given document using the JCR UUID reference. We are using Jackrabbit v2.2.1 and Oracle as the repository. Now our requirements are getting expanded as we would like to use the document metadata feature to store contextual info about a document so that we can use the metadata to retrieve a selected set of documents.
As the first step, I added the default SearchIndex section in workspace.xml file and restarted the JCR.
I saw a bunch of lines like this in my log file - then I saw it created the index folder under workspace area.
2011-07-05 15:04:01.724 INFO [WebContainer : 0] MultiIndex.java:1204 indexing... /vfs:metaData/21ee130e-978e-415f-bfd1-7aa03d91608c/vfs:attributes (3500)
I have the folder structure like this. When I create a document in JCR, I specify the metadata info as part of the document which is by a complex XSD type with tags like docType, uploadedBy, contextValue, etc.
/ (root)
/MyApp (sub-folder)
/documents/ (sub-folder)
/document-1.pdf (file)
/document-2.pdf (file)
/accounts/ (sub-folder)
/account.txt (file)
etc...
The following XPath expression works.
//jcr:root/vfs:metaData//*[vfs:attributes/vfs:docType='TAX_DOCS']
If I give wrong value, for example instead of 'TAX_DOCS', 'TAX', it returns no documents as expected which is great. This proves that the metadata is correctly stored as expected and it is used in the filter process correctly.
The problem with this query is that it starts searching from the root folder but I want to search from /MyApp/documents sub-folder only. So I tried this:
//jcr:root/MyApp/documents//vfs:metaData//*[vfs:attributes/vfs:docType='TAX_DOCS']
It returns nothing. Then I tried this too but no success.
//jcr:root/MyApp/documents//*[vfs:metaData/vfs:attributes/vfs:docType='TAX_DOCS']
So what am I doing wrong? Is anything in workspace.xml configuration that we need to set or missing?
Any help is appreciated.
Thanks, Jack
Drop the double slashed from anything but the last path component and use the # notation for the attribute value, resulting in:
/jcr:root/MyApp/documents//*[vfs:attributes/#vfs:docType='TAX_DOCS']
The // construct looks for the whole subtree instead of just the immediate children like / does. The JCR specification only requires implementations to support the // construct as the last step of the XPath query.

Resources