To follow up with your other issue, if you are just trying to count elements in a DStream, you can do that without an Accumulator. foreachRDD is meant to be an output action, it does not return anything and it is actually run in the driver program. Because Java (before 8) handles closures a little differently, it might be easiest to implement the function to pass to foreachRDD as something like this:
class MyFunc implements VoidFunction<JavaRDD<Integer>> { public long total = 0; @Override public void call(JavaRDD<Integer> rdd) { System.out.println("foo " + rdd.collect().toString()); total += rdd.count(); } } MyFunc f = new MyFunc(); inputStream.foreachRDD(f); // f.total will have the count of all RDDs Hope that helps some! -bryan On Wed, Dec 16, 2015 at 8:37 AM, Bryan Cutler <cutl...@gmail.com> wrote: > Hi Andy, > > Regarding the foreachrdd return value, this Jira that will be in 1.6 > should take care of that https://issues.apache.org/jira/browse/SPARK-4557 > and make things a little simpler. > On Dec 15, 2015 6:55 PM, "Andy Davidson" <a...@santacruzintegration.com> > wrote: > >> I am writing a JUnit test for some simple streaming code. I want to >> make assertions about how many things are in a given JavaDStream. I wonder >> if there is an easier way in Java to get the count? >> >> I think there are two points of friction. >> >> >> 1. is it easy to create an accumulator of type double or int, How >> ever Long is not supported >> 2. We need to use javaDStream.foreachRDD. The Function interface must >> return void. I was not able to define an accumulator in my driver and >> use a lambda function. (I am new to lambda in Java) >> >> Here is a little lambda example that logs my test objects. I was not >> able to figure out how to get to return a value or access a accumulator >> >> data.foreachRDD(rdd -> { >> >> logger.info(“Begin data.foreachRDD" ); >> >> for (MyPojo pojo : rdd.collect()) { >> >> logger.info("\n{}", pojo.toString()); >> >> } >> >> return null; >> >> }); >> >> >> Any suggestions would be greatly appreciated >> >> Andy >> >> This following code works in my driver but is a lot of code for such a >> trivial computation. Because it needs to the JavaSparkContext I do not >> think it would work inside a closure. I assume the works do not have access >> to the context as a global and that it shipping it in the closure is not a >> good idea? >> >> public class JavaDStreamCount<T> implements Serializable { >> >> private static final long serialVersionUID = -3600586183332429887L; >> >> public static Logger logger = >> LoggerFactory.getLogger(JavaDStreamCount.class); >> >> >> >> public Double hack(JavaSparkContext sc, JavaDStream<T> javaDStream) { >> >> Count c = new Count(sc); >> >> javaDStream.foreachRDD(c); >> >> return c.getTotal().value(); >> >> } >> >> >> >> class Count implements Function<JavaRDD<T>,Void> { >> >> private static final long serialVersionUID = >> -5239727633710162488L; >> >> Accumulator<Double> total; >> >> >> >> public Count(JavaSparkContext sc) { >> >> total = sc.accumulator(0.0); >> >> } >> >> >> >> @Override >> >> public java.lang.Void call(JavaRDD<T> rdd) throws Exception { >> >> List<T> data = rdd.collect(); >> >> int dataSize = data.size(); >> >> logger.error("data.size:{}", dataSize); >> >> long num = rdd.count(); >> >> logger.error("num:{}", num); >> >> total.add(new Double(num)); >> >> return null; >> >> } >> >> >> public Accumulator<Double> getTotal() { >> >> return total; >> >> } >> >> } >> >> } >> >> >> >> >>