Thursday, April 11, 2019

Experiences with BAT

I've generally been fairly skeptical of cryptocurrency.  I don't doubt that there are applications for which blockchain is the perfect solution, but most of the use cases popularly mentioned are rather unconvincing.  I'm a lurker of /r/Buttcoin and found a lot of logic in the blog post by Ivan Ivanitskiy.

However, I am rather intrigued by what Brave and BAT are doing.  I run an ad-blocker because some sites are running ads that are just ridiculously obtrusive (and/or malicious).  But it's a real problem for how the internet gets funded.  A huge portion of the internet, mobile apps, etc are funded largely by ads, and the question of how digital content will be funded in the future is one of the biggest existential questions facing the internet today.  The work being done on acceptable ads is long overdue and helps address some of those problems.  But there is still a problem of misaligned incentives.  That is, Even if ads never tried to get you to install malware, and were never obnoxious, do users still have an incentive to not run ad blockers?  I don't know if it's perfect, but BAT gets closer than any solution I've seen so far to solving this problem.

But it's kinda broken at the moment due to the frustrations of getting going.  For example, I can't just set up a monthly deposit to keep my BAT wallet funded.  If you use Brave's preferred partner (Uphold), you currently have to transfer money to a fiat card first, then transfer it to a BAT card, then transfer it to Brave's wallet.  Not exactly simple.  Even worse, my MasterCard (Citi and Meijer ) and Visa (Amazon) declined the transaction to fund the fiat card.  Citi told me it was against their policy to allow cryptocurrency transactions.  I presume the other cards have similar rules/restrictions, though I haven't verified yet if that's why the transaction was declined (though I think Visa said something about needing manual verification).  I couldn't even add my Fifth Third or Cabela's MasterCards as funding methods in Uphold.  There was some kind of error.  I can't blame the financial institutions too much for this -- cryptocurrency is used so much for criminal activity, it's not unreasonable for them to be a little cautious.

But this poses a serious problem in adoption.  A lot of folks (especially millennials) don't want to pay anything for anything.  But if it's a pain to pay money to content providers, even when you are willing to pitch a few bucks their way, it makes the entire enterprise rather doomed from the start.  I think Brave has plans to allow you to fund your wallet directly in the browser -- and I think that's really what needs to happen to make the process as painless as possible for users.  Here's to hoping the process gets smoothed out in the future.

Edit: yes, I'm aware I don't have to use Uphold and can use whatever platform I want.  That's how cryptowallets work.  But, the only link in Brave's FAQ is documentation on how to setup Uphold.  I'd expect this is what most users would do.  Only users already comfortable with some other cyrptoplatform would know to do anything different.

Wednesday, August 26, 2015

A Maven Plugin Developer's Thoughts on Gradle

I use both Gradle and Maven, and I maintain a plugin for working with Groovy (GMavenPlus). I thought this gave me a somewhat unique perspective. I know this comparison is far from exhaustive, but I wanted to share some thoughts I'd jotted down.

When I first heard about Gradle, I was fairly dubious. Maven had been around for about 6 years at that point and they were making some rather large promises. Although I was intrigued, my reaction was "come back to me when you have a non-RC 1.0 release". Since then, they've had several stable releases and about 6 years of their own maturing.

What I like about Gradle
  • They kept the best parts of Maven
    • The lifecycle concept
    • The standardized project layout
    • The dependency management concept
  • Very concise syntax.  It's an amazing feeling to be able to do a standard Java build with a single line of code.
  • Keeps the simple things simple, while allowing you to use the power of Groovy and Ant if you need something non-standard.
  • Gradle Wrapper (gradlew) is a nice way to help keep builds reproducible
  • Application Plugin (Maven has ways to do this, but having it in a plugin is convenient)
  • Much more flexible than Maven (in nearly every way -- dependency management, lifecycle customization, custom tasks, etc)
  • Can put environment config and dev helper scripts right into the build as tasks instead of separate script files
  • HTML test report is nicer than Surefire's, and I now prefer it over console text
  • Has a test runtime scope (unlike Maven)
What I don't like about Gradle
  • Allowing people to do custom things so easily might lead to the tangled mess that was Ant. There's already some pretty crazy builds out there (though arguably this isn't much riskier than what you could do with AntRun or GMavenPlus).
  • Because it's Groovy instead of XML, you don't answers get as helpful hints from your IDE.
  • Can't include multiple source directories each with their own includes/excludes patterns (they have a TODO for this).
  • Groovy building Groovy can sometimes be problematic
  • No equivalent of mvn install, which makes end-to-end testing of plugins clunkier (though they now offer TestKit that should help with this)
  • Some areas might be perceived as being less mature
  • No isolation of plugin dependencies -- they all run on the same classpath (unlike Maven), unless the author took the time to do custom classloader work, which most don't.
Notable differences from Maven
  • In Gradle, default target bytecode version is version of JDK, whereas in Maven default is currently 1.5
  • Gradle's commands are case-insensitive (something I actually really like)
  • Gradle doesn't compile tests unless specifically asked for (gradle classes != mvn compile, gradle testClasses == mvn compile) (not really a positive or negative, just something to be aware of)
  • Gradle will stop testing after the first module to have a test failure. You have to use the --continue argument to continue on to the other modules the way Maven does. I kinda wish this was the default.
What I like About Maven
  • Maven's inflexibility has largely proven very successful in preventing pointless deviation from the established pattern.
  • The lifecycle concept
  • The standardized project layout
  • The dependency management concept
What I don't like About Maven
  • XML is pretty cumbersome (though Polyglot for Maven isn't completely dead). This leads to out of control copy-and-pasting of POMs, with dependencies that have no business being there.
  • Convention over configuration doesn't go far enough (ideally, a basic Java project should be just a few lines, like it is in Gradle)
  • No ability to specify ranges of versions that are acceptable for transitive resolution (I haven't used it much -- but it's a really cool feature)
  • No TestRuntime scope
  • No Maven Wrapper equivalent of gradlew (though there is an unofficial project)
How Gradle has improved Maven
It took a while, but you can finally opt out of transitive dependencies. I think Gradle (and Ivy) earned a good deal of credit for the pressure to offer this feature.

I honestly think despite there being some areas Gradle can be improved, it's generally the better choice for most projects.  There are circumstances where this isn't the case (like if you're building a Maven plugin). But in most cases, I think Gradle's pros outweigh the cons. But if you prefer Maven (or your CTO/CIO/Architect is making the choice for you), rest assured that despite my recommendation, I'm committed to maintaining GMavenPlus for the indefinite future so that the choice is always yours to make.

More Resources

Monday, August 10, 2015

Forcing Windows 10 Upgrade

Want to get your free upgrade to Windows 10, but don't want to wait your turn? Run this reg file
Windows Registry Editor Version 5.00
Then open the command prompt as an administrator and run
wuauclt.exe /updatenow

Wednesday, July 15, 2015

Custom configuration script ASTs

Nikolay Totomanov asked on the Groovy mailing list how one could add a default constructor (if it doesn't already exist) to all classes. I realized there were no examples on the internet (that I could find anyway) of
  1. How to pass parameters into an AST in a configuration script
  2. How to use a custom AST in a configuration script
So I decided to try to remedy that with this post.

1. AST parameters in a configuration script
Let's say you wanted to do
in a configuration script. How do you pass the includes? Use a map. The equivalent configuration script would be
withConfig(configuration) {
    ast(groovy.transform.TupleConstructor, includes:['foo'])

2. Custom AST in a configuration script
If you wanted to create your own AST and use it in a configuration script, I suggest looking at Groovy as a starting point. Here, I'll use groovy.transform.TupleConstructor and org.codehaus.groovy.transform.TupleConstructorASTTransformation as an example to solve Nikolay's problem. Here is the result
import java.lang.annotation.ElementType
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Target
import org.codehaus.groovy.ast.ASTNode
import org.codehaus.groovy.ast.AnnotatedNode
import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.ast.ConstructorNode
import org.codehaus.groovy.ast.Parameter
import org.codehaus.groovy.ast.stmt.BlockStatement
import org.codehaus.groovy.control.CompilePhase
import org.codehaus.groovy.control.SourceUnit
import org.codehaus.groovy.transform.AbstractASTTransformation
import org.codehaus.groovy.transform.GroovyASTTransformation
import org.codehaus.groovy.transform.GroovyASTTransformationClass

@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
public class DefaultConstructorASTTransformation extends AbstractASTTransformation {
    public void visit(ASTNode[] nodes, SourceUnit source) {
        init(nodes, source)
        AnnotatedNode parent = (AnnotatedNode) nodes[1]
        if (parent instanceof ClassNode) {
            ClassNode cNode = (ClassNode) parent
            if (!cNode.getDeclaredConstructor(new Parameter[0])) {  // doesn't already have a default constructor
                cNode.addConstructor(new ConstructorNode(ACC_PUBLIC, new Parameter[0], cNode.EMPTY_ARRAY, new BlockStatement()))
public @interface DefaultConstructor {}

withConfig(configuration) {

Tuesday, May 26, 2015

Guava Hadoop Classpath Issue

Blogging this because it was slightly too large for a tweet.  If you've got a stacktrace like

java.lang.NoClassDefFoundError: com/google/common/io/LimitInputStream
at org.apache.hadoop.mapreduce.JobSubmitter.submitJobInternal( at org.apache.hadoop.mapreduce.Job$ at org.apache.hadoop.mapreduce.Job$ at Method) at at at org.apache.hadoop.mapreduce.Job.submit( at org.apache.hadoop.mapreduce.Job.waitForCompletion(

You may find this problematic dependency tree

It seems Google has once again broken compatibility in Guava by removing LimitInputStream in Guava 15.  And while much of Hadoop (except the new versions which have upgraded their Guava version) are on an older version of Guva, the hadoop-auth module contains a newer version of Guava that most dependency management tools (aka Maven and Gradle) will choose over the older version.  Adding an exclusion for this transitive dependency should resolve this issue.

Friday, May 15, 2015

IntelliJ and junit-hierarchicalcontextrunner

For those using junit-hierarchicalcontextrunner getting an exception like
java.lang.Exception: The inner class com.mycompany.SomeClassTest$InnerClass is not static.
 at org.junit.runners.BlockJUnit4ClassRunner.validateNoNonStaticInnerClass(
You might be able to get rid of that error (especially if it happens when running in IntelliJ, but not the commandline) by upgrading to JUnit 4.12 and junit-hierarchicalcontextrunner 4.12.0. However, if you're an IntelliJ user, you'll find that running an individual test still runs all the tests. This will be fixed in an upcoming release.

Friday, May 1, 2015

Codehaus Migration

Since Codehaus is shutting down, you may be wondering where a project you use has moved. Here's where some of the more popular projects have moved.

Project Old Homepage New Homepage
JavaNCSS NONE YET (though Codehaus has a mirror on Github)
Mojo (still transitioning)
Pico Container
Plexus Classworlds
Plexus Containers

I'll keep this page updated as more information becomes available (let me know if you spot something incorrect or out of date). Also if there's a project not on this list that you think should be, let me know and I'll add it. I know some of these moves are old news, but I listed them anyway since once Codehaus shuts down, any redirects they may have had will stop working.