tag:blogger.com,1999:blog-84452396175208843122024-03-16T11:52:06.911-07:00Dmitrijs Artjomenko blogDmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.comBlogger169125tag:blogger.com,1999:blog-8445239617520884312.post-81857475151751737482016-08-20T06:06:00.000-07:002017-03-08T06:07:06.570-08:00Converting byte array to string without loosing data<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Recently I had to deal with poor Redis interface, that didn't allowed to store bytes and it was not possible to
update it or change. Redis handles bytes perfectly for keys and data, but there was no way to pass it.
Standard solution for this task is to use Base64, but for my case overhead was too big as I had to store hundreds of
millions of records. UTF is not good too, as it is ruining data. Finally, I found that right encoding for this task is
to use ISO-8859-1 encoding and it works just fine.
<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">
new String([10,20,-30,126] as byte[], "ISO-8859-1").getBytes("ISO-8859-1");
</span></span></pre>
<br />
<br />
<br /></div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com1tag:blogger.com,1999:blog-8445239617520884312.post-31779981668469791752016-07-09T06:04:00.000-07:002017-03-08T06:04:41.236-08:00URL canonicalization and normalization in Java<div dir="ltr" style="text-align: left;" trbidi="on">
Recently I had to implement integration with <a href="https://developers.google.com/safe-browsing/">Google Safe Browsing</a> in Java
and one part of the task is URL normalisation, basically it is like JSoup for URL. You should remove redundant parts, decode, encode, etc.
Seems trivial: even java.net.URI has normalisation, but it really was not trivial,
nothing was working and result was not even remotely compliant.<br />
<br />
After searching and trying everything suggested on Stackoverflow, I finally found working solution - <a href="https://github.com/linkedin/URL-Detector">URL-Detector</a> from Linkedin. Lib itself looks raw
and it is not even in public Maven as of now, but it successfully passes all <a href="https://developers.google.com/safe-browsing/v4/urls-hashing#canonicalization">Google tests</a> after replacing port and using URL without fragment.</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com1tag:blogger.com,1999:blog-8445239617520884312.post-34651124439812553922016-06-25T05:57:00.000-07:002017-03-08T05:57:43.984-08:00Quickly create groovy script in Intellij IDEA<div dir="ltr" style="text-align: left;" trbidi="on">
It is sometimes frustrating when you need quickly check db, non-trivial http, or AWS with Groovy. It is fine and great
if standard lib is enough for your case, but once you need new libraries, it is not that quick. Grab is amazing, but
you need to specify dependency ids and recall exact API and settings. At some point I had a bunch of typical scripts
with typical settings, but you have to be in same project to find them, remember not to commit them, and they tend to
grow big and have their own lives at some point. Bad for hacking and it is not convenient for majority of one-off cases.<br />
<br />
That is where I started using IntelliJ Live Templates:
they are available in every project, easily configurable, you can
dispose or save results as needed, they accessible from regular files, scratches, even Groovy console.<br />
<br />
My typical template consists of everything needed for single use case:
grabs, imports, initialisation and bunch of examples. It is always easier to slash unneeded stuff than recall all API specifics. For me, it is more like tldr output, than what typical default template looks like.<br />
<br />
There is example of one template I use for AWS S3:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">
@Grab('com.amazonaws:aws-java-sdk:1.9.31')
import com.amazonaws.auth.BasicAWSCredentials
import com.amazonaws.services.s3.AmazonS3Client
import com.amazonaws.services.s3.model.ObjectMetadata
def client = new AmazonS3Client(new BasicAWSCredentials('access', 'secret'))
println client.listObjects("bucket", "name").getObjectSummaries().collect{it.key}
def meta = new ObjectMetadata()
meta.setContentType("text/plain")
client.putObject("bucket", "name", new ByteArrayInputStream("1".bytes), meta)
client.deleteObject("bucket", "name")
println new String(client.getObject("bucket", "name").objectContent.bytes)
client.listVersions("bucket", "name").versionSummaries.each {
println "${it.deleteMarker} ${it.key} ${it.size}"
}
client.deleteVersion("bucket", "name", "123")
</span></span></pre>
<br />
And of course, you can have multiple templates preconfigured for different environments and use cases.<br />
<br />
Biggest disadvantages comparing with regular files is that they are stored somewhere deeply in IntelliJ and not easily
transferable, still they are easily exportable with other settings.
Other disadvantage is that content is not searchable, so you have to pack all keywords as abbreviation or description, but
anyway it is not part of universal search.
</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com1tag:blogger.com,1999:blog-8445239617520884312.post-54872941691670120062016-05-07T05:49:00.000-07:002017-03-08T05:50:29.906-08:00Trim is not removing all whitespaces in Java<div dir="ltr" style="text-align: left;" trbidi="on">
Java trim is removing only ASCII whitespace characters, but ignores unicode whitespaces. This is backward compatibility
thing, and there is <a href="http://stackoverflow.com/questions/4304928/unicode-equivalents-for-w-and-b-in-java-regular-expressions">big and detailed explanation</a> of this problem
It can be easily fixed by using regular expression that will remove all official unicode whitespaces:
<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">
Pattern TRIM_PATTERN = Pattern.compile("^\\s*(.*?)\\s*$", Pattern.UNICODE_CHARACTER_CLASS);
Matcher matcher = TRIM_PATTERN.matcher(input);
if (matcher.matches() && matcher.groupCount() > 0) {
return matcher.group(1);
}
return input;
</span></span></pre>
<br />
But for more extreme cases you may want to use also this pattern
<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">"^[\\s\\u2060\\u200D\\u200C\\u200B\\u180E\\uFEFF\\u00AD]*(.*?)[\\s\\u2060\\u200D\\u200C\\u200B\\u180E\\uFEFF\\u00AD]*$"
</span></span></pre>
<br /></div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-28166245232030618462016-04-09T05:27:00.000-07:002017-03-08T05:28:46.517-08:00SSH key forwarding is not working on Mac OS<div dir="ltr" style="text-align: left;" trbidi="on">
If you need to use ssh key forwarding (in git, for example) from Mac - it might not work. This is because Mac is not loading SSH keys automatically.
<br />
It can be easily done manually by calling command:
<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">ssh-add</span></span></pre>
<br />
There is good tutorial about configuration and troubleshooting at <a href="https://developer.github.com/guides/using-ssh-agent-forwarding/">https://developer.github.com/guides/using-ssh-agent-forwarding/</a><br />
<br />
<br />
<br />
<br /></div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-35214053796975330542016-03-05T05:24:00.000-08:002017-03-08T05:24:48.760-08:00XML parsing in Java<div dir="ltr" style="text-align: left;" trbidi="on">
JSON is much popular now, but occasionally it is still possible to come across XML API.
I had such experience recently and I have to say that in 2016 it is much easier than some 10 years ago.
I mostly use Jackson for JSON, so for me best way to use it is <a href="https://github.com/FasterXML/jackson-dataformat-xml">XmlMapper</a> plugin. After that it is plain Jackson.
<br />
There is example:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">
XmlMapper mapper = new XmlMapper();
List rates = mapper.readValue(ratesString, List.class);
</span></span></pre>
<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">
compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.6.3'
compile 'org.codehaus.woodstox:woodstox-core-asl:4.4.1'
</span></span></pre>
<br />
<br />
<br />
<br /></div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com1tag:blogger.com,1999:blog-8445239617520884312.post-56814571062037573742016-02-12T05:17:00.000-08:002017-03-08T05:18:55.221-08:00Using property files with map values in Spring configuration beans<div dir="ltr" style="text-align: left;" trbidi="on">
Spring and Spring Boot can map property files as configuration beans automatically. What is
less known is that it can easily wire Map objects too:
<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">
@Configuration
@Component
@PropertySource("classpath:config.properties")
public class Config {
@Value("#{${my.map}}")
private Map<string string=""> map;
...
</string></span></span></pre>
<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">
my.map={\
'key1' : 'val1', \
'key2' : 'val2', \
...
</span></span></pre>
<br />
<br /></div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com1tag:blogger.com,1999:blog-8445239617520884312.post-76383746236775034002016-01-09T05:04:00.000-08:002017-03-08T05:19:57.439-08:00Selenium style automation script with plain JavaScript in Chrome<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
It is hard to beat Selenium for heavy browser scripting - it has a lot of features, support and infrastructure. But if you only need it occasionally, everything already exists in Chrome.<br />
<br />
For example:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function demo($x) {
$x('//a[@title="Click here first"]')[0].click();
await sleep(2000);
$x('//button[text()=\"Click here then\"]')[0].click();
}
demo($x);
</span></span></pre>
</div>
<br />
It even have advantages over Selenium: you can omit initialisation, like logins and captchas and script only functional parts. Perfect for boring repetitive tasks and adhoc testing.
</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-72053962847926452802015-12-05T23:04:00.000-08:002016-05-22T23:08:16.307-07:00Returning first successful result from CompletableFuture<div dir="ltr" style="text-align: left;" trbidi="on">
Recently I wanted to get first non empty result from bunch of CompletableFutures.
For my case, <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#allOf-java.util.concurrent.CompletableFuture...-">allOf</a> -
is bad because it runs all futures till end and returns nothing.
<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#anyOf-java.util.concurrent.CompletableFuture...-">AnyOf</a> -
is bad because it returns first result, even if it is empty.
So there is no such function in Java API, but it is still very easy to implement, and maybe
it is even more logical, because actually there are 2 cases: found or not found; and it can be easily solved
with two CompletableFutures. There is example:
<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">import java.util.concurrent.CompletableFuture
success = new CompletableFuture<integer>()
def futures = (1..10).collect { CompletableFuture.supplyAsync {
if (val == 6) {
success.complete(val)
} else {
Thread.sleep(1000)
}
}
}
println CompletableFuture.allOf(futures as CompletableFuture[])
.thenApply({ throw new RuntimeException("not found") })
.applyToEither(success, {it}).get()
</integer></span></span></pre>
<br />
This way it will return result if there is any, or throw exception if all done and there is no result, and it can be easily adjusted to return default value, for example.
<br />
<br /></div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-56785260500627005692015-11-28T08:45:00.000-08:002015-12-24T08:53:02.143-08:00Groovy framework for AWS lambda<div dir="ltr" style="text-align: left;" trbidi="on">
I was playing with <a href="http://docs.aws.amazon.com/lambda/latest/dg/welcome.html">AWS lambda</a> recently and I find it pretty exciting. It is cheap, does not require any maintenance and it is simple.
The biggest problem I found so far, is lack of tooling. AWS has web UI which does what it supposed to do, but is far from
pleasant. AWS command line tools and API are much better, but are AWS centric.
So, I have created <a href="https://github.com/dmitart/groovylambda">tool to work with AWS lambda</a>. It uses some convention now, but can be adjusted to
whatever feels right for specific situation, idea is that it is just one script with few lines of code.
Basically, it does 2 things: uploads application and local testing. I have created small example that illustrates how and what it does.<br />
<br />
Example is trivial application that increments number by clicking on button. It is SPA, with static client in S3 and
two API functions add and get.<br />
<br />
All lambda code is just single Groovy script. It consists of router function, dependencies and logic.
Router function is what will be mapped to lambda. It is function that accepts map and returns map.
Input map can be plain request JSON, or some additional parameters can be injected at API gateway.
Even for this trivial case it was a good idea and I injected
configuration parameters - AWS access and secret keys and region for DynamoDB access,
so they are hidden at admin level and are environment specific.
Simplest way to do routing is just by using some designated parameter, in this example, it is called "function". Doing it with
real URI will need AWS configuration, and it is not very convenient and flexible.<br />
<br />
In this simple example, router script does logic, but for more complex cases it is better to be just router and
logic would be in dependencies.<br />
<br />
During packaging Groovy script is compiled and packaged together with all dependencies into uberjar which is
required by AWS. After that, it is uploaded via AWS API.<br />
<br />
Development can be done and tested locally by using mock server. Mock server mimics AWS,
parses input into JSON like lambda, injects parameters like API gateway,
includes Access-Control-Allow-Origin and separates configuration via config.js, supports debug and reloading.<br />
<br /></div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-49765005692344896712015-10-17T07:36:00.000-07:002015-12-24T07:40:18.288-08:00Trim is not removing all whitespaces in Java<div dir="ltr" style="text-align: left;" trbidi="on">
Java trim is removing only ASCII whitespace characters, but ignores unicode whitespaces. This is backward compatibility
thing, and there is <a href="http://stackoverflow.com/questions/4304928/unicode-equivalents-for-w-and-b-in-java-regular-expressions">big and detailed explanation</a> of this problem.
It can be easily fixed by using regular expression that will remove all official unicode whitespaces:
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">Pattern TRIM_PATTERN = Pattern.compile("^\\s*(.*?)\\s*$", Pattern.UNICODE_CHARACTER_CLASS);
Matcher matcher = TRIM_PATTERN.matcher(input);
if (matcher.matches() && matcher.groupCount() > 0) {
return matcher.group(1);
}
return input;</span></span></pre>
<br />
But for more extreme cases you may want to use also this pattern
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">"^[\\s\\u2060\\u200D\\u200C\\u200B\\u180E\\uFEFF\\u00AD]*(.*?)[\\s\\u2060\\u200D\\u200C\\u200B\\u180E\\uFEFF\\u00AD]*$"</span></span></pre>
<br />
besides whitespaces it will also remove other invisible symbols.
</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-27093664802684477322015-09-16T07:33:00.000-07:002015-11-14T07:35:53.352-08:00Using IDE scripting console in Intellij IDEA<div dir="ltr" style="text-align: left;" trbidi="on">
Some time ago, <a href="https://www.jetbrains.com/idea/">Intellij</a> added option to write simple scripts to automate it's functions, extract information and write
simple plugins. It is located under <i>Tools / IDE scripting console</i>. It is very basic now, just scripting file that
runs inside of Intellij JVM and has access to Intellij API.<br />
<br />
There is simple Groovy example that automatically adds non-suspending breakpoint with log expression:
<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.ProjectManager
import com.intellij.xdebugger.breakpoints.SuspendPolicy
def file = LocalFileSystem.getInstance().findFileByPath("/users/test/project/src/Test.java")
def doc = FileDocumentManager.getInstance().getDocument(file)
def bp = ProjectManager.getInstance().getOpenProjects()[0].getComponent("DebuggerManager").getBreakpointManager().addLineBreakpoint(doc, 11)
bp.getXBreakpoint().setLogExpression('"test"')
bp.getXBreakpoint().setSuspendPolicy(SuspendPolicy.NONE)
</span></span></pre>
<br />
Of course, this basic task can be done through XML configuration, but IDE scripting has access to much more and can do
trickier tasks. There is very cool <a href="https://gist.github.com/gregsh/b7ef2e4ebbc4c4c11ee9">demo</a>. Generally, from what I have seen, API is pretty impressive, it is intuitive, powerful and easy to start with.<br />
<br />
My biggest complains are that it is pretty verbose (as Java itself), it would be great if in future versions it would be
solved at least at tooling levels - with auto imports for packages, autocompletion, and more convenience functions, like attaching to
actions, getting projects or files quickly.
Second problem is total lack of documentation. Basically, what I have found is only <a href="https://github.com/JetBrains/intellij-community">GitHub repo of Intellij community edition</a>.
It has multiple modules with API scattered across them, most generic classes are under <a href="https://github.com/JetBrains/intellij-community/tree/210e0ed138627926e10094bb9c76026319cec178/platform/core-api">Core API</a>.</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com13tag:blogger.com,1999:blog-8445239617520884312.post-83460923756009234452015-08-14T07:20:00.000-07:002015-11-14T07:23:11.267-08:00Adding custom hostname to docker-machine VirtualBox image<div dir="ltr" style="text-align: left;" trbidi="on">
When boot2docker was changed to <a href="https://www.docker.com/docker-machine">docker-machine</a>, it added dubious feature of being read only container, so no
changes to VirtualBox will be preserved after restart. Saving changes is still perfectly fine for Linux Docker users, but
not docker-machine users anymore for some reason.<br />
<br />
So, to add new hostname before, you could just go to VirtualBox, change <i>/etc/hosts</i> file, and this is it - this will
not work with docker-machine, as hosts file will be erased after restart.
You are luckier, if you are not using <i>net:host</i> in docker-compose, there is special property for that too.
But, if you are using <i>net:host</i>, the only working option is to change VirtualBox image and add this configuration:
<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">VBoxManage modifyvm "default" --natdnshostresolver1 on
</span></span></pre>
<br />
In this case it will use host machine to resolve all dns requests, even those from <i>/etc/hosts</i>.
</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-30925745927811395132015-07-23T10:46:00.000-07:002015-11-14T07:13:59.422-08:00How to add configuration parameters to AWS lambda with API gateway<div dir="ltr" style="text-align: left;" trbidi="on">
Unfortunately, there is no easy way to add configuration parameters to <a href="https://aws.amazon.com/lambda/">AWS lambdas</a>, there is almost nothing in <a href="https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/Context.java">context</a>
that you can configure;
there is description, but besides being ambiguous, it is not accessible from function itself.
Fortunately, it is possible to set additional values from <a href="https://aws.amazon.com/api-gateway/">API gateway</a>, even it is not straightforward.<br />
<br />
When you have created API gateway mapping, go to the method screen in gateway console, there is screen with
multiple boxes, one of which is called <i>Integration Request</i>, click it and there will be section called <i>Mapping Templates</i>.
Add new mapping template for type <i>application/x-www-form-urlencoded</i>, save it, edit value and change from default <i>Input passthrough</i> to <i>Mapping template</i>, then you can transform your original request, by adding additional
parameters, it uses <a href="http://docs.aws.amazon.com/apigateway/latest/developerguide/models-mappings.html#models-mappings-mappings">velocity for transformation</a>,
but there is basic example:
<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">
{
"my-new-configuration" : "my value",
"body" : "$input.path('$')",
"params" : "$input.params()",
"ip" : "$context.identity.sourceIp",
"user-agent" : "$context.identity.userAgent"
}
</span></span></pre>
<br />
Besides possibility to add anything to lambda function it also has access to
interesting request data like headers, ip, client type, user agent, country, etc. - all will be available in your map or
pojo as parameter for lambda function.
And do not forget to click <i>Deploy API</i> after making changes to make them live.
</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-44810861773716704922015-06-25T14:01:00.000-07:002015-11-14T07:06:28.112-08:00How to create executable JAR from single Groovy script<div dir="ltr" style="text-align: left;" trbidi="on">
Groovy scripts are nice - they allow to use dependencies and write logic in small single file,
but Groovy is mostly available on developers machine, but not on servers, so deploying them is a little more
tricky. You can package them in uberjar with Gradle, but it requires additional build file and compatible structure, so
it is more like project than script already.<br />
<br />
To keep things simple, I have created <a href="https://github.com/dmitart/scriptjar">Groovy script that converts other Groovy scripts into executable JARs</a>.
It packages all dependencies from Grab and compiles original script into Java main class with same name as script and sets it in manifest.
So it is perfectly usable from empty JVM.
JAR structure is also compatible with <a href="https://aws.amazon.com/lambda/">AWS lambda</a>, so it can be launched from there too, just put logic in specific method.
To convert your script, just download it from <a href="https://github.com/dmitart/scriptjar">here</a> and run like:
<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: "andale mono" , "lucida console" , "monaco" , "fixed" , monospace;"><span style="font-size: 12px; line-height: 14px;">./scriptjar.groovy input.groovy output.jar</span></span><span style="font-family: "times new roman";"><span style="white-space: normal;">
</span></span></pre>
<br />
Script tries to find groovy libs via GROOVY_HOME, so set it or just hack it for your location, it is just one small Groovy script.
</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com10tag:blogger.com,1999:blog-8445239617520884312.post-37777093452054627732015-05-15T09:34:00.002-07:002015-05-15T09:35:56.640-07:00Erlang connection from boot2docker<div dir="ltr" style="text-align: left;" trbidi="on">
If you need to connect from outside of <a href="http://www.docker.com/">Docker</a> into boot2docker instance on MacOS, but nothing happens:
First, make sure that all ports are mapped in VirtualBox instance - at minimum it requires 4369 and 20000-20999. Then, for hidden nodes, you may need to ping them explicitly, like:
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;"><span style="font-size: 12px; line-height: 14px;">net_adm:ping('server@127.0.0.1').</span></span><span style="font-family: Times New Roman;"><span style="white-space: normal;">
</span></span></pre>
</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-67875575679326775032015-04-09T13:33:00.000-07:002015-04-09T13:33:44.951-07:00Using Clojure dependencies without specifying version number<div dir="ltr" style="text-align: left;" trbidi="on">
Clojure has mandatory version number for dependecies, so until you are a real fan of the library, you may need to look it up somewhere.
Fortunately, it is possible to specify LATEST instead of version, like:
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;"><span style="font-size: 12px; line-height: 14px;">(leiningen.exec/deps '[[http-kit "LATEST"]])
...</span></span><span style="font-family: Times New Roman;"><span style="white-space: normal;">
</span></span></pre>
</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-16920415592727898882015-04-09T13:26:00.000-07:002015-04-09T13:30:11.494-07:00Clojure command line script with dependencies<div dir="ltr" style="text-align: left;" trbidi="on">
If you want to use Clojure for command line scripts, the easiest way is by using <a href="https://github.com/kumarshantanu/lein-exec">lein-exec plugin</a>. It compiles clj files on the fly and downloads all necessary dependencies that are
declared in same file, similarly to Groovy <a href="http://docs.groovy-lang.org/latest/html/documentation/grape.html">@Grab annotation</a>.<br />
<br />
For example, if you have file named download.clj with<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;"><span style="font-size: 12px; line-height: 14px;">(leiningen.exec/deps '[[http-kit "2.1.16"]])
(require '[org.httpkit.client :as http])
(prn (:body @(http/get "http://www.google.com")))
</span></span><span style="font-family: Times New Roman;"><span style="white-space: normal;">
</span></span></pre>
it is possible to run it by:<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;"><span style="font-size: 12px; line-height: 14px;">lein exec download.clj
</span></span><span style="font-family: Times New Roman;"><span style="white-space: normal;">
</span></span></pre>
</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com1tag:blogger.com,1999:blog-8445239617520884312.post-62161716295862024262015-04-05T02:23:00.000-07:002015-04-05T02:26:12.283-07:00My recipe for IntelliJ IDEA distraction free mode<div dir="ltr" style="text-align: left;" trbidi="on">
One of the top features in <a href="http://blog.jetbrains.com/idea/2015/03/intellij-idea-14-1-is-here/">IntelliJ IDEA 14.1</a> is distraction free mode. I am totally in love with it and not looking back, working 100% of time in it. Biggest concern about it is: loosing tabs. I was happy with tabs before, but it looks like there is a bunch of better options:<br />
<br />
<ul style="text-align: left;">
<li><i>Recent Files </i>(Cmd + E) - basically dropdown with tabs, but you can also do text search in it.</li>
<li><i>Switcher</i> (Ctrl + Tab) - same as <i>Recent Files</i>, but opens file once shortcut is released. A little faster, but you are loosing search. This is the closest to original tabs.</li>
<li><i>Search Everywhere </i>(Shift + Shift) - acts as <i>Recent Files</i>, but if you type something - also does search for <i>Classes</i>, <i>Files</i>, <i>Symbols</i>, <i>Actions</i>, <i>Preferences</i>. So together with tabs it basically replaces also Cmd + E, Cmd + O, Shift + Cmd + O, Alt + Cmd + O, Shift + Cmd + A.</li>
</ul>
<br />
I chose <i>Search Everywhere</i> as it is most feature rich and is really awesome. I also remapped it to Ctrl + E as it includes <i>Recent Files</i>, but as shortcut Ctrl + E works faster and is easier to reach.<br />
<br />
Tabs had another aspect - tabs pinning, I didn't used it a lot, but for occasional use, bookmarks replace them nicely and provide more features as can pin specific line together with file. So use F3 to bookmark and Cmd + F3 to list bookmarks.<br />
<br />
Everything else: like splitting, navigation bar, file path, tool windows, etc. is easy accessible via shortcuts or <i>Find Action...</i> (Shift + Cmd + A) if you forgot shortcut.<br />
<div>
<br /></div>
</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-14354614104000306572015-03-04T15:58:00.000-08:002015-03-04T15:58:20.561-08:00Changing SSH port for dynamic inventory script in Ansible<div dir="ltr" style="text-align: left;" trbidi="on">
If you have to write dynamic inventory script in Ansible, but need to use SSH port which is not 22, there is example output of the script output:<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;"><span style="font-size: 12px; line-height: 14px;">
{"databases":{
"hosts":["127.0.0.1"],
"vars":{
"ansible_ssh_port":2222
}
}
}
</span></span><span style="font-family: Times New Roman;"><span style="white-space: normal;">
</span></span></pre>
<br /></div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com1tag:blogger.com,1999:blog-8445239617520884312.post-78944446561163665202015-02-21T13:12:00.000-08:002015-04-04T13:15:39.517-07:00Ansible freezes during start<div dir="ltr" style="text-align: left;" trbidi="on">
If Ansible stops for several minutes or so during start without any messages, check if it calls your inventory
script, because it might query for additional options using <i>--host</i> parameter and if there are a lot of hosts, it may
take some time.<br />
<br />
It can be easily fixed by adding this to JSON root:<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;"><span style="font-size: 12px; line-height: 14px;">
"_meta" : {
"hostvars" : {
}
}
</span></span><span style="font-family: Times New Roman;"><span style="white-space: normal;">
</span></span></pre>
More about it <a href="http://docs.ansible.com/developing_inventory.html#tuning-the-external-inventory-script">here</a>.</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-10794858864677251032015-02-11T14:19:00.000-08:002015-04-27T14:20:45.788-07:00My Everyday Carry<div dir="ltr" style="text-align: left;" trbidi="on">
This will be rare post not about IT. So, apart from programming, my other obsession is <a href="http://en.wikipedia.org/wiki/Everyday_carry">EDC</a>, if not familiar: very good intro is <a href="http://everydaycarry.com/posts/5827/What-Is-EDC-The-Beginnerand039s-Guide-to-Everyday-Carry">here</a>.<br />
<br />
<h2 style="text-align: left;">
Current setup: phone + keys</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQJc7udQL35D5Jx_G8WVnxXR3raDkJrBmCfO-bZ95S9rXhJvI-4u07PgKqudASgkYTK1bbzaONBkJqor4ipMCPaZUBxJg4WK6eSl9aKtAhrB16b5R8oLvMrRT9kY4uX_3XNiBhlvmni__Z/s1600/P4035750.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQJc7udQL35D5Jx_G8WVnxXR3raDkJrBmCfO-bZ95S9rXhJvI-4u07PgKqudASgkYTK1bbzaONBkJqor4ipMCPaZUBxJg4WK6eSl9aKtAhrB16b5R8oLvMrRT9kY4uX_3XNiBhlvmni__Z/s1600/P4035750.JPG" height="240" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnK1g0LmTXanmWmC2YBQS3UCRBVnHvrQ-NPZSDAKFghn2fI0CACrhnErFEjSiNGFunAlXsOhFjBCTWYPes3z9z5vQvHSOyaG46uYFZVzq6mrbc_oX5wZgzyPOcg9yEpBnvg8lwVeVSUHaj/s1600/P4035785.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnK1g0LmTXanmWmC2YBQS3UCRBVnHvrQ-NPZSDAKFghn2fI0CACrhnErFEjSiNGFunAlXsOhFjBCTWYPes3z9z5vQvHSOyaG46uYFZVzq6mrbc_oX5wZgzyPOcg9yEpBnvg8lwVeVSUHaj/s1600/P4035785.JPG" height="320" width="240" /></a></div>
<br />
For long time my EDC kit was phone and keys. I had special phone case, that holds cards and keys hold other essentials like <a href="http://www.trueutility.com/products/cashstash">CashStash</a> for bills, <a href="http://www.leatherman.com/squirt-ps4-22.html">Leatherman Squirt PS4</a> as multitool, <a href="http://www.trueutility.com/collections/keyring-accessories/products/tu257black">TrueUtility pen</a>,<br />
even <a href="http://www.swisstechtools.com/proddetail.aspx?pid=5">Utili-key</a> as second multitool, as it is easier to get off keyring. I am still looking for good USB cable (I tried <a href="http://incharge.rocks/">InCharge</a>, but it is another story)<br />
<br />
I like this setup very much despite drawbacks. One problem was that it is very tight and there is no place for occasional spare items: checks, change, etc. Other problem is that case holds only 2 cards and e-ticket, but ideally I need more. Final and biggest problem is that my phone gets old<br />
and I want to change it, and wallet cases are not so popular as they used to, and there is no any decent for the new phone I want to buy. So I have to shuffle my items to fit caseless phone.<br />
<br />
<h2 style="text-align: left;">
Saddleback + phone + keys</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-9UTe9vr0nnQ/VR68ry_JL1I/AAAAAAABT3c/Gb5okvHsubw/s1600/P4035788.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-9UTe9vr0nnQ/VR68ry_JL1I/AAAAAAABT3c/Gb5okvHsubw/s1600/P4035788.JPG" height="240" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-rNhKvpVrll4/VR7A4zAEsAI/AAAAAAABUHw/xDCBAMHeVLc/s1600/P4035791.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-rNhKvpVrll4/VR7A4zAEsAI/AAAAAAABUHw/xDCBAMHeVLc/s1600/P4035791.JPG" height="320" width="240" /></a></div>
<br />
Saddleback is nice slim wallet, one of the best <a href="http://lifehacker.com/five-best-wallets-1659048954">according to LifeHacker</a>. Holds all cards and bills, and occasional checks. A little fat itself, even without cards, but not too fat. Phone with this wallet is almost as fat as phone with case. My biggest problem is that it is 3 pieces setup. 2 pieces - one item per pocket. With 3 pieces, 2 items should go into single pocket and there is problem that when I take out one item, another can fall out of pocket accidentally.<br />
<br />
<h2 style="text-align: left;">
<a href="http://www.crabbygear.com/">Crabby wallet</a> + phone</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIOFtMoZlj_iJNVJ4V8phE2Q2w3TeVIw6110RPH20MmIvpD-PSJbMDjSexhnWCQlx0njctUoX1DOFnR8M3sec92TKAYT1gMrw9XMJn6zHXKefmK-PqpmtPXE1cOBJyTSvcvuif-ki_gs5z/s1600/P4035775.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIOFtMoZlj_iJNVJ4V8phE2Q2w3TeVIw6110RPH20MmIvpD-PSJbMDjSexhnWCQlx0njctUoX1DOFnR8M3sec92TKAYT1gMrw9XMJn6zHXKefmK-PqpmtPXE1cOBJyTSvcvuif-ki_gs5z/s1600/P4035775.JPG" height="240" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEsXf5l9CaKBCqQfGBxhqjbZP3q8lI7Ab_jHLHv3iy50tkq0TZJgd8HRC5i9mKCksZR_9OQwuYL8POcgrNdiRQeqY1s_i5s71qIc-Z-DnvFo6zJOw_oGJ1TI1PjvlG5j62ybgP6wfWCAi0/s1600/P4035778.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEsXf5l9CaKBCqQfGBxhqjbZP3q8lI7Ab_jHLHv3iy50tkq0TZJgd8HRC5i9mKCksZR_9OQwuYL8POcgrNdiRQeqY1s_i5s71qIc-Z-DnvFo6zJOw_oGJ1TI1PjvlG5j62ybgP6wfWCAi0/s1600/P4035778.JPG" height="320" width="240" /></a></div>
<br />
Crabby is best for cards, super slim, holds cards firmly but still convenient to take card even from the middle. But it is not suitable for my keys as I have too many of them. I even got rid of Leatherman and CashStash (not super important as CashStash is not really needed anymore, as there is place for bills now; and Utili-key has most important tools of Leatherman).<br />
First problem: strap is too weak and narrow. It can hold 1 or max 2 flat keys. Second: single strap locks both cards and keys, so if you need keys - cards can fall out, and if you need cards, keys are not locked and it is disturbing. Third: strapping so many keys is always annoying and difficult, and with single strap you have to do it two times more often.<br />
Generally, Crabby is fine, but only if you have small number of keys. They warn about it in their ad, but I still decided to try. Unfortunately, they were right. Another disadvantage is that cards pocket is not zipped, so no coins or occasional small items.<br />
<br />
<h2 style="text-align: left;">
Local wallet with crabby claw <complete id="goog_1940986927">+ </complete>phone</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-V04QQJ7fv4I/VR6UP4-7h-I/AAAAAAABUDg/oaj8nmXhhnA/s1600/P4035762.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-V04QQJ7fv4I/VR6UP4-7h-I/AAAAAAABUDg/oaj8nmXhhnA/s1600/P4035762.JPG" height="240" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-0Px1ZV_Czlg/VR6Wl4jqDPI/AAAAAAABTus/IXSDOVH4W7I/s1600/P4035773.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-0Px1ZV_Czlg/VR6Wl4jqDPI/AAAAAAABTus/IXSDOVH4W7I/s1600/P4035773.JPG" height="320" width="240" /></a></div>
<br />
Very good setup, wallet has 2 pockets - one puffy for keys and other - larger but tighter - for cards and bills. Both pockets are zipped separately, so everything is safe and independent. Wallet is bigger, but still comfortable for pocket.<br />
Downsides: keys pocket is not intended for keys, so there is no any special ring or strap. I adapted slider to hold crabby claw, but it is not ideal. Also size of the keys pocket is pretty tight, and it is hard to put keys there. Taking keys out of wallet is fine and crabby claw gives some freedom, but putting them back is a little tricky. Other complain is that it is real, soft leather, which gives it great texture, but it is also a little bulkier and heavier.<br />
<br />
<h2 style="text-align: left;">
<a href="https://www.chums.com/keychains/product/marsupial">Chums marsupial</a> with crabby claw + phone</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZJ0qp3eOZL6E6Leyzuyh-1QeMPkp2CpZJVhgb3yH-4HUnXsbcmit9vRC1DZDbdpxZmMMhw1e7Eb0FRhn8bpFXqeXN3pGe1WpOo6iA8shcvwiGx3TZ0_YJRtqM7kHIpBbVCpIrM6H_CeDv/s1600/P4115800.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZJ0qp3eOZL6E6Leyzuyh-1QeMPkp2CpZJVhgb3yH-4HUnXsbcmit9vRC1DZDbdpxZmMMhw1e7Eb0FRhn8bpFXqeXN3pGe1WpOo6iA8shcvwiGx3TZ0_YJRtqM7kHIpBbVCpIrM6H_CeDv/s1600/P4115800.JPG" height="240" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFcA_t60LfFrelVccsRuw8crzmVVksAGTv9pVPDrSAs2QYVNh_QVY70zePg9so4fco0zyQgizjEet_dcy9nEVSWq79z5A5vmyUrIk1NNLG5zyH21xj1jiboDqlKz3Y099Ak6HAydffV55U/s1600/P4115808.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFcA_t60LfFrelVccsRuw8crzmVVksAGTv9pVPDrSAs2QYVNh_QVY70zePg9so4fco0zyQgizjEet_dcy9nEVSWq79z5A5vmyUrIk1NNLG5zyH21xj1jiboDqlKz3Y099Ak6HAydffV55U/s1600/P4115808.JPG" height="320" width="240" /></a></div>
<br />
Best setup. Size is almost as small as crabby, but has special pocket for keys, which even has strap (unfortunately it is not retractable, this is my only complain). Cards pocket is zipped, so it can hold occasional change, and size is just right for cards, easily holds about 10 cards, and there is some space left. Special keys pocket is very good. It is open from the short side, It is made from some artificial fabric and is really thin and light, feels like cheap plastic though. I should see if it is durable, hopefully - it is, as I'd like to keep it.<br />
<br />
<br /></div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com3tag:blogger.com,1999:blog-8445239617520884312.post-4257124242215174762015-01-23T13:18:00.000-08:002015-04-04T13:21:23.013-07:00VirtualBox DHCP gives same IP address to different machines<div dir="ltr" style="text-align: left;" trbidi="on">
Usually happens after cloning VMs and problem is because there is the same MAC address. Check virtual machine network settings and change as needed.</div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-82899063942250178922015-01-02T09:01:00.000-08:002015-01-02T09:01:55.719-08:00CanJS and ClojureScript<div dir="ltr" style="text-align: left;" trbidi="on">
I don't really like compiled JavaScript languages, but if I had to choose - I like <a href="http://clojure.org/clojurescript">ClojureScript</a> the most. It is big friends with <a href="https://github.com/swannodette/om">Om</a> MVC framework, which is based on <a href="http://facebook.github.io/react/">React.js</a>. React is another component framework like <a href="http://canjs.com/">CanJS</a>, but is too verbose to my tastes and has less features out of the box, so I like CanJS more. Only problem is that it does not have a lot of integration with ClojureScript. But it is pretty easy to solve, because ClojureScipt and CanJS are both amazing and flexible. There is example of simple component, there is ClojureScript:
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;"><span style="font-size: 12px; line-height: 14px;">
(ns myexample
(:require [domina :refer [by-id set-html!]]
[domina.css :refer [sel]]))
(.extend can/Component
#js {:tag "my-component"
:scope #js {:value 3
:increment #(.attr % "value" (inc (.attr % "value")))}})
(set-html! (by-id "my-root") (can/view "my-template" {}))
</span></span><span style="font-family: Times New Roman;"><span style="white-space: normal;">
</span></span></pre>
<div>
<br />
And HTML:
</div>
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;"><span style="font-size: 12px; line-height: 14px;">
<html>
<body>
<div id="my-root"></div>
<script type="text/mustache" id="my-template">
<my-component>
Value: {{value}} <input type="button" can-click="increment" value="Increment"/>
</my-component>
</script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.js"></script>
<script src="http://canjs.com/release/latest/can.jquery.js"></script>
<script src="base.js" type="text/javascript"></script>
<script src="</span></span><span style="font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px;">myexample</span><span style="font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px;">.js" type="text/javascript"></script></span>
<span style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;"><span style="font-size: 12px; line-height: 14px;"> <script type="text/javascript">goog.require("myexample");</script>
</body>
</html>
</span></span><span style="font-family: Times New Roman;"><span style="white-space: normal;">
</span></span></pre>
<br />
<br /></div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0tag:blogger.com,1999:blog-8445239617520884312.post-40095410031840371632014-12-19T09:56:00.000-08:002014-12-19T10:01:16.053-08:00Sending data to CanJS component<div dir="ltr" style="text-align: left;" trbidi="on">
Ideally, components should be independent, but sometimes it is needed to send data or call function on component from outside. It is possible to do by using observable like <i>can.Map</i> and listen to events on it from component like:
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;"><span style="font-size: 12px; line-height: 14px;">
<script type="text/javascript">
var observable = new can.Map({val:0});
$(function() {
can.Component.extend({
tag: "my-tag",
events: {
"{observable} val": function(param, param2, newval){
alert(newval);
}
}
});
$('#myTagDiv').html(can.view.mustache('<my-tag/>'));
});
</script>
</span></span><span style="font-family: Times New Roman;"><span style="white-space: normal;">
</span></span></pre>
<div>
<br /></div>
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); overflow: auto; padding: 5px; width: 100%;"><span style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;"><span style="font-size: 12px; line-height: 14px;">
<div id="myTagDiv"></div>
<input type="button" value="Call observable" onclick="observable.attr('val', observable.val+1);">
</span></span><span style="font-family: Times New Roman;"><span style="white-space: normal;">
</span></span></pre>
<br />
This way all components will receive observable change event either they are sent from itself, other component or directly from JavaScript.
<br />
<br /></div>
Dmitryhttp://www.blogger.com/profile/06410638196278990957noreply@blogger.com0