├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── libraries │ ├── Maven__aopalliance_aopalliance_1_0.xml │ ├── Maven__ch_qos_logback_logback_classic_1_1_7.xml │ ├── Maven__ch_qos_logback_logback_core_1_1_7.xml │ ├── Maven__com_google_guava_guava_16_0_1.xml │ ├── Maven__io_netty_netty_3_7_0_Final.xml │ ├── Maven__jline_jline_0_9_94.xml │ ├── Maven__junit_junit_4_12.xml │ ├── Maven__net_sf_jopt_simple_jopt_simple_3_2.xml │ ├── Maven__org_apache_curator_curator_client_2_10_0.xml │ ├── Maven__org_apache_curator_curator_framework_2_10_0.xml │ ├── Maven__org_apache_curator_curator_recipes_2_10_0.xml │ ├── Maven__org_apache_samza_samza_api_0_9_1.xml │ ├── Maven__org_apache_samza_samza_core_2_10_0_9_1.xml │ ├── Maven__org_apache_zookeeper_zookeeper_3_4_6.xml │ ├── Maven__org_codehaus_groovy_groovy_all_2_4_6.xml │ ├── Maven__org_codehaus_jackson_jackson_core_asl_1_8_5.xml │ ├── Maven__org_codehaus_jackson_jackson_mapper_asl_1_8_5.xml │ ├── Maven__org_easymock_easymock_3_4.xml │ ├── Maven__org_eclipse_jetty_jetty_continuation_8_1_8_v20121106.xml │ ├── Maven__org_eclipse_jetty_jetty_http_8_1_8_v20121106.xml │ ├── Maven__org_eclipse_jetty_jetty_io_8_1_8_v20121106.xml │ ├── Maven__org_eclipse_jetty_jetty_security_8_1_8_v20121106.xml │ ├── Maven__org_eclipse_jetty_jetty_server_8_1_8_v20121106.xml │ ├── Maven__org_eclipse_jetty_jetty_servlet_8_1_8_v20121106.xml │ ├── Maven__org_eclipse_jetty_jetty_util_8_1_8_v20121106.xml │ ├── Maven__org_eclipse_jetty_jetty_webapp_8_1_8_v20121106.xml │ ├── Maven__org_eclipse_jetty_jetty_xml_8_1_8_v20121106.xml │ ├── Maven__org_eclipse_jetty_orbit_javax_servlet_3_0_0_v201112011016.xml │ ├── Maven__org_hamcrest_hamcrest_core_1_3.xml │ ├── Maven__org_hamcrest_hamcrest_library_1_3.xml │ ├── Maven__org_mockito_mockito_core_1_10_19.xml │ ├── Maven__org_objenesis_objenesis_2_2.xml │ ├── Maven__org_scala_lang_scala_library_2_10_4.xml │ ├── Maven__org_slf4j_jcl_over_slf4j_1_7_21.xml │ ├── Maven__org_slf4j_jul_to_slf4j_1_7_21.xml │ ├── Maven__org_slf4j_log4j_over_slf4j_1_7_21.xml │ ├── Maven__org_slf4j_slf4j_api_1_7_21.xml │ ├── Maven__org_springframework_boot_spring_boot_1_3_4_RELEASE.xml │ ├── Maven__org_springframework_boot_spring_boot_autoconfigure_1_3_4_RELEASE.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_1_3_4_RELEASE.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_logging_1_3_4_RELEASE.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_test_1_3_4_RELEASE.xml │ ├── Maven__org_springframework_spring_aop_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_beans_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_context_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_core_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_expression_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_test_4_2_6_RELEASE.xml │ └── Maven__org_yaml_snakeyaml_1_16.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── .travis.yml ├── LICENSE ├── README.md ├── additional-curator-recipes ├── additional-curator-recipes.iml ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── stormpath │ │ └── curator │ │ └── framework │ │ └── recipes │ │ └── nodes │ │ └── SequentialGroupMember.java │ └── test │ └── groovy │ └── com │ └── stormpath │ └── curator │ └── framework │ └── recipes │ └── nodes │ └── SequentialGroupMemberTest.groovy ├── pom.xml ├── samza-api ├── pom.xml ├── samza-api.iml └── src │ ├── main │ └── java │ │ └── com │ │ └── stormpath │ │ └── samza │ │ └── serializers │ │ └── SpringSerde.java │ └── test │ └── groovy │ └── com │ └── stormpath │ └── samza │ └── serializers │ └── SpringSerdeTest.groovy ├── samza-spring-boot-autoconfigure ├── pom.xml ├── samza-spring-boot-autoconfigure.iml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── stormpath │ │ │ └── spring │ │ │ ├── boot │ │ │ └── samza │ │ │ │ ├── ConfigTimeCheckpointManagerFactory.java │ │ │ │ ├── ConfigTimeStreamTask.java │ │ │ │ ├── DisabledCheckpointManager.java │ │ │ │ ├── FixedCheckpointManagerFactory.java │ │ │ │ ├── SamzaAutoConfiguration.java │ │ │ │ └── SpringThreadJob.java │ │ │ └── context │ │ │ └── StaticApplicationContextProvider.java │ └── resources │ │ └── META-INF │ │ └── spring.factories │ └── test │ ├── groovy │ └── com │ │ └── stormpath │ │ └── spring │ │ └── boot │ │ └── samza │ │ ├── MemorySystemConsumer.groovy │ │ ├── MemorySystemFactory.groovy │ │ ├── MemorySystemProducer.groovy │ │ ├── SamzaConfigurationIT.groovy │ │ ├── TestTask.groovy │ │ └── TestTaskConfiguration.groovy │ └── resources │ ├── com │ └── stormpath │ │ └── spring │ │ └── boot │ │ └── samza │ │ └── application.properties │ └── logback.xml ├── samza-spring-boot-starter-parent.iml ├── samza-spring-boot-starter ├── pom.xml ├── samza-spring-boot-starter.iml └── src │ └── main │ └── resources │ └── META-INF │ └── spring.provides ├── samza-zookeeper-spring-boot-autoconfigure ├── pom.xml ├── samza-zookeeper-spring-boot-autoconfigure.iml └── src │ └── main │ ├── java │ └── com │ │ └── stormpath │ │ └── spring │ │ └── boot │ │ └── samza │ │ └── curator │ │ ├── CuratorSamzaAutoConfiguration.java │ │ └── checkpoint │ │ └── ZookeeperCheckpointAutoConfiguration.java │ └── resources │ └── META-INF │ └── spring.factories └── samza-zookeeper ├── pom.xml ├── samza-zookeeper.iml └── src └── main └── java └── com └── stormpath └── samza ├── curator └── checkpoint │ └── ZookeeperCheckpointManager.java └── lang ├── Arrays.java ├── Assert.java ├── Classes.java ├── Collections.java ├── InstantiationException.java ├── Objects.java ├── ScalaUtils.java ├── Strings.java └── UnknownClassException.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | target/ 3 | .idea/workspace.xml 4 | 5 | # Mobile Tools for Java (J2ME) 6 | .mtj.tmp/ 7 | 8 | # Package Files # 9 | *.jar 10 | *.war 11 | *.ear 12 | 13 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 14 | hs_err_pid* 15 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | samza-spring-boot-starter-parent -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__aopalliance_aopalliance_1_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__ch_qos_logback_logback_classic_1_1_7.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__ch_qos_logback_logback_core_1_1_7.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_google_guava_guava_16_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_netty_netty_3_7_0_Final.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__jline_jline_0_9_94.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__junit_junit_4_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__net_sf_jopt_simple_jopt_simple_3_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_curator_curator_client_2_10_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_curator_curator_framework_2_10_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_curator_curator_recipes_2_10_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_samza_samza_api_0_9_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_samza_samza_core_2_10_0_9_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_zookeeper_zookeeper_3_4_6.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_codehaus_groovy_groovy_all_2_4_6.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_codehaus_jackson_jackson_core_asl_1_8_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_codehaus_jackson_jackson_mapper_asl_1_8_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_easymock_easymock_3_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_eclipse_jetty_jetty_continuation_8_1_8_v20121106.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_eclipse_jetty_jetty_http_8_1_8_v20121106.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_eclipse_jetty_jetty_io_8_1_8_v20121106.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_eclipse_jetty_jetty_security_8_1_8_v20121106.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_eclipse_jetty_jetty_server_8_1_8_v20121106.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_eclipse_jetty_jetty_servlet_8_1_8_v20121106.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_eclipse_jetty_jetty_util_8_1_8_v20121106.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_eclipse_jetty_jetty_webapp_8_1_8_v20121106.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_eclipse_jetty_jetty_xml_8_1_8_v20121106.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_eclipse_jetty_orbit_javax_servlet_3_0_0_v201112011016.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_hamcrest_hamcrest_library_1_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_mockito_mockito_core_1_10_19.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_objenesis_objenesis_2_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_scala_lang_scala_library_2_10_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_slf4j_jcl_over_slf4j_1_7_21.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_21.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_slf4j_log4j_over_slf4j_1_7_21.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_21.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_1_3_4_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_1_3_4_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_1_3_4_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_1_3_4_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_1_3_4_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_aop_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_beans_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_context_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_core_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_expression_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_test_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_yaml_snakeyaml_1_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 36 | 37 | 38 | 39 | 40 | 41 | 1.8 42 | 43 | 48 | 49 | 50 | 51 | 52 | 53 | 1.8 54 | 55 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | sudo: false 3 | jdk: 4 | - oraclejdk8 5 | before_install: 6 | - export RELEASE_VERSION="$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate 7 | -Dexpression=project.version|grep -Ev '(^\[|Download\w+:)')" 8 | - export IS_RELEASE="$([ ${RELEASE_VERSION/SNAPSHOT} == $RELEASE_VERSION ] && [ $TRAVIS_BRANCH == 'master' ] && echo 'true')" 9 | - export BUILD_DOCS="$([ $TRAVIS_JDK_VERSION == 'oraclejdk8' ] && echo 'true')" 10 | - export RUN_ITS="$([ $TRAVIS_JDK_VERSION == 'oraclejdk8' ] && echo 'true')" 11 | script: 12 | - mvn clean install -B -Pdocs -DskipITs=false 13 | 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Stormpath is Joining Okta 2 | We are incredibly excited to announce that [Stormpath is joining forces with Okta](https://stormpath.com/blog/stormpaths-new-path?utm_source=github&utm_medium=readme&utm-campaign=okta-announcement). Please visit [the Migration FAQs](https://stormpath.com/oktaplusstormpath?utm_source=github&utm_medium=readme&utm-campaign=okta-announcement) for a detailed look at what this means for Stormpath users. 3 | 4 | We're available to answer all questions at [support@stormpath.com](mailto:support@stormpath.com). 5 | 6 | # samza-spring-boot-starter 7 | Run Samza as a Spring Boot application 8 | -------------------------------------------------------------------------------- /additional-curator-recipes/additional-curator-recipes.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /additional-curator-recipes/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | com.stormpath.spring.boot.samza 9 | samza-spring-boot-starter-parent 10 | 0.2.3-SNAPSHOT 11 | ../pom.xml 12 | 13 | 14 | additional-curator-recipes 15 | Samza Spring Boot :: Addtl Curator Recipes 16 | 17 | 18 | 19 | org.apache.curator 20 | curator-recipes 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-autoconfigure 25 | 26 | 27 | 28 | 29 | org.slf4j 30 | jcl-over-slf4j 31 | test 32 | 33 | 34 | org.slf4j 35 | log4j-over-slf4j 36 | test 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /additional-curator-recipes/src/main/java/com/stormpath/curator/framework/recipes/nodes/SequentialGroupMember.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.curator.framework.recipes.nodes; 2 | 3 | import com.google.common.base.Throwables; 4 | import org.apache.curator.framework.CuratorFramework; 5 | import org.apache.curator.framework.recipes.locks.InterProcessMutex; 6 | import org.apache.curator.framework.recipes.nodes.PersistentNode; 7 | import org.apache.curator.utils.CloseableUtils; 8 | import org.apache.curator.utils.ThreadUtils; 9 | import org.apache.curator.utils.ZKPaths; 10 | import org.apache.zookeeper.CreateMode; 11 | import org.apache.zookeeper.data.Stat; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.util.Assert; 15 | 16 | import java.io.Closeable; 17 | import java.util.concurrent.TimeUnit; 18 | 19 | public class SequentialGroupMember implements Closeable { 20 | 21 | private static final Logger log = LoggerFactory.getLogger(SequentialGroupMember.class); 22 | 23 | private final CuratorFramework client; 24 | private final int startingId; 25 | private final String membersBasePath; 26 | private final String locksBasePath; 27 | private final byte[] payload; 28 | 29 | private PersistentNode pen; 30 | private int id = -1; 31 | 32 | /** 33 | * @param client client 34 | * @param membersBasePath the path to use for membership 35 | * @param payload the payload to write in our member node 36 | */ 37 | public SequentialGroupMember(CuratorFramework client, String membersBasePath, String locksBasePath, byte[] payload) { 38 | this(client, membersBasePath, locksBasePath, 0, payload); 39 | } 40 | 41 | /** 42 | * @param client client 43 | * @param membersBasePath the path to use for membership 44 | * @param payload the payload to write in our member node 45 | */ 46 | public SequentialGroupMember(CuratorFramework client, String membersBasePath, String locksBasePath, int startingId, byte[] payload) { 47 | Assert.isTrue(startingId >= 0, "startingId must be greater than or equal to zero."); 48 | this.startingId = startingId; 49 | this.membersBasePath = membersBasePath; 50 | this.locksBasePath = locksBasePath; 51 | this.client = client; 52 | this.payload = payload; 53 | } 54 | 55 | public int getId() { 56 | Assert.isTrue(this.id != -1, "member id not yet acquired. call start() first."); 57 | return this.id; 58 | } 59 | 60 | /** 61 | * Start the group membership. Register thisId as a member and begin 62 | * caching all members 63 | */ 64 | public void start() { 65 | try { 66 | doStart(); 67 | } catch (Exception e) { 68 | ThreadUtils.checkInterrupted(e); 69 | Throwables.propagate(e); 70 | } 71 | } 72 | 73 | protected void doStart() throws Exception { 74 | 75 | int i = startingId; 76 | 77 | while (this.id == -1) { 78 | 79 | String lockPath = ZKPaths.makePath(locksBasePath, String.valueOf(i)); 80 | String memberPath = ZKPaths.makePath(membersBasePath, String.valueOf(i)); 81 | 82 | log.trace("Acquiring mutex for member {} via lock path {}", i, lockPath); 83 | 84 | InterProcessMutex mutex = new InterProcessMutex(this.client, lockPath); 85 | mutex.acquire(); 86 | 87 | log.debug("Acquired mutex for member {} via lock path {}", i, lockPath); 88 | 89 | try { 90 | 91 | Stat stat = client.checkExists().creatingParentContainersIfNeeded().forPath(memberPath); 92 | 93 | if (stat == null) { 94 | 95 | log.debug("Claiming container id {} via member path {}", i, memberPath); 96 | 97 | try { 98 | //no peer has this node yet, grab it: 99 | pen = new PersistentNode(client, CreateMode.EPHEMERAL, false, memberPath, payload); 100 | pen.start(); 101 | pen.waitForInitialCreate(30000, TimeUnit.SECONDS); 102 | this.id = i; 103 | log.info("Claimed container id {} via member path {}", i, memberPath); 104 | return; 105 | } catch (InterruptedException e) { 106 | CloseableUtils.closeQuietly(pen); 107 | ThreadUtils.checkInterrupted(e); 108 | Throwables.propagate(e); 109 | } 110 | } 111 | 112 | } finally { 113 | mutex.release(); 114 | log.debug("Released mutex for member {} via lock path {}", i, lockPath); 115 | } 116 | 117 | i++; 118 | } 119 | } 120 | 121 | /** 122 | * Change the data stored in this instance's node 123 | * 124 | * @param data new data (cannot be null) 125 | */ 126 | public void setData(byte[] data) { 127 | try { 128 | pen.setData(data); 129 | } catch (Exception e) { 130 | ThreadUtils.checkInterrupted(e); 131 | Throwables.propagate(e); 132 | } 133 | } 134 | 135 | /** 136 | * Have thisId leave the group and stop caching membership 137 | */ 138 | @Override 139 | public void close() { 140 | CloseableUtils.closeQuietly(pen); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /additional-curator-recipes/src/test/groovy/com/stormpath/curator/framework/recipes/nodes/SequentialGroupMemberTest.groovy: -------------------------------------------------------------------------------- 1 | package com.stormpath.curator.framework.recipes.nodes 2 | 3 | import org.junit.Test 4 | 5 | import static org.junit.Assert.*; 6 | 7 | class SequentialGroupMemberTest { 8 | 9 | /* 10 | @Test 11 | void testIdFromPathWithZero() { 12 | String path = '/samza/jobs/foo/containers/_c_f1b351a4-fc30-44a7-8072-c3bc4635c09c-containers0000000000' 13 | assertEquals 0, SequentialGroupMember.idFromPath(path); 14 | } 15 | 16 | @Test 17 | void testIdFromPathWithOne() { 18 | String path = '/samza/jobs/foo/containers/_c_f1b351a4-fc30-44a7-8072-c3bc4635c09c-containers0000000001' 19 | assertEquals 1, SequentialGroupMember.idFromPath(path); 20 | } 21 | 22 | @Test 23 | void testIdFromPathWithVarious() { 24 | String path = '/samza/jobs/foo/containers/_c_f1b351a4-fc30-44a7-8072-c3bc4635c09c-containers0012003001' 25 | assertEquals 12003001, SequentialGroupMember.idFromPath(path); 26 | } 27 | */ 28 | } 29 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | org.sonatype.oss 9 | oss-parent 10 | 7 11 | 12 | 13 | com.stormpath.spring.boot.samza 14 | samza-spring-boot-starter-parent 15 | 0.2.3-SNAPSHOT 16 | pom 17 | 18 | Samza Spring Boot 19 | Starter for running Samza inside a Spring Boot application. 20 | https://github.com/stormpath/samza-spring-boot-starter 21 | 22 | 23 | Stormpath, Inc. 24 | https://stormpath.com 25 | 26 | 27 | 28 | 29 | Apache License, Version 2.0 30 | http://www.apache.org/licenses/LICENSE-2.0 31 | repo 32 | 33 | 34 | 35 | 36 | scm:git:git@github.com:stormpath/samza-spring-boot-starter.git 37 | scm:git:git@github.com:stormpath/samza-spring-boot-starter.git 38 | git@github.com:stormpath/samza-spring-boot-starter.git 39 | HEAD 40 | 41 | 42 | GitHub 43 | https://github.com/stormpath/samza-spring-boot-starter/issues 44 | 45 | 46 | 47 | 2.10.0 48 | 3.4 49 | 1.1.7 50 | 1.4 51 | 0.9.1 52 | 1.7.21 53 | 4.2.6.RELEASE 54 | 1.3.4.RELEASE 55 | 56 | 57 | 2.16 58 | 2.4.6 59 | 4.12 60 | false 61 | 62 | 64 | -Xdoclint:none 65 | 66 | 67 | 68 | additional-curator-recipes 69 | samza-api 70 | samza-spring-boot-autoconfigure 71 | samza-zookeeper 72 | samza-zookeeper-spring-boot-autoconfigure 73 | samza-spring-boot-starter 74 | 75 | 76 | 77 | 78 | 79 | com.stormpath.spring.boot.samza 80 | additional-curator-recipes 81 | ${project.version} 82 | 83 | 84 | com.stormpath.spring.boot.samza 85 | samza-spring-boot-autoconfigure 86 | ${project.version} 87 | 88 | 89 | com.stormpath.spring.boot.samza 90 | samza-kv 91 | ${project.version} 92 | 93 | 94 | com.stormpath.spring.boot.samza 95 | samza-zookeeper 96 | ${project.version} 97 | 98 | 99 | com.stormpath.spring.boot.samza 100 | samza-zookeeper-spring-boot-autoconfigure 101 | ${project.version} 102 | 103 | 104 | 105 | org.springframework 106 | spring-core 107 | ${spring.version} 108 | 109 | 110 | commons-logging 111 | commons-logging 112 | 113 | 114 | 115 | 116 | org.springframework.boot 117 | spring-boot-starter 118 | ${spring.boot.version} 119 | 120 | 121 | 122 | org.springframework.boot 123 | spring-boot-autoconfigure 124 | ${spring.boot.version} 125 | 126 | 127 | commons-logging 128 | commons-logging 129 | 130 | 131 | 132 | 133 | 134 | org.slf4j 135 | slf4j-api 136 | ${slf4j.version} 137 | 138 | 139 | 140 | org.apache.samza 141 | samza-api 142 | ${samza.version} 143 | 144 | 145 | org.apache.samza 146 | samza-core_2.10 147 | ${samza.version} 148 | 149 | 150 | 151 | org.apache.samza 152 | samza-kv_2.10 153 | ${samza.version} 154 | 155 | 156 | 157 | org.apache.curator 158 | curator-recipes 159 | ${curator.version} 160 | 161 | 162 | log4j 163 | log4j 164 | 165 | 166 | commons-logging 167 | commons-logging 168 | 169 | 170 | 171 | 172 | 173 | 174 | org.springframework.boot 175 | spring-boot-starter-test 176 | ${spring.boot.version} 177 | test 178 | 179 | 180 | org.slf4j 181 | jcl-over-slf4j 182 | ${slf4j.version} 183 | test 184 | 185 | 186 | org.slf4j 187 | log4j-over-slf4j 188 | ${slf4j.version} 189 | test 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | org.slf4j 198 | slf4j-api 199 | 200 | 201 | 202 | 203 | junit 204 | junit 205 | ${junit.version} 206 | 207 | 208 | org.easymock 209 | easymock 210 | ${easymock.version} 211 | test 212 | 213 | 214 | ch.qos.logback 215 | logback-classic 216 | ${logback.version} 217 | test 218 | 219 | 220 | org.slf4j 221 | jcl-over-slf4j 222 | test 223 | 224 | 225 | org.slf4j 226 | log4j-over-slf4j 227 | test 228 | 229 | 230 | org.codehaus.groovy 231 | groovy-all 232 | ${groovy.version} 233 | test 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | org.apache.maven.plugins 242 | maven-enforcer-plugin 243 | ${maven.enforcer.plugin.version} 244 | 245 | 246 | enforce-banned-dependencies 247 | 248 | enforce 249 | 250 | 251 | 252 | 253 | 254 | log4j 255 | commons-logging 256 | slf4j-log4j12 257 | slf4j-jdk14 258 | slf4j-nop 259 | slf4j-simple 260 | slf4j-jcl 261 | 262 | 263 | 264 | true 265 | 266 | 267 | 268 | 269 | 270 | org.apache.maven.plugins 271 | maven-compiler-plugin 272 | 3.1 273 | 274 | 1.8 275 | 1.8 276 | 277 | 278 | 279 | org.apache.maven.plugins 280 | maven-surefire-plugin 281 | 2.19.1 282 | 283 | 284 | **/*Spec.* 285 | **/*Test.* 286 | 287 | 288 | 289 | 290 | 291 | org.codehaus.gmavenplus 292 | gmavenplus-plugin 293 | 1.5 294 | 295 | 296 | org.codehaus.groovy 297 | groovy-all 298 | ${groovy.version} 299 | 300 | 301 | 302 | 303 | 304 | addSources 305 | addTestSources 306 | generateStubs 307 | compile 308 | testGenerateStubs 309 | testCompile 310 | removeStubs 311 | removeTestStubs 312 | 313 | 314 | 315 | 316 | 317 | org.apache.maven.plugins 318 | maven-failsafe-plugin 319 | ${failsafe.plugin.version} 320 | 321 | 322 | org.apache.maven.plugins 323 | maven-release-plugin 324 | 2.4.2 325 | 326 | 327 | org.apache.maven.scm 328 | maven-scm-provider-gitexe 329 | 1.8.1 330 | 331 | 332 | 333 | forked-path 334 | false 335 | -DskipTests -Pdocs,stormpath-signature 336 | true 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | stormpath-signature 345 | 346 | 347 | 348 | org.apache.maven.plugins 349 | maven-gpg-plugin 350 | 1.4 351 | 352 | 353 | sign-artifacts 354 | verify 355 | 356 | sign 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | docs 366 | 367 | 368 | 369 | org.apache.maven.plugins 370 | maven-javadoc-plugin 371 | 2.10.1 372 | 373 | 374 | attach-api-docs 375 | 376 | jar 377 | 378 | 379 | 380 | true 381 | 382 | 383 | org.apache.maven.plugins 384 | maven-source-plugin 385 | 2.1.2 386 | 387 | 388 | attach-sources 389 | 390 | jar-no-fork 391 | 392 | 393 | 394 | true 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | -------------------------------------------------------------------------------- /samza-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | com.stormpath.spring.boot.samza 9 | samza-spring-boot-starter-parent 10 | 0.2.3-SNAPSHOT 11 | ../pom.xml 12 | 13 | 14 | samza-api 15 | Samza Spring Boot :: Samza :: API 16 | 17 | 18 | 19 | org.apache.samza 20 | samza-api 21 | 22 | 23 | org.springframework 24 | spring-core 25 | 26 | 27 | 28 | 29 | org.slf4j 30 | jcl-over-slf4j 31 | test 32 | 33 | 34 | org.slf4j 35 | log4j-over-slf4j 36 | test 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /samza-api/samza-api.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /samza-api/src/main/java/com/stormpath/samza/serializers/SpringSerde.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.samza.serializers; 2 | 3 | import org.apache.samza.serializers.Serde; 4 | import org.springframework.core.serializer.Deserializer; 5 | import org.springframework.core.serializer.Serializer; 6 | import org.springframework.util.Assert; 7 | 8 | import java.io.ByteArrayInputStream; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.IOException; 11 | 12 | public class SpringSerde implements Serde { 13 | 14 | private final Serializer serializer; 15 | private final Deserializer deserializer; 16 | 17 | public SpringSerde(Serializer serializer, Deserializer deserializer) { 18 | Assert.notNull(serializer, "Serializer cannot be null."); 19 | Assert.notNull(deserializer, "Deserializer cannot be null."); 20 | this.serializer = serializer; 21 | this.deserializer = deserializer; 22 | } 23 | 24 | @Override 25 | public byte[] toBytes(T object) { 26 | if (object == null) { 27 | return null; 28 | } 29 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); 30 | try { 31 | serializer.serialize(object, stream); 32 | } catch (IOException e) { 33 | String msg = "Unable to serialize object [" + object + "]: " + e.getMessage(); 34 | throw new IllegalArgumentException(msg); 35 | } 36 | return stream.toByteArray(); 37 | } 38 | 39 | @Override 40 | public T fromBytes(byte[] bytes) { 41 | if (bytes == null || bytes.length == 0) { 42 | return null; 43 | } 44 | ByteArrayInputStream stream = new ByteArrayInputStream(bytes); 45 | try { 46 | return deserializer.deserialize(stream); 47 | } catch (IOException e) { 48 | String msg = "Unable to deserialize byte array of length " + bytes.length + ": " + e.getMessage(); 49 | throw new IllegalArgumentException(msg, e); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /samza-api/src/test/groovy/com/stormpath/samza/serializers/SpringSerdeTest.groovy: -------------------------------------------------------------------------------- 1 | package com.stormpath.samza.serializers 2 | 3 | import org.junit.Before 4 | import org.junit.Test 5 | import org.springframework.core.serializer.DefaultDeserializer 6 | import org.springframework.core.serializer.DefaultSerializer 7 | import org.springframework.core.serializer.Deserializer 8 | import org.springframework.core.serializer.Serializer; 9 | 10 | import static org.junit.Assert.* 11 | import static org.easymock.EasyMock.* 12 | 13 | class SpringSerdeTest { 14 | 15 | SpringSerde serde 16 | 17 | @Before 18 | void setUp() { 19 | serde = new SpringSerde(new DefaultSerializer(), new DefaultDeserializer()) 20 | } 21 | 22 | @Test 23 | void testToBytesWithNullObject() { 24 | assertNull serde.toBytes(null) 25 | } 26 | 27 | @Test 28 | void testFromBytesWithNullBytes() { 29 | assertNull serde.fromBytes(null) 30 | } 31 | 32 | @Test 33 | void testFromBytesWithEmptyBytes() { 34 | assertNull serde.fromBytes(new byte[0]) 35 | } 36 | 37 | @Test 38 | void testSerializationDeserialization() { 39 | byte[] bytes = serde.toBytes('foo') 40 | assertEquals 'foo', serde.fromBytes(bytes) 41 | } 42 | 43 | @Test(expected = IllegalArgumentException) 44 | void testToBytesWithIOException() { 45 | 46 | def serializer = createNiceMock(Serializer) 47 | serde = new SpringSerde(serializer, new DefaultDeserializer()) 48 | 49 | expect(serializer.serialize(eq('foo'), isA(OutputStream))).andThrow(new IOException('kapow')) 50 | replay serializer 51 | 52 | try { 53 | serde.toBytes('foo') 54 | } finally { 55 | verify serializer 56 | } 57 | } 58 | 59 | @Test(expected = IllegalArgumentException) 60 | void testFromBytesWithIOException() { 61 | 62 | def deserializer = createNiceMock(Deserializer) 63 | serde = new SpringSerde(new DefaultSerializer(), deserializer) 64 | 65 | expect(deserializer.deserialize(isA(InputStream))).andThrow(new IOException('boom!')) 66 | replay deserializer 67 | 68 | try { 69 | serde.fromBytes('foo'.getBytes('UTF-8')) 70 | } finally { 71 | verify deserializer 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | com.stormpath.spring.boot.samza 9 | samza-spring-boot-starter-parent 10 | 0.2.3-SNAPSHOT 11 | ../pom.xml 12 | 13 | 14 | samza-spring-boot-autoconfigure 15 | Samza Spring Boot :: Samza :: Autoconf 16 | 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-autoconfigure 21 | 22 | 23 | org.apache.samza 24 | samza-core_2.10 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-test 31 | 32 | 33 | org.slf4j 34 | jcl-over-slf4j 35 | 36 | 37 | org.slf4j 38 | log4j-over-slf4j 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/samza-spring-boot-autoconfigure.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/main/java/com/stormpath/spring/boot/samza/ConfigTimeCheckpointManagerFactory.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza; 2 | 3 | import org.apache.samza.checkpoint.CheckpointManager; 4 | import org.apache.samza.checkpoint.CheckpointManagerFactory; 5 | import org.apache.samza.config.Config; 6 | import org.apache.samza.metrics.MetricsRegistry; 7 | import org.springframework.util.Assert; 8 | 9 | public class ConfigTimeCheckpointManagerFactory implements CheckpointManagerFactory { 10 | 11 | private static CheckpointManagerFactory delegate; 12 | 13 | protected CheckpointManagerFactory getDelegate() { 14 | Assert.notNull(delegate, "Static delegate CheckpointManagerFactory cannot be null."); 15 | return delegate; 16 | } 17 | 18 | public static void setCheckpointManagerFactory(CheckpointManagerFactory factory) { 19 | ConfigTimeCheckpointManagerFactory.delegate = factory; 20 | } 21 | 22 | @Override 23 | public CheckpointManager getCheckpointManager(Config config, MetricsRegistry registry) { 24 | return getDelegate().getCheckpointManager(config, registry); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/main/java/com/stormpath/spring/boot/samza/ConfigTimeStreamTask.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza; 2 | 3 | import org.apache.samza.config.Config; 4 | import org.apache.samza.system.IncomingMessageEnvelope; 5 | import org.apache.samza.task.*; 6 | import org.springframework.beans.BeansException; 7 | import org.springframework.beans.factory.BeanInitializationException; 8 | import org.springframework.context.ApplicationContext; 9 | import org.springframework.util.Assert; 10 | 11 | public class ConfigTimeStreamTask implements StreamTask, InitableTask, WindowableTask, ClosableTask { 12 | 13 | private static ApplicationContext APPCTX; 14 | 15 | private StreamTask _delegate; 16 | 17 | private StreamTask getDelegate() { 18 | if (_delegate == null) { 19 | try { 20 | Assert.notNull(APPCTX, "static ApplicationContext cannot be null."); 21 | _delegate = APPCTX.getBean(StreamTask.class); 22 | } catch (BeansException e) { 23 | String msg = "Unable to acquire Samza StreamTask bean. If you enable the " + 24 | "Samza Spring Boot Plugin you must declare a prototype bean that implements the " + 25 | StreamTask.class.getCanonicalName() + " interface. It MUST be prototype-scoped."; 26 | throw new BeanInitializationException(msg, e); 27 | } 28 | } 29 | return _delegate; 30 | } 31 | 32 | public static void setApplicationContext(ApplicationContext appCtx) { 33 | ConfigTimeStreamTask.APPCTX = appCtx; 34 | } 35 | 36 | @Override 37 | public void init(Config config, TaskContext context) throws Exception { 38 | StreamTask task = getDelegate(); 39 | if (task instanceof InitableTask) { 40 | ((InitableTask) task).init(config, context); 41 | } 42 | } 43 | 44 | @Override 45 | public void process(IncomingMessageEnvelope envelope, MessageCollector collector, TaskCoordinator coordinator) throws Exception { 46 | getDelegate().process(envelope, collector, coordinator); 47 | 48 | } 49 | 50 | @Override 51 | public void window(MessageCollector collector, TaskCoordinator coordinator) throws Exception { 52 | StreamTask task = getDelegate(); 53 | if (task instanceof WindowableTask) { 54 | ((WindowableTask) task).window(collector, coordinator); 55 | } 56 | } 57 | 58 | @Override 59 | public void close() throws Exception { 60 | StreamTask task = getDelegate(); 61 | if (task instanceof ClosableTask) { 62 | ((ClosableTask) task).close(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/main/java/com/stormpath/spring/boot/samza/DisabledCheckpointManager.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza; 2 | 3 | import org.apache.samza.checkpoint.Checkpoint; 4 | import org.apache.samza.checkpoint.CheckpointManager; 5 | import org.apache.samza.container.TaskName; 6 | 7 | import java.util.Map; 8 | 9 | public class DisabledCheckpointManager implements CheckpointManager { 10 | 11 | @Override 12 | public void start() { 13 | } 14 | 15 | @Override 16 | public void register(TaskName taskName) { 17 | } 18 | 19 | @Override 20 | public void writeCheckpoint(TaskName taskName, Checkpoint checkpoint) { 21 | } 22 | 23 | @Override 24 | public Checkpoint readLastCheckpoint(TaskName taskName) { 25 | return null; 26 | } 27 | 28 | @Override 29 | public Map readChangeLogPartitionMapping() { 30 | return null; 31 | } 32 | 33 | @Override 34 | public void writeChangeLogPartitionMapping(Map mapping) { 35 | } 36 | 37 | @Override 38 | public void stop() { 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/main/java/com/stormpath/spring/boot/samza/FixedCheckpointManagerFactory.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza; 2 | 3 | import org.apache.samza.checkpoint.CheckpointManager; 4 | import org.apache.samza.checkpoint.CheckpointManagerFactory; 5 | import org.apache.samza.config.Config; 6 | import org.apache.samza.metrics.MetricsRegistry; 7 | import org.springframework.util.Assert; 8 | 9 | public class FixedCheckpointManagerFactory implements CheckpointManagerFactory { 10 | 11 | private final CheckpointManager checkpointManager; 12 | 13 | public FixedCheckpointManagerFactory(CheckpointManager checkpointManager) { 14 | Assert.notNull(checkpointManager, "CheckpointManager cannot be null."); 15 | this.checkpointManager = checkpointManager; 16 | } 17 | 18 | @Override 19 | public CheckpointManager getCheckpointManager(Config config, MetricsRegistry registry) { 20 | return checkpointManager; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/main/java/com/stormpath/spring/boot/samza/SamzaAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza; 2 | 3 | import com.stormpath.spring.context.StaticApplicationContextProvider; 4 | import org.apache.samza.checkpoint.CheckpointManager; 5 | import org.apache.samza.checkpoint.CheckpointManagerFactory; 6 | import org.apache.samza.config.Config; 7 | import org.apache.samza.config.JobConfig$; 8 | import org.apache.samza.config.MapConfig; 9 | import org.apache.samza.config.TaskConfig$; 10 | import org.apache.samza.container.SamzaContainer; 11 | import org.apache.samza.container.SamzaContainer$; 12 | import org.apache.samza.coordinator.JobCoordinator$; 13 | import org.apache.samza.job.StreamJob; 14 | import org.apache.samza.job.model.ContainerModel; 15 | import org.apache.samza.job.model.JobModel; 16 | import org.springframework.beans.factory.BeanInitializationException; 17 | import org.springframework.beans.factory.annotation.Autowired; 18 | import org.springframework.beans.factory.annotation.Value; 19 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 20 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 21 | import org.springframework.context.ApplicationContext; 22 | import org.springframework.context.annotation.Bean; 23 | import org.springframework.context.annotation.Configuration; 24 | import org.springframework.core.env.CompositePropertySource; 25 | import org.springframework.core.env.ConfigurableEnvironment; 26 | import org.springframework.core.env.EnumerablePropertySource; 27 | import org.springframework.core.env.PropertySource; 28 | import org.springframework.util.Assert; 29 | import org.springframework.util.StringUtils; 30 | 31 | import java.util.Arrays; 32 | import java.util.HashMap; 33 | import java.util.Map; 34 | import java.util.Set; 35 | import java.util.stream.Collectors; 36 | 37 | @Configuration 38 | @ConditionalOnProperty(name = "samza.enabled", matchIfMissing = true) 39 | public class SamzaAutoConfiguration { 40 | 41 | protected static final String SAMZA_PROPERTY_PREFIX = "samza."; 42 | 43 | @Autowired 44 | private ConfigurableEnvironment configurableEnvironment; 45 | 46 | @Autowired 47 | private ApplicationContext applicationContext; 48 | 49 | @Value("#{ @environment['samza.container.count'] ?: 1 }") 50 | private int samzaContainerCount; //only used for static configuration of the number of job instances 51 | 52 | @Value("#{ @environment['samza.container.id'] ?: 0 }") 53 | private int samzaContainerId; 54 | 55 | @Value("#{ @environment['samza.job.name'] ?: (@environment['spring.application.name'] ?: '') }") 56 | private String samzaJobName; 57 | 58 | @Value("#{ @environment['samza.job.thread.name'] ?: null }") 59 | private String samzaJobThreadName; 60 | 61 | @Value("#{ @environment['samza.job.phase'] ?: 0 }") 62 | private int samzaJobPhase = 0; 63 | 64 | @Value("#{ @environment['samza.job.startWaitMillis'] ?: 2000 }") 65 | private long samzaJobStartWaitMillis = 2000; 66 | 67 | @Value("#{ @environment['samza.job.stopWaitMillis'] ?: 1000 }") 68 | private long samzaJobStopWaitMillis = 1000; 69 | 70 | @Bean 71 | public Map samzaConfigurationProperties() { 72 | Map props = new HashMap<>(); 73 | findPropertyNamesStartingWith(configurableEnvironment, SAMZA_PROPERTY_PREFIX).stream() 74 | .forEach(key -> { 75 | String value = configurableEnvironment.getProperty(key); 76 | String unprefixed = key.substring(SAMZA_PROPERTY_PREFIX.length()); 77 | props.put(unprefixed, value); 78 | }); 79 | return props; 80 | } 81 | 82 | @Bean 83 | @ConditionalOnMissingBean 84 | public CheckpointManager samzaCheckpointManager() { 85 | return new DisabledCheckpointManager(); 86 | } 87 | 88 | @Bean 89 | @ConditionalOnMissingBean 90 | public Config samzaConfig() { 91 | 92 | //useful for various Samza factory implementations until they are 100% spring configurable: 93 | StaticApplicationContextProvider.setApplicationContext(applicationContext); 94 | 95 | CheckpointManagerFactory factory = null; 96 | 97 | CheckpointManager manager = samzaCheckpointManager(); 98 | 99 | //don't overwrite the original values: 100 | Map props = new HashMap<>(); 101 | props.putAll(samzaConfigurationProperties()); 102 | 103 | String key = JobConfig$.MODULE$.STREAM_JOB_FACTORY_CLASS(); 104 | String value = props.get(key); 105 | if (StringUtils.hasLength(value)) { 106 | String msg = "The '" + key + "' property is not supported by the Samza Spring Boot Starter. " + 107 | "Define a StreamJob bean instead."; 108 | throw new BeanInitializationException(msg); 109 | } 110 | 111 | Assert.hasText(samzaJobName, "samza.job.name or spring.application.name must be defined."); 112 | props.put(JobConfig$.MODULE$.JOB_NAME(), samzaJobName); 113 | 114 | key = TaskConfig$.MODULE$.TASK_CLASS(); 115 | value = props.get(key); 116 | if (StringUtils.hasLength(value)) { 117 | String msg = "The '" + key + "' property is not supported by the Samza Spring Boot Starter. " + 118 | "Define a prototype-scoped StreamTask bean instead. It MUST be prototype-scoped."; 119 | throw new BeanInitializationException(msg); 120 | } 121 | ConfigTimeStreamTask.setApplicationContext(applicationContext); 122 | props.put(key, ConfigTimeStreamTask.class.getCanonicalName()); 123 | 124 | //Ensure Spring-configured CheckpointManagerFactory or CheckpointManager is used: 125 | key = TaskConfig$.MODULE$.CHECKPOINT_MANAGER_FACTORY(); 126 | if (!props.containsKey(key)) { 127 | 128 | if (/*factory == null &&*/ manager != null && (!(manager instanceof DisabledCheckpointManager))) { 129 | factory = new FixedCheckpointManagerFactory(manager); 130 | } 131 | 132 | if (factory != null) { 133 | ConfigTimeCheckpointManagerFactory.setCheckpointManagerFactory(factory); 134 | String className = ConfigTimeCheckpointManagerFactory.class.getCanonicalName(); 135 | props.put(key, className); 136 | } 137 | } 138 | 139 | return new MapConfig(props); 140 | } 141 | 142 | @Bean 143 | @ConditionalOnMissingBean(name = "samzaContainerCount") 144 | public int samzaContainerCount() { 145 | Assert.isTrue(samzaContainerCount > 0, "samza.container.count must be a positive integer (greater than zero)."); 146 | return samzaContainerCount; //TODO enable Zookeeper supplier to avoid YARN messiness 147 | } 148 | 149 | @Bean 150 | @ConditionalOnMissingBean(name = "samzaContainerId") 151 | public int samzaContainerId() { 152 | Assert.isTrue(samzaContainerId >= 0, "samza.container.id must be a non-negative integer (0 or greater)"); 153 | return samzaContainerId; //will be overwritten if zookeeper is enabled 154 | } 155 | 156 | @Bean 157 | @ConditionalOnMissingBean 158 | public JobModel samzaJobModel() { 159 | Config samzaConfig = samzaConfig(); 160 | 161 | int count = samzaContainerCount(); 162 | Assert.isTrue(count > 0, "samzaContainerCount must be a positive integer (greater than zero)."); 163 | 164 | return JobCoordinator$.MODULE$.buildJobModel(samzaConfig, count); 165 | } 166 | 167 | @Bean 168 | @ConditionalOnMissingBean 169 | public SamzaContainer samzaContainer() { 170 | 171 | JobModel jobModel = samzaJobModel(); 172 | 173 | int containerId = samzaContainerId(); 174 | Assert.isTrue(containerId >= 0, "samzaContainerId must be a non-negative integer (0 or greater)."); 175 | 176 | Map containers = jobModel.getContainers(); 177 | ContainerModel containerModel = containers.get(containerId); 178 | if (containerModel == null) { 179 | String msg = "Container model does not exist for samza container id '" + containerId + "'. " + 180 | "Ensure that samzaContainerId is a zero-based integer less than the total number " + 181 | "of containers for the job. Number of containers in the model: " + containers.size(); 182 | throw new BeanInitializationException(msg); 183 | } 184 | 185 | return SamzaContainer$.MODULE$.apply(containerModel, jobModel); 186 | } 187 | 188 | @Bean 189 | @ConditionalOnMissingBean 190 | public StreamJob samzaJob() { 191 | 192 | SamzaContainer container = samzaContainer(); 193 | 194 | SpringThreadJob job = new SpringThreadJob(container); 195 | 196 | if (samzaJobThreadName != null) { 197 | job.setThreadName(samzaJobThreadName); 198 | } 199 | 200 | job.setPhase(samzaJobPhase); 201 | job.setStartWaitMillis(samzaJobStartWaitMillis); 202 | job.setStopWaitMillis(samzaJobStopWaitMillis); 203 | 204 | return job; 205 | } 206 | 207 | protected static Set findPropertyNamesStartingWith(ConfigurableEnvironment env, String prefix) { 208 | return getAllProperties(env).keySet().stream() 209 | .filter(key -> key.startsWith(prefix)) 210 | .collect(Collectors.toSet()); 211 | } 212 | 213 | protected static Map getAllProperties(ConfigurableEnvironment aEnv) { 214 | Map result = new HashMap<>(); 215 | aEnv.getPropertySources().forEach(ps -> addAll(result, getAllProperties(ps))); 216 | return result; 217 | } 218 | 219 | protected static Map getAllProperties(PropertySource aPropSource) { 220 | Map result = new HashMap<>(); 221 | 222 | if (aPropSource instanceof CompositePropertySource) { 223 | CompositePropertySource cps = (CompositePropertySource) aPropSource; 224 | cps.getPropertySources().forEach(ps -> addAll(result, getAllProperties(ps))); 225 | return result; 226 | } 227 | 228 | if (aPropSource instanceof EnumerablePropertySource) { 229 | EnumerablePropertySource ps = (EnumerablePropertySource) aPropSource; 230 | Arrays.asList(ps.getPropertyNames()).forEach(key -> result.put(key, ps.getProperty(key))); 231 | return result; 232 | } 233 | 234 | return result; 235 | } 236 | 237 | private static void addAll(Map aBase, Map aToBeAdded) { 238 | for (Map.Entry entry : aToBeAdded.entrySet()) { 239 | if (aBase.containsKey(entry.getKey())) { 240 | continue; 241 | } 242 | aBase.put(entry.getKey(), entry.getValue()); 243 | } 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/main/java/com/stormpath/spring/boot/samza/SpringThreadJob.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza; 2 | 3 | import org.apache.samza.container.RunLoop; 4 | import org.apache.samza.container.SamzaContainer; 5 | import org.apache.samza.job.ApplicationStatus; 6 | import org.apache.samza.job.StreamJob; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.BeansException; 10 | import org.springframework.beans.factory.InitializingBean; 11 | import org.springframework.context.ApplicationContext; 12 | import org.springframework.context.ApplicationContextAware; 13 | import org.springframework.context.SmartLifecycle; 14 | import org.springframework.util.Assert; 15 | import org.springframework.util.ReflectionUtils; 16 | 17 | import java.lang.reflect.Field; 18 | 19 | public class SpringThreadJob implements StreamJob, InitializingBean, ApplicationContextAware, SmartLifecycle { 20 | 21 | private static final Logger log = LoggerFactory.getLogger(SpringThreadJob.class); 22 | 23 | private final Runnable samzaContainer; 24 | private Thread thread = null; 25 | private volatile ApplicationStatus status; 26 | private volatile boolean interrupting = false; 27 | 28 | private int phase = 0; 29 | private String threadName = getClass().getSimpleName(); 30 | private long startWaitMillis = 2000; 31 | private long stopWaitMillis = 1000; 32 | 33 | private ApplicationContext applicationContext; 34 | 35 | public SpringThreadJob(Runnable samzaContainer) { 36 | Assert.notNull(samzaContainer, "SamzaContainer Runnable argument cannot be null."); 37 | this.samzaContainer = samzaContainer; 38 | } 39 | 40 | public void setPhase(int phase) { 41 | this.phase = phase; 42 | } 43 | 44 | public String getThreadName() { 45 | return threadName; 46 | } 47 | 48 | public void setThreadName(String threadName) { 49 | this.threadName = threadName; 50 | } 51 | 52 | public long getStartWaitMillis() { 53 | return startWaitMillis; 54 | } 55 | 56 | public void setStartWaitMillis(long startWaitMillis) { 57 | this.startWaitMillis = startWaitMillis; 58 | } 59 | 60 | public long getStopWaitMillis() { 61 | return stopWaitMillis; 62 | } 63 | 64 | public void setStopWaitMillis(long stopWaitMillis) { 65 | this.stopWaitMillis = stopWaitMillis; 66 | } 67 | 68 | @Override 69 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 70 | this.applicationContext = applicationContext; 71 | } 72 | 73 | @Override 74 | public void afterPropertiesSet() throws Exception { 75 | Assert.isTrue(startWaitMillis >= 0, "startWaitMillis must be greater than or equal to zero."); 76 | Assert.isTrue(stopWaitMillis >= 0, "stopWaitMillis must be greater than or equal to zero."); 77 | Assert.hasText(threadName, "threadName cannot be null or empty."); 78 | Assert.notNull(applicationContext, "applicationContext cannot be null."); 79 | } 80 | 81 | @Override 82 | public boolean isAutoStartup() { 83 | return true; 84 | } 85 | 86 | @Override 87 | public void stop(Runnable runnable) { 88 | try { 89 | stop(); 90 | } finally { 91 | runnable.run(); 92 | } 93 | } 94 | 95 | @Override 96 | public void start() { 97 | 98 | doStart(); 99 | 100 | log.debug("Starting Samza container thread..."); 101 | 102 | ApplicationStatus status = this.status; 103 | 104 | if (startWaitMillis > 0) { 105 | status = waitForStatus(ApplicationStatus.Running, startWaitMillis); 106 | } 107 | 108 | if (status != ApplicationStatus.Running) { 109 | String msg = "Unable to start Samza container thread successfully within " + startWaitMillis + 110 | " milliseconds. Status: " + status; 111 | throw new IllegalStateException(msg); 112 | } 113 | 114 | log.info("Started Samza container thread: {}", status); 115 | } 116 | 117 | private void doStart() { 118 | 119 | status = ApplicationStatus.New; 120 | 121 | thread = new Thread() { 122 | @Override 123 | public void run() { 124 | try { 125 | samzaContainer.run(); 126 | status = ApplicationStatus.SuccessfulFinish; 127 | } catch (Exception e) { 128 | log.error("Samza container startup failed due to exception: " + e.getMessage(), e); 129 | status = ApplicationStatus.UnsuccessfulFinish; 130 | } 131 | } 132 | }; 133 | 134 | thread.setName(threadName); 135 | thread.start(); 136 | 137 | status = ApplicationStatus.Running; 138 | } 139 | 140 | @Override 141 | public void stop() { 142 | log.debug("Stopping Samza container..."); 143 | kill(); 144 | if (stopWaitMillis > 0) { 145 | waitForFinish(stopWaitMillis); 146 | } 147 | log.info("Stopped Samza container."); 148 | } 149 | 150 | @Override 151 | public boolean isRunning() { 152 | return status == ApplicationStatus.Running; 153 | } 154 | 155 | @Override 156 | public int getPhase() { 157 | return this.phase; 158 | } 159 | 160 | @Override 161 | public StreamJob submit() { 162 | start(); 163 | return this; 164 | } 165 | 166 | @Override 167 | public StreamJob kill() { 168 | 169 | try { 170 | invokeShutdownNow(); 171 | } catch (Exception e) { 172 | throw new IllegalStateException("Unable to set samzaContainer.runLoop.shutdownNow = true", e); 173 | } 174 | 175 | return this; 176 | } 177 | 178 | private void invokeShutdownNow() { 179 | try { 180 | Field field = ReflectionUtils.findField(SamzaContainer.class, "runLoop"); 181 | ReflectionUtils.makeAccessible(field); 182 | final Object runLoopObject = field.get(samzaContainer); 183 | 184 | ReflectionUtils.doWithFields(RunLoop.class, aField -> { 185 | ReflectionUtils.makeAccessible(aField); 186 | aField.setBoolean(runLoopObject, true); 187 | }, aField -> aField.getName().endsWith("shutdownNow")); 188 | } catch (Exception e) { 189 | throw new IllegalStateException("Cannot set samzaContainer.runLoop.shutdownNow field", e); 190 | } 191 | } 192 | 193 | @Override 194 | public ApplicationStatus waitForFinish(long timeoutMs) { 195 | 196 | Assert.isTrue(timeoutMs > 0, "timeoutMs must be greater than zero."); 197 | 198 | try { 199 | thread.join(timeoutMs); 200 | } catch (InterruptedException e) { 201 | throw new IllegalStateException("waitForFinish interrupted.", e); 202 | } 203 | 204 | return status; 205 | } 206 | 207 | @Override 208 | public ApplicationStatus waitForStatus(ApplicationStatus status, long timeoutMs) { 209 | 210 | Assert.isTrue(timeoutMs > 0, "timeoutMs must be greater than zero."); 211 | 212 | long start = System.currentTimeMillis(); 213 | 214 | while (System.currentTimeMillis() - start < timeoutMs && !status.equals(this.status)) { 215 | try { 216 | Thread.sleep(500); 217 | } catch (InterruptedException e) { 218 | throw new IllegalStateException("waitForStatus interrupted.", e); 219 | } 220 | } 221 | 222 | return this.status; 223 | } 224 | 225 | @Override 226 | public ApplicationStatus getStatus() { 227 | return this.status; 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/main/java/com/stormpath/spring/context/StaticApplicationContextProvider.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.context; 2 | 3 | import org.springframework.context.ApplicationContext; 4 | 5 | public class StaticApplicationContextProvider { 6 | 7 | private static ApplicationContext applicationContext; 8 | 9 | public static ApplicationContext getApplicationContext() { 10 | return applicationContext; 11 | } 12 | 13 | public static void setApplicationContext(ApplicationContext applicationContext) { 14 | StaticApplicationContextProvider.applicationContext = applicationContext; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.stormpath.spring.boot.samza.SamzaAutoConfiguration -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/test/groovy/com/stormpath/spring/boot/samza/MemorySystemConsumer.groovy: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza 2 | 3 | import org.apache.samza.system.IncomingMessageEnvelope 4 | import org.apache.samza.system.OutgoingMessageEnvelope 5 | import org.apache.samza.system.SystemConsumer 6 | import org.apache.samza.system.SystemStreamPartition 7 | 8 | import java.util.concurrent.LinkedBlockingQueue 9 | 10 | class MemorySystemConsumer implements SystemConsumer { 11 | 12 | private final MemorySystemProducer producer; 13 | 14 | public MemorySystemConsumer(MemorySystemProducer producer) { 15 | this.producer = producer; 16 | } 17 | 18 | @Override 19 | void start() { 20 | } 21 | 22 | @Override 23 | void stop() { 24 | } 25 | 26 | @Override 27 | void register(SystemStreamPartition systemStreamPartition, String offset) { 28 | } 29 | 30 | @Override 31 | Map> poll(Set systemStreamPartitions, long timeout) throws InterruptedException { 32 | 33 | Map> found = new HashMap<>(); 34 | 35 | for(SystemStreamPartition ssp : systemStreamPartitions) { 36 | 37 | String stream = ssp.getStream() 38 | 39 | LinkedBlockingQueue queue = producer.queues.get(stream) 40 | 41 | List messages = new ArrayList<>(); 42 | 43 | if (queue != null) { 44 | 45 | OutgoingMessageEnvelope omsg; 46 | 47 | while((omsg = queue.poll()) != null) { 48 | IncomingMessageEnvelope imsg = 49 | new IncomingMessageEnvelope(ssp, null, omsg.getKey(), omsg.getMessage()); 50 | messages.add(imsg); 51 | } 52 | } 53 | 54 | found.put(ssp, messages); 55 | } 56 | 57 | return found; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/test/groovy/com/stormpath/spring/boot/samza/MemorySystemFactory.groovy: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza 2 | 3 | import org.apache.samza.config.Config 4 | import org.apache.samza.metrics.MetricsRegistry 5 | import org.apache.samza.system.SystemAdmin 6 | import org.apache.samza.system.SystemConsumer 7 | import org.apache.samza.system.SystemFactory 8 | import org.apache.samza.system.SystemProducer 9 | import org.apache.samza.util.SinglePartitionWithoutOffsetsSystemAdmin 10 | 11 | /** 12 | * A Samza SystemFactory implementation that just uses memory - for testing only. 13 | */ 14 | class MemorySystemFactory implements SystemFactory { 15 | 16 | private MemorySystemConsumer consumer; 17 | private MemorySystemProducer producer; 18 | 19 | public MemorySystemFactory() { 20 | this.producer = new MemorySystemProducer(); 21 | this.consumer = new MemorySystemConsumer(this.producer); 22 | } 23 | 24 | @Override 25 | SystemConsumer getConsumer(String systemName, Config config, MetricsRegistry registry) { 26 | return this.consumer; 27 | } 28 | 29 | @Override 30 | SystemProducer getProducer(String systemName, Config config, MetricsRegistry registry) { 31 | return this.producer 32 | } 33 | 34 | @Override 35 | SystemAdmin getAdmin(String systemName, Config config) { 36 | return new SinglePartitionWithoutOffsetsSystemAdmin(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/test/groovy/com/stormpath/spring/boot/samza/MemorySystemProducer.groovy: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza 2 | 3 | import org.apache.samza.system.OutgoingMessageEnvelope 4 | import org.apache.samza.system.SystemProducer 5 | 6 | import java.util.concurrent.LinkedBlockingQueue 7 | 8 | class MemorySystemProducer implements SystemProducer { 9 | 10 | public final Map> queues = new HashMap<>(); 11 | 12 | @Override 13 | void start() { 14 | 15 | } 16 | 17 | @Override 18 | void stop() { 19 | 20 | } 21 | 22 | @Override 23 | void register(String source) { 24 | this.queues.put(source, new LinkedBlockingQueue<>()); 25 | } 26 | 27 | @Override 28 | void send(String source, OutgoingMessageEnvelope envelope) { 29 | this.queues.get(source).offer(envelope); 30 | } 31 | 32 | @Override 33 | void flush(String source) { 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/test/groovy/com/stormpath/spring/boot/samza/SamzaConfigurationIT.groovy: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza 2 | 3 | import org.apache.samza.container.SamzaContainer 4 | import org.junit.Test 5 | import org.junit.runner.RunWith 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.boot.test.SpringApplicationConfiguration 8 | import org.springframework.test.context.TestPropertySource 9 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner 10 | 11 | import static org.junit.Assert.assertNotNull 12 | 13 | @RunWith(SpringJUnit4ClassRunner.class) 14 | @SpringApplicationConfiguration(classes=[SamzaAutoConfiguration, TestTaskConfiguration]) 15 | @TestPropertySource("classpath:com/stormpath/spring/boot/samza/application.properties") 16 | class SamzaConfigurationIT { 17 | 18 | @Autowired 19 | private SamzaContainer samzaContainer; 20 | 21 | @Test 22 | void testThreadJob() { 23 | assertNotNull samzaContainer 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/test/groovy/com/stormpath/spring/boot/samza/TestTask.groovy: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza 2 | 3 | import org.apache.samza.config.Config 4 | import org.apache.samza.system.IncomingMessageEnvelope 5 | import org.apache.samza.task.* 6 | import org.slf4j.Logger 7 | import org.slf4j.LoggerFactory 8 | 9 | class TestTask implements StreamTask, InitableTask { 10 | 11 | private static final Logger log = LoggerFactory.getLogger(TestTask.class); 12 | 13 | @Override 14 | public void init(Config config, TaskContext taskContext) throws Exception { 15 | log.info("init config: {}", config); 16 | log.info("init taskContext: {}", taskContext); 17 | } 18 | 19 | @Override 20 | public void process(IncomingMessageEnvelope envelope, MessageCollector messageCollector, TaskCoordinator taskCoordinator) throws Exception { 21 | log.info("Received incoming message envelope: {}", envelope); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/test/groovy/com/stormpath/spring/boot/samza/TestTaskConfiguration.groovy: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza 2 | 3 | import org.apache.samza.task.StreamTask 4 | import org.springframework.context.annotation.Bean 5 | import org.springframework.context.annotation.Configuration 6 | import org.springframework.context.annotation.Scope 7 | 8 | @Configuration 9 | class TestTaskConfiguration { 10 | 11 | @Bean 12 | @Scope("prototype") 13 | public StreamTask samzaStreamTask() { 14 | return new TestTask(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/test/resources/com/stormpath/spring/boot/samza/application.properties: -------------------------------------------------------------------------------- 1 | # suppress inspection "UnusedProperty" for whole file 2 | # 3 | # Copyright (c) 2016 Stormpath, Inc. All rights reserved. 4 | 5 | spring.application.name=spring-boot-test 6 | 7 | # Task 8 | samza.task.inputs=memory.foo 9 | 10 | # Systems 11 | samza.systems.memory.samza.factory=com.stormpath.spring.boot.samza.MemorySystemFactory 12 | -------------------------------------------------------------------------------- /samza-spring-boot-autoconfigure/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 22 | 23 | %date %-5level [%thread] %logger{36} %m%n 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /samza-spring-boot-starter-parent.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /samza-spring-boot-starter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | com.stormpath.spring.boot.samza 9 | samza-spring-boot-starter-parent 10 | 0.2.3-SNAPSHOT 11 | ../pom.xml 12 | 13 | 14 | samza-spring-boot-starter 15 | Samza Spring Boot :: Starter 16 | 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter 21 | 22 | 23 | com.stormpath.spring.boot.samza 24 | samza-spring-boot-autoconfigure 25 | 26 | 27 | com.stormpath.spring.boot.samza 28 | samza-zookeeper-spring-boot-autoconfigure 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /samza-spring-boot-starter/samza-spring-boot-starter.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /samza-spring-boot-starter/src/main/resources/META-INF/spring.provides: -------------------------------------------------------------------------------- 1 | provides=samza -------------------------------------------------------------------------------- /samza-zookeeper-spring-boot-autoconfigure/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | com.stormpath.spring.boot.samza 9 | samza-spring-boot-starter-parent 10 | 0.2.3-SNAPSHOT 11 | ../pom.xml 12 | 13 | 14 | samza-zookeeper-spring-boot-autoconfigure 15 | Samza Spring Boot :: Samza :: Zookeeper :: Autoconf 16 | 17 | 18 | 19 | com.stormpath.spring.boot.samza 20 | samza-spring-boot-autoconfigure 21 | 22 | 23 | com.stormpath.spring.boot.samza 24 | additional-curator-recipes 25 | 26 | 27 | com.stormpath.spring.boot.samza 28 | samza-zookeeper 29 | 30 | 31 | 32 | 33 | org.slf4j 34 | jcl-over-slf4j 35 | test 36 | 37 | 38 | org.slf4j 39 | log4j-over-slf4j 40 | test 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /samza-zookeeper-spring-boot-autoconfigure/samza-zookeeper-spring-boot-autoconfigure.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /samza-zookeeper-spring-boot-autoconfigure/src/main/java/com/stormpath/spring/boot/samza/curator/CuratorSamzaAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza.curator; 2 | 3 | import com.stormpath.curator.framework.recipes.nodes.SequentialGroupMember; 4 | import org.apache.curator.framework.CuratorFramework; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.beans.factory.annotation.Qualifier; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.boot.autoconfigure.AutoConfigureOrder; 9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 10 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | import org.springframework.util.Assert; 14 | 15 | @Configuration 16 | @ConditionalOnProperty(name = {"samza.enabled", "spring.cloud.zookeeper.enabled", "samza.zookeeper.enabled"}, matchIfMissing = true) 17 | @AutoConfigureOrder(1) 18 | public class CuratorSamzaAutoConfiguration { 19 | 20 | private static final byte[] EMPTY_PAYLOAD = new byte[0]; 21 | 22 | @SuppressWarnings("SpringJavaAutowiringInspection") 23 | @Autowired 24 | private CuratorFramework curator; //should be pulled in by configuring the spring-cloud-zookeeper-core artifact 25 | 26 | @Value("#{ @environment['samza.job.name'] ?: (@environment['spring.application.name'] ?: null) }") 27 | private String samzaJobName; 28 | 29 | @Value("#{ @environment['samza.zookeeper.containers.namespace.prefix'] ?: (@environment['samza.zookeper.jobs.namespace'] ?: '/samza/jobs') }") 30 | private String samzaContainerMembershipPathPrefix; 31 | 32 | @Value("#{ @environment['samza.zookeeper.containers.namespace.suffix'] ?: '/containers' }") 33 | private String samzaContainerMembershipPathSuffix; 34 | 35 | @Bean 36 | @ConditionalOnMissingBean(name = "samzaContainerMembershipPath") 37 | public String samzaContainerMembershipPath() { 38 | Assert.hasText(samzaJobName, "samza.job.name or spring.application.name must be defined."); 39 | Assert.hasText(samzaContainerMembershipPathPrefix, 40 | "samza.zookeeper.containers.namespace.prefix cannot be a null or empty string."); 41 | Assert.hasText(samzaContainerMembershipPathSuffix, 42 | "samza.zookeeper.containers.namespace.suffix cannot be a null or empty string."); 43 | 44 | String val = samzaContainerMembershipPathPrefix; 45 | if (!val.endsWith("/")) { 46 | val += "/"; 47 | } 48 | val += samzaJobName; 49 | if (!samzaContainerMembershipPathSuffix.startsWith("/")) { 50 | val += "/"; 51 | } 52 | val += samzaContainerMembershipPathSuffix; 53 | 54 | return val; 55 | } 56 | 57 | @Bean(initMethod = "start", destroyMethod = "close") 58 | @ConditionalOnMissingBean(name = "samzaContainerGroupMember") 59 | public SequentialGroupMember samzaContainerGroupMember() { 60 | String membersBasePath = samzaContainerMembershipPath(); 61 | String locksBasePath = membersBasePath + "-locks"; 62 | return new SequentialGroupMember(curator, membersBasePath, locksBasePath, EMPTY_PAYLOAD); 63 | } 64 | 65 | @Bean 66 | @ConditionalOnMissingBean(name = "samzaContainerCount") 67 | public int samzaContainerId() { 68 | SequentialGroupMember member = samzaContainerGroupMember(); 69 | return member.getId(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /samza-zookeeper-spring-boot-autoconfigure/src/main/java/com/stormpath/spring/boot/samza/curator/checkpoint/ZookeeperCheckpointAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.spring.boot.samza.curator.checkpoint; 2 | 3 | import com.stormpath.samza.curator.checkpoint.ZookeeperCheckpointManager; 4 | import org.apache.curator.framework.CuratorFramework; 5 | import org.apache.samza.checkpoint.CheckpointManager; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.boot.autoconfigure.AutoConfigureOrder; 9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 10 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | 14 | @Configuration 15 | @ConditionalOnProperty(name = {"samza.enabled", "spring.cloud.zookeeper.enabled", "samza.zookeeper.enabled", "samza.zookeeper.checkpointManager.enabled"}, matchIfMissing = true) 16 | @AutoConfigureOrder(10) 17 | public class ZookeeperCheckpointAutoConfiguration { 18 | 19 | @Autowired 20 | private CuratorFramework curator; 21 | 22 | @Value("#{@environment['samza.zookeper.jobs.namespace'] ?: '/samza/jobs'}") 23 | private String jobsNamespace; 24 | 25 | @Value("#{ @environment['samza.job.name'] ?: (@environment['spring.application.name'] ?: null) }") 26 | private String samzaJobName; 27 | 28 | @Bean 29 | @ConditionalOnMissingBean(name = "samzaJobZookeeperPath") 30 | public String samzaJobZookeeperPath() { 31 | return jobsNamespace + "/" + samzaJobName; 32 | } 33 | 34 | @Bean 35 | //do not specify the init/destroy methods here - the SamzaContainer instance calls these methods when necessary 36 | @ConditionalOnMissingBean 37 | public CheckpointManager samzaCheckpointManager() { 38 | String jobPath = samzaJobZookeeperPath(); 39 | return new ZookeeperCheckpointManager(curator, jobPath); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /samza-zookeeper-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | com.stormpath.spring.boot.samza.curator.CuratorSamzaAutoConfiguration,\ 3 | com.stormpath.spring.boot.samza.curator.checkpoint.ZookeeperCheckpointAutoConfiguration -------------------------------------------------------------------------------- /samza-zookeeper/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | com.stormpath.spring.boot.samza 9 | samza-spring-boot-starter-parent 10 | 0.2.3-SNAPSHOT 11 | ../pom.xml 12 | 13 | 14 | samza-zookeeper 15 | Samza Spring Boot :: Samza :: Zookeeper 16 | 17 | 18 | 19 | org.apache.curator 20 | curator-recipes 21 | 22 | 23 | org.apache.samza 24 | samza-core_2.10 25 | 26 | 27 | 28 | 29 | org.slf4j 30 | jcl-over-slf4j 31 | test 32 | 33 | 34 | org.slf4j 35 | log4j-over-slf4j 36 | test 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /samza-zookeeper/samza-zookeeper.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /samza-zookeeper/src/main/java/com/stormpath/samza/curator/checkpoint/ZookeeperCheckpointManager.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.samza.curator.checkpoint; 2 | 3 | import com.stormpath.samza.lang.Assert; 4 | import org.apache.curator.framework.CuratorFramework; 5 | import org.apache.curator.framework.api.transaction.CuratorTransaction; 6 | import org.apache.curator.framework.api.transaction.CuratorTransactionFinal; 7 | import org.apache.samza.SamzaException; 8 | import org.apache.samza.checkpoint.Checkpoint; 9 | import org.apache.samza.checkpoint.CheckpointManager; 10 | import org.apache.samza.container.TaskName; 11 | import org.apache.samza.serializers.CheckpointSerde; 12 | import org.apache.zookeeper.KeeperException; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | import java.nio.ByteBuffer; 17 | import java.util.*; 18 | 19 | public class ZookeeperCheckpointManager implements CheckpointManager { 20 | 21 | private static final Logger log = LoggerFactory.getLogger(ZookeeperCheckpointManager.class); 22 | 23 | private static final byte[] EMPTY_BYTES = new byte[0]; 24 | private static final CheckpointSerde CHECKPOINT_SERDE = new CheckpointSerde(); 25 | 26 | private final String tasksPath; 27 | private final Set registeredTaskNames = new HashSet<>(); 28 | private final CuratorFramework curator; 29 | 30 | public ZookeeperCheckpointManager(CuratorFramework curator, String jobPath) { 31 | Assert.hasText(jobPath, "jobPath cannot be null or empty."); 32 | this.tasksPath = jobPath + "/tasks"; 33 | this.curator = Assert.notNull(curator, "Curator cannot be null."); 34 | } 35 | 36 | @Override 37 | public void start() { 38 | log.debug("Starting {}...", getClass().getSimpleName()); 39 | try { 40 | doStart(); 41 | log.info("Started {}", getClass().getSimpleName()); 42 | } catch (Exception e) { 43 | String msg = "Unable to start " + getClass().getSimpleName() + ": " + e.getMessage(); 44 | throw new SamzaException(msg, e); 45 | } 46 | } 47 | 48 | private void doStart() throws Exception { 49 | 50 | //ensure base path node exists: 51 | try { 52 | String result = curator.create().creatingParentsIfNeeded().forPath(tasksPath, EMPTY_BYTES); 53 | log.info("Created tasks node {}", result); 54 | } catch (KeeperException.NodeExistsException e) { 55 | log.info("Tasks node already exists: {}", tasksPath); 56 | log.trace("Exception details: ", e); 57 | } 58 | 59 | //can be empty if start is being called for changelog partition number duty. Samza does not 60 | //register task names until *after* changelog partition number registrations are reported 61 | // (at which point it will call stop, register task names and then call start again 62 | // and this collection will be non-empty): 63 | if (registeredTaskNames.isEmpty()) { 64 | return; 65 | } 66 | 67 | log.info("Ensuring checkpoint nodes exist for registeredTaskNames: {}", registeredTaskNames); 68 | for (TaskName tn : registeredTaskNames) { 69 | 70 | String checkpointPath = getCheckpointPath(tn); 71 | try { 72 | String result = curator.create().creatingParentsIfNeeded().forPath(checkpointPath, EMPTY_BYTES); 73 | log.info("Created checkpoint node {}", result); 74 | } catch (KeeperException.NodeExistsException e) { 75 | log.info("Checkpoint node already exists: {}", checkpointPath); 76 | log.trace("Exception details: ", e); 77 | } 78 | } 79 | } 80 | 81 | @Override 82 | public void register(TaskName taskName) { 83 | registeredTaskNames.add(taskName); 84 | log.info("Registered TaskName '{}' for checkpoint management", taskName); 85 | } 86 | 87 | protected String getCheckpointPath(TaskName tn) { 88 | return tasksPath + "/" + tn.getTaskName() + "/" + "checkpoint"; 89 | } 90 | 91 | protected String getChangelogPartitionNumberPath(TaskName tn) { 92 | return tasksPath + "/" + tn.getTaskName() + "/" + "changelogPartitionNumber"; 93 | } 94 | 95 | @Override 96 | public void writeCheckpoint(TaskName taskName, Checkpoint checkpoint) { 97 | try { 98 | log.info("Writing Task {} {}", taskName, checkpoint); 99 | doWriteCheckpoint(taskName, checkpoint); 100 | } catch (Exception e) { 101 | String msg = "Unable to write checkpoint " + checkpoint + " for taskName " + taskName + ": " + e.getMessage(); 102 | throw new SamzaException(msg, e); 103 | } 104 | } 105 | 106 | protected void doWriteCheckpoint(TaskName tn, Checkpoint checkpoint) throws Exception { 107 | String checkpointPath = getCheckpointPath(tn); 108 | byte[] serialized = CHECKPOINT_SERDE.toBytes(checkpoint); 109 | curator.setData().forPath(checkpointPath, serialized); 110 | } 111 | 112 | @Override 113 | public Checkpoint readLastCheckpoint(TaskName taskName) { 114 | try { 115 | Checkpoint checkpoint = doReadLastCheckpoint(taskName); 116 | log.info("Read last Checkpoint {} for TaskName {}", checkpoint, taskName); 117 | return checkpoint; 118 | } catch (Exception e) { 119 | String msg = "Unable to read last checkpoint for task name " + taskName + ": " + e.getMessage(); 120 | throw new SamzaException(msg, e); 121 | } 122 | } 123 | 124 | protected Checkpoint doReadLastCheckpoint(TaskName tn) throws Exception { 125 | 126 | assertRegistered(tn); 127 | 128 | String checkpointPath = getCheckpointPath(tn); 129 | byte[] data = curator.getData().forPath(checkpointPath); 130 | if (data != null && data.length > 0) { 131 | return CHECKPOINT_SERDE.fromBytes(data); 132 | } 133 | return null; 134 | } 135 | 136 | protected static byte[] intToBytes(int i) { 137 | ByteBuffer bb = ByteBuffer.allocate(4); 138 | bb.putInt(i); 139 | return bb.array(); 140 | } 141 | 142 | protected static int bytesToInt(byte[] bytes) { 143 | Assert.notNull(bytes, "bytes cannot be null."); 144 | Assert.isTrue(bytes.length == 4, "integer byte arrays must be 4 bytes long."); 145 | ByteBuffer bb = ByteBuffer.wrap(bytes); 146 | return bb.getInt(); 147 | } 148 | 149 | protected void assertRegistered(TaskName tn) { 150 | if (!registeredTaskNames.contains(tn)) { 151 | throw new SamzaException(tn + " is not registered with this CheckpointManager."); 152 | } 153 | } 154 | 155 | @Override 156 | public Map readChangeLogPartitionMapping() { 157 | try { 158 | Map mapping = doReadChangeLogPartitionMapping(); 159 | log.info("Read changelog partition mapping {}", mapping); 160 | return mapping; 161 | } catch (Exception e) { 162 | String msg = "Unable to read change log partition mapping: " + e.getMessage(); 163 | throw new SamzaException(msg, e); 164 | } 165 | } 166 | 167 | protected Map doReadChangeLogPartitionMapping() throws Exception { 168 | 169 | Map m = new HashMap<>(); 170 | 171 | List children; 172 | try { 173 | children = curator.getChildren().forPath(tasksPath); 174 | } catch (KeeperException.NoNodeException nne) { 175 | //can be null if no tasks have been registered yet - i.e. very first run of a job 176 | return Collections.emptyMap(); 177 | } 178 | 179 | log.debug("Getting changelog partition mappings for tasks {}", children); 180 | for (String taskName : children) { 181 | String path = tasksPath + "/" + taskName; 182 | byte[] data = curator.getData().forPath(path); 183 | if (data != null && data.length > 0) { 184 | int val = bytesToInt(data); 185 | TaskName tn = new TaskName(taskName); 186 | m.put(tn, val); 187 | } 188 | } 189 | 190 | return m; 191 | } 192 | 193 | @Override 194 | public void writeChangeLogPartitionMapping(Map mapping) { 195 | try { 196 | doWriteChangeLogPartitionMapping(mapping); 197 | log.info("Wrote changelog partition mapping {}", mapping); 198 | } catch (Exception e) { 199 | String msg = "Unable to write changelog partition mapping: " + e.getMessage(); 200 | throw new SamzaException(msg, e); 201 | } 202 | } 203 | 204 | protected boolean createChangeLogPartitionPathIfNecessary(String clpnPath, byte[] data) throws Exception { 205 | try { 206 | String result = curator.create().creatingParentsIfNeeded().forPath(clpnPath, data); 207 | log.info("Created changelog partition number node {}", result); 208 | return true; 209 | } catch (KeeperException.NodeExistsException e) { 210 | log.info("Changelog partition number node already exists: {}", clpnPath); 211 | log.trace("Exception details: ", e); 212 | return false; 213 | } 214 | } 215 | 216 | protected void doWriteChangeLogPartitionMapping(Map mapping) throws Exception { 217 | 218 | CuratorTransaction transaction = curator.inTransaction(); 219 | boolean needTransaction = false; 220 | 221 | for (Map.Entry entry : mapping.entrySet()) { 222 | 223 | Integer partitionNumber = entry.getValue(); 224 | TaskName tn = entry.getKey(); 225 | 226 | String clpnPath = getChangelogPartitionNumberPath(tn); 227 | byte[] data = intToBytes(partitionNumber); 228 | 229 | boolean created = createChangeLogPartitionPathIfNecessary(clpnPath, data); 230 | 231 | if (!created) {//create would have written with the data, but since we didn't create, we have to set it now: 232 | transaction.setData().forPath(clpnPath, data); 233 | needTransaction = true; 234 | log.debug("Appended changelog partition mapping {}={} to current transaction.", tn, partitionNumber); 235 | } 236 | } 237 | 238 | if (needTransaction) { 239 | ((CuratorTransactionFinal) transaction).commit(); 240 | } 241 | 242 | log.info("Wrote changelog partition mappings {}", mapping); 243 | } 244 | 245 | @Override 246 | public void stop() { 247 | log.debug("Stopped {}", getClass().getSimpleName()); 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /samza-zookeeper/src/main/java/com/stormpath/samza/lang/Arrays.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.samza.lang; 2 | 3 | /** 4 | * @since 0.6 5 | */ 6 | public final class Arrays { 7 | 8 | //for code coverage 9 | private static final Arrays INSTANCE = new Arrays(); 10 | 11 | private Arrays(){} 12 | 13 | public static int length(byte[] bytes) { 14 | return bytes != null ? bytes.length : 0; 15 | } 16 | 17 | public static byte[] clean(byte[] bytes) { 18 | return length(bytes) > 0 ? bytes : null; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /samza-zookeeper/src/main/java/com/stormpath/samza/lang/Assert.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.samza.lang; 2 | 3 | import java.util.Collection; 4 | import java.util.Map; 5 | 6 | public final class Assert { 7 | 8 | //for code coverage 9 | private static final Assert INSTANCE = new Assert(); 10 | 11 | private Assert(){} 12 | 13 | /** 14 | * Assert a boolean expression, throwing IllegalArgumentException 15 | * if the test result is false. 16 | *
Assert.isTrue(i > 0, "The value must be greater than zero");
17 | * @param expression a boolean expression 18 | * @param message the exception message to use if the assertion fails 19 | * @throws IllegalArgumentException if expression is false 20 | */ 21 | public static void isTrue(boolean expression, String message) { 22 | if (!expression) { 23 | throw new IllegalArgumentException(message); 24 | } 25 | } 26 | 27 | /** 28 | * Assert a boolean expression, throwing IllegalArgumentException 29 | * if the test result is false. 30 | *
Assert.isTrue(i > 0);
31 | * @param expression a boolean expression 32 | * @throws IllegalArgumentException if expression is false 33 | */ 34 | public static void isTrue(boolean expression) { 35 | isTrue(expression, "[Assertion failed] - this expression must be true"); 36 | } 37 | 38 | /** 39 | * Assert that an object is null . 40 | *
Assert.isNull(value, "The value must be null");
41 | * @param object the object to check 42 | * @param message the exception message to use if the assertion fails 43 | * @throws IllegalArgumentException if the object is not null 44 | */ 45 | public static void isNull(Object object, String message) { 46 | if (object != null) { 47 | throw new IllegalArgumentException(message); 48 | } 49 | } 50 | 51 | /** 52 | * Assert that an object is null . 53 | *
Assert.isNull(value);
54 | * @param object the object to check 55 | * @throws IllegalArgumentException if the object is not null 56 | */ 57 | public static void isNull(Object object) { 58 | isNull(object, "[Assertion failed] - the object argument must be null"); 59 | } 60 | 61 | /** 62 | * Assert that an object is not null . 63 | *
Assert.notNull(clazz, "The class must not be null");
64 | * @param object the object to check 65 | * @param message the exception message to use if the assertion fails 66 | * @throws IllegalArgumentException if the object is null 67 | */ 68 | public static T notNull(T object, String message) { 69 | if (object == null) { 70 | throw new IllegalArgumentException(message); 71 | } 72 | return object; 73 | } 74 | 75 | /** 76 | * Assert that an object is not null . 77 | *
Assert.notNull(clazz);
78 | * @param object the object to check 79 | * @throws IllegalArgumentException if the object is null 80 | */ 81 | public static void notNull(Object object) { 82 | notNull(object, "[Assertion failed] - this argument is required; it must not be null"); 83 | } 84 | 85 | /** 86 | * Assert that the given String is not empty; that is, 87 | * it must not be null and not the empty String. 88 | *
Assert.hasLength(name, "Name must not be empty");
89 | * @param text the String to check 90 | * @param message the exception message to use if the assertion fails 91 | * @see Strings#hasLength 92 | */ 93 | public static void hasLength(String text, String message) { 94 | if (!Strings.hasLength(text)) { 95 | throw new IllegalArgumentException(message); 96 | } 97 | } 98 | 99 | /** 100 | * Assert that the given String is not empty; that is, 101 | * it must not be null and not the empty String. 102 | *
Assert.hasLength(name);
103 | * @param text the String to check 104 | * @see Strings#hasLength 105 | */ 106 | public static void hasLength(String text) { 107 | hasLength(text, 108 | "[Assertion failed] - this String argument must have length; it must not be null or empty"); 109 | } 110 | 111 | /** 112 | * Assert that the given String has valid text content; that is, it must not 113 | * be null and must contain at least one non-whitespace character. 114 | *
Assert.hasText(name, "'name' must not be empty");
115 | * @param text the String to check 116 | * @param message the exception message to use if the assertion fails 117 | * @see Strings#hasText 118 | */ 119 | public static String hasText(String text, String message) { 120 | if (!Strings.hasText(text)) { 121 | throw new IllegalArgumentException(message); 122 | } 123 | return text; 124 | } 125 | 126 | /** 127 | * Assert that the given String has valid text content; that is, it must not 128 | * be null and must contain at least one non-whitespace character. 129 | *
Assert.hasText(name, "'name' must not be empty");
130 | * @param text the String to check 131 | * @see Strings#hasText 132 | */ 133 | public static void hasText(String text) { 134 | hasText(text, 135 | "[Assertion failed] - this String argument must have text; it must not be null, empty, or blank"); 136 | } 137 | 138 | /** 139 | * Assert that the given text does not contain the given substring. 140 | *
Assert.doesNotContain(name, "rod", "Name must not contain 'rod'");
141 | * @param textToSearch the text to search 142 | * @param substring the substring to find within the text 143 | * @param message the exception message to use if the assertion fails 144 | */ 145 | public static void doesNotContain(String textToSearch, String substring, String message) { 146 | if (Strings.hasLength(textToSearch) && Strings.hasLength(substring) && 147 | textToSearch.indexOf(substring) != -1) { 148 | throw new IllegalArgumentException(message); 149 | } 150 | } 151 | 152 | /** 153 | * Assert that the given text does not contain the given substring. 154 | *
Assert.doesNotContain(name, "rod");
155 | * @param textToSearch the text to search 156 | * @param substring the substring to find within the text 157 | */ 158 | public static void doesNotContain(String textToSearch, String substring) { 159 | doesNotContain(textToSearch, substring, 160 | "[Assertion failed] - this String argument must not contain the substring [" + substring + "]"); 161 | } 162 | 163 | 164 | /** 165 | * Assert that an array has elements; that is, it must not be 166 | * null and must have at least one element. 167 | *
Assert.notEmpty(array, "The array must have elements");
168 | * @param array the array to check 169 | * @param message the exception message to use if the assertion fails 170 | * @throws IllegalArgumentException if the object array is null or has no elements 171 | */ 172 | public static void notEmpty(Object[] array, String message) { 173 | if (Objects.isEmpty(array)) { 174 | throw new IllegalArgumentException(message); 175 | } 176 | } 177 | 178 | /** 179 | * Assert that an array has elements; that is, it must not be 180 | * null and must have at least one element. 181 | *
Assert.notEmpty(array);
182 | * @param array the array to check 183 | * @throws IllegalArgumentException if the object array is null or has no elements 184 | */ 185 | public static void notEmpty(Object[] array) { 186 | notEmpty(array, "[Assertion failed] - this array must not be empty: it must contain at least 1 element"); 187 | } 188 | 189 | public static void notEmpty(byte[] array, String msg) { 190 | if (Objects.isEmpty(array)) { 191 | throw new IllegalArgumentException(msg); 192 | } 193 | } 194 | 195 | /** 196 | * Assert that an array has no null elements. 197 | * Note: Does not complain if the array is empty! 198 | *
Assert.noNullElements(array, "The array must have non-null elements");
199 | * @param array the array to check 200 | * @param message the exception message to use if the assertion fails 201 | * @throws IllegalArgumentException if the object array contains a null element 202 | */ 203 | public static void noNullElements(Object[] array, String message) { 204 | if (array != null) { 205 | for (int i = 0; i < array.length; i++) { 206 | if (array[i] == null) { 207 | throw new IllegalArgumentException(message); 208 | } 209 | } 210 | } 211 | } 212 | 213 | /** 214 | * Assert that an array has no null elements. 215 | * Note: Does not complain if the array is empty! 216 | *
Assert.noNullElements(array);
217 | * @param array the array to check 218 | * @throws IllegalArgumentException if the object array contains a null element 219 | */ 220 | public static void noNullElements(Object[] array) { 221 | noNullElements(array, "[Assertion failed] - this array must not contain any null elements"); 222 | } 223 | 224 | /** 225 | * Assert that a collection has elements; that is, it must not be 226 | * null and must have at least one element. 227 | *
Assert.notEmpty(collection, "Collection must have elements");
228 | * @param collection the collection to check 229 | * @param message the exception message to use if the assertion fails 230 | * @throws IllegalArgumentException if the collection is null or has no elements 231 | */ 232 | public static C notEmpty(C collection, String message) { 233 | if (Collections.isEmpty(collection)) { 234 | throw new IllegalArgumentException(message); 235 | } 236 | return collection; 237 | } 238 | 239 | /** 240 | * Assert that a collection has elements; that is, it must not be 241 | * null and must have at least one element. 242 | *
Assert.notEmpty(collection, "Collection must have elements");
243 | * @param collection the collection to check 244 | * @throws IllegalArgumentException if the collection is null or has no elements 245 | */ 246 | public static void notEmpty(Collection collection) { 247 | notEmpty(collection, 248 | "[Assertion failed] - this collection must not be empty: it must contain at least 1 element"); 249 | } 250 | 251 | /** 252 | * Assert that a Map has entries; that is, it must not be null 253 | * and must have at least one entry. 254 | *
Assert.notEmpty(map, "Map must have entries");
255 | * @param map the map to check 256 | * @param message the exception message to use if the assertion fails 257 | * @throws IllegalArgumentException if the map is null or has no entries 258 | */ 259 | public static Map notEmpty(Map map, String message) { 260 | if (Collections.isEmpty(map)) { 261 | throw new IllegalArgumentException(message); 262 | } 263 | return map; 264 | } 265 | 266 | /** 267 | * Assert that a Map has entries; that is, it must not be null 268 | * and must have at least one entry. 269 | *
Assert.notEmpty(map);
270 | * @param map the map to check 271 | * @throws IllegalArgumentException if the map is null or has no entries 272 | */ 273 | public static void notEmpty(Map map) { 274 | notEmpty(map, "[Assertion failed] - this map must not be empty; it must contain at least one entry"); 275 | } 276 | 277 | 278 | /** 279 | * Assert that the provided object is an instance of the provided class. 280 | *
Assert.instanceOf(Foo.class, foo);
281 | * @param clazz the required class 282 | * @param obj the object to check 283 | * @throws IllegalArgumentException if the object is not an instance of clazz 284 | * @see Class#isInstance 285 | */ 286 | public static void isInstanceOf(Class clazz, Object obj) { 287 | isInstanceOf(clazz, obj, ""); 288 | } 289 | 290 | /** 291 | * Assert that the provided object is an instance of the provided class. 292 | *
Assert.instanceOf(Foo.class, foo);
293 | * @param type the type to check against 294 | * @param obj the object to check 295 | * @param message a message which will be prepended to the message produced by 296 | * the function itself, and which may be used to provide context. It should 297 | * normally end in a ": " or ". " so that the function generate message looks 298 | * ok when prepended to it. 299 | * @throws IllegalArgumentException if the object is not an instance of clazz 300 | * @see Class#isInstance 301 | */ 302 | public static void isInstanceOf(Class type, Object obj, String message) { 303 | notNull(type, "Type to check against must not be null"); 304 | if (!type.isInstance(obj)) { 305 | throw new IllegalArgumentException(message + 306 | "Object of class [" + (obj != null ? obj.getClass().getName() : "null") + 307 | "] must be an instance of " + type); 308 | } 309 | } 310 | 311 | /** 312 | * Assert that superType.isAssignableFrom(subType) is true. 313 | *
Assert.isAssignable(Number.class, myClass);
314 | * @param superType the super type to check 315 | * @param subType the sub type to check 316 | * @throws IllegalArgumentException if the classes are not assignable 317 | */ 318 | public static void isAssignable(Class superType, Class subType) { 319 | isAssignable(superType, subType, ""); 320 | } 321 | 322 | /** 323 | * Assert that superType.isAssignableFrom(subType) is true. 324 | *
Assert.isAssignable(Number.class, myClass);
325 | * @param superType the super type to check against 326 | * @param subType the sub type to check 327 | * @param message a message which will be prepended to the message produced by 328 | * the function itself, and which may be used to provide context. It should 329 | * normally end in a ": " or ". " so that the function generate message looks 330 | * ok when prepended to it. 331 | * @throws IllegalArgumentException if the classes are not assignable 332 | */ 333 | public static void isAssignable(Class superType, Class subType, String message) { 334 | notNull(superType, "Type to check against must not be null"); 335 | if (subType == null || !superType.isAssignableFrom(subType)) { 336 | throw new IllegalArgumentException(message + subType + " is not assignable to " + superType); 337 | } 338 | } 339 | 340 | 341 | /** 342 | * Assert a boolean expression, throwing IllegalStateException 343 | * if the test result is false. Call isTrue if you wish to 344 | * throw IllegalArgumentException on an assertion failure. 345 | *
Assert.state(id == null, "The id property must not already be initialized");
346 | * @param expression a boolean expression 347 | * @param message the exception message to use if the assertion fails 348 | * @throws IllegalStateException if expression is false 349 | */ 350 | public static void state(boolean expression, String message) { 351 | if (!expression) { 352 | throw new IllegalStateException(message); 353 | } 354 | } 355 | 356 | /** 357 | * Assert a boolean expression, throwing {@link IllegalStateException} 358 | * if the test result is false. 359 | *

Call {@link #isTrue(boolean)} if you wish to 360 | * throw {@link IllegalArgumentException} on an assertion failure. 361 | *

Assert.state(id == null);
362 | * @param expression a boolean expression 363 | * @throws IllegalStateException if the supplied expression is false 364 | */ 365 | public static void state(boolean expression) { 366 | state(expression, "[Assertion failed] - this state invariant must be true"); 367 | } 368 | 369 | } 370 | -------------------------------------------------------------------------------- /samza-zookeeper/src/main/java/com/stormpath/samza/lang/Classes.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.samza.lang; 2 | 3 | import java.io.InputStream; 4 | import java.lang.reflect.Constructor; 5 | 6 | /** 7 | * @since 0.1 8 | */ 9 | public final class Classes { 10 | 11 | private static final Classes INSTANCE = new Classes(); 12 | 13 | private Classes() {} 14 | 15 | /** 16 | * @since 0.1 17 | */ 18 | private static final ClassLoaderAccessor THREAD_CL_ACCESSOR = new ExceptionIgnoringAccessor() { 19 | @Override 20 | protected ClassLoader doGetClassLoader() throws Throwable { 21 | return Thread.currentThread().getContextClassLoader(); 22 | } 23 | }; 24 | 25 | /** 26 | * @since 0.1 27 | */ 28 | private static final ClassLoaderAccessor CLASS_CL_ACCESSOR = new ExceptionIgnoringAccessor() { 29 | @Override 30 | protected ClassLoader doGetClassLoader() throws Throwable { 31 | return Classes.class.getClassLoader(); 32 | } 33 | }; 34 | 35 | /** 36 | * @since 0.1 37 | */ 38 | private static final ClassLoaderAccessor SYSTEM_CL_ACCESSOR = new ExceptionIgnoringAccessor() { 39 | @Override 40 | protected ClassLoader doGetClassLoader() throws Throwable { 41 | return ClassLoader.getSystemClassLoader(); 42 | } 43 | }; 44 | 45 | /** 46 | * Attempts to load the specified class name from the current thread's 47 | * {@link Thread#getContextClassLoader() context class loader}, then the 48 | * current ClassLoader (Classes.class.getClassLoader()), then the system/application 49 | * ClassLoader (ClassLoader.getSystemClassLoader(), in that order. If any of them cannot locate 50 | * the specified class, an UnknownClassException is thrown (our RuntimeException equivalent of 51 | * the JRE's ClassNotFoundException. 52 | * 53 | * @param fqcn the fully qualified class name to load 54 | * @return the located class 55 | * @throws UnknownClassException if the class cannot be found. 56 | */ 57 | public static Class forName(String fqcn) throws UnknownClassException { 58 | 59 | Class clazz = THREAD_CL_ACCESSOR.loadClass(fqcn); 60 | 61 | if (clazz == null) { 62 | clazz = CLASS_CL_ACCESSOR.loadClass(fqcn); 63 | } 64 | 65 | if (clazz == null) { 66 | clazz = SYSTEM_CL_ACCESSOR.loadClass(fqcn); 67 | } 68 | 69 | if (clazz == null) { 70 | String msg = "Unable to load class named [" + fqcn + "] from the thread context, current, or " + 71 | "system/application ClassLoaders. All heuristics have been exhausted. Class could not be found."; 72 | 73 | if (fqcn != null && fqcn.startsWith("com.stormpath.sdk.impl")) { 74 | msg += " Have you remembered to include the stormpath-sdk-impl .jar in your runtime classpath?"; 75 | } 76 | 77 | throw new UnknownClassException(msg); 78 | } 79 | 80 | return clazz; 81 | } 82 | 83 | /** 84 | * Returns the specified resource by checking the current thread's 85 | * {@link Thread#getContextClassLoader() context class loader}, then the 86 | * current ClassLoader (Classes.class.getClassLoader()), then the system/application 87 | * ClassLoader (ClassLoader.getSystemClassLoader(), in that order, using 88 | * {@link ClassLoader#getResourceAsStream(String) getResourceAsStream(name)}. 89 | * 90 | * @param name the name of the resource to acquire from the classloader(s). 91 | * @return the InputStream of the resource found, or null if the resource cannot be found from any 92 | * of the three mentioned ClassLoaders. 93 | * @since 0.8 94 | */ 95 | public static InputStream getResourceAsStream(String name) { 96 | 97 | InputStream is = THREAD_CL_ACCESSOR.getResourceStream(name); 98 | 99 | if (is == null) { 100 | is = CLASS_CL_ACCESSOR.getResourceStream(name); 101 | } 102 | 103 | if (is == null) { 104 | is = SYSTEM_CL_ACCESSOR.getResourceStream(name); 105 | } 106 | 107 | return is; 108 | } 109 | 110 | public static boolean isAvailable(String fullyQualifiedClassName) { 111 | try { 112 | forName(fullyQualifiedClassName); 113 | return true; 114 | } catch (UnknownClassException e) { 115 | return false; 116 | } 117 | } 118 | 119 | @SuppressWarnings("unchecked") 120 | public static Object newInstance(String fqcn) { 121 | return newInstance(forName(fqcn)); 122 | } 123 | 124 | @SuppressWarnings("unchecked") 125 | public static Object newInstance(String fqcn, Object... args) { 126 | return newInstance(forName(fqcn), args); 127 | } 128 | 129 | public static T newInstance(Class clazz) { 130 | if (clazz == null) { 131 | String msg = "Class method parameter cannot be null."; 132 | throw new IllegalArgumentException(msg); 133 | } 134 | try { 135 | return clazz.newInstance(); 136 | } catch (Exception e) { 137 | throw new InstantiationException("Unable to instantiate class [" + clazz.getName() + "]", e); 138 | } 139 | } 140 | 141 | public static T newInstance(Class clazz, Object... args) { 142 | Class[] argTypes = new Class[args.length]; 143 | for (int i = 0; i < args.length; i++) { 144 | argTypes[i] = args[i].getClass(); 145 | } 146 | Constructor ctor = getConstructor(clazz, argTypes); 147 | return instantiate(ctor, args); 148 | } 149 | 150 | public static Constructor getConstructor(Class clazz, Class... argTypes) { 151 | try { 152 | return clazz.getConstructor(argTypes); 153 | } catch (NoSuchMethodException e) { 154 | throw new IllegalStateException(e); 155 | } 156 | 157 | } 158 | 159 | public static T instantiate(Constructor ctor, Object... args) { 160 | try { 161 | return ctor.newInstance(args); 162 | } catch (Exception e) { 163 | String msg = "Unable to instantiate instance with constructor [" + ctor + "]"; 164 | throw new InstantiationException(msg, e); 165 | } 166 | } 167 | 168 | /** 169 | * @since 1.0 170 | */ 171 | private static interface ClassLoaderAccessor { 172 | Class loadClass(String fqcn); 173 | 174 | InputStream getResourceStream(String name); 175 | } 176 | 177 | /** 178 | * @since 1.0 179 | */ 180 | private static abstract class ExceptionIgnoringAccessor implements ClassLoaderAccessor { 181 | 182 | public Class loadClass(String fqcn) { 183 | Class clazz = null; 184 | ClassLoader cl = getClassLoader(); 185 | if (cl != null) { 186 | try { 187 | clazz = cl.loadClass(fqcn); 188 | } catch (ClassNotFoundException e) { 189 | //Class couldn't be found by loader 190 | } 191 | } 192 | return clazz; 193 | } 194 | 195 | public InputStream getResourceStream(String name) { 196 | InputStream is = null; 197 | ClassLoader cl = getClassLoader(); 198 | if (cl != null) { 199 | is = cl.getResourceAsStream(name); 200 | } 201 | return is; 202 | } 203 | 204 | protected final ClassLoader getClassLoader() { 205 | try { 206 | return doGetClassLoader(); 207 | } catch (Throwable t) { 208 | //Unable to get ClassLoader 209 | } 210 | return null; 211 | } 212 | 213 | protected abstract ClassLoader doGetClassLoader() throws Throwable; 214 | } 215 | } 216 | 217 | -------------------------------------------------------------------------------- /samza-zookeeper/src/main/java/com/stormpath/samza/lang/Collections.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.samza.lang; 2 | 3 | import java.util.*; 4 | import java.util.Arrays; 5 | 6 | public final class Collections { 7 | 8 | //for code coverage 9 | private static final Collections INSTANCE = new Collections(); 10 | 11 | private Collections(){} 12 | 13 | public static List emptyList() { 14 | return java.util.Collections.emptyList(); 15 | } 16 | 17 | @SafeVarargs 18 | public static List listOf(T... elements) { 19 | if (elements == null || elements.length == 0) { 20 | return java.util.Collections.emptyList(); 21 | } 22 | return java.util.Collections.unmodifiableList(Arrays.asList(elements)); 23 | } 24 | 25 | @SafeVarargs 26 | public static Set setOf(T... elements) { 27 | if (elements == null || elements.length == 0) { 28 | return java.util.Collections.emptySet(); 29 | } 30 | Set set = new HashSet<>(elements.length); 31 | java.util.Collections.addAll(set, elements); 32 | return java.util.Collections.unmodifiableSet(set); 33 | } 34 | 35 | /** 36 | * Return true if the supplied Collection is null 37 | * or empty. Otherwise, return false. 38 | * @param collection the Collection to check 39 | * @return whether the given Collection is empty 40 | */ 41 | public static boolean isEmpty(Collection collection) { 42 | return (collection == null || collection.isEmpty()); 43 | } 44 | 45 | /** 46 | * Returns the collection's size or {@code 0} if the collection is {@code null}. 47 | * 48 | * @param collection the collection to check. 49 | * @return the collection's size or {@code 0} if the collection is {@code null}. 50 | * @since 0.9.2 51 | */ 52 | public static int size(Collection collection) { 53 | return collection == null ? 0 : collection.size(); 54 | } 55 | 56 | /** 57 | * Returns the map's size or {@code 0} if the map is {@code null}. 58 | * 59 | * @param map the map to check 60 | * @return the map's size or {@code 0} if the map is {@code null}. 61 | * @since 0.9.2 62 | */ 63 | public static int size(Map map) { 64 | return map == null ? 0 : map.size(); 65 | } 66 | 67 | /** 68 | * Return true if the supplied Map is null 69 | * or empty. Otherwise, return false. 70 | * @param map the Map to check 71 | * @return whether the given Map is empty 72 | */ 73 | public static boolean isEmpty(Map map) { 74 | return (map == null || map.isEmpty()); 75 | } 76 | 77 | /** 78 | * Convert the supplied array into a List. A primitive array gets 79 | * converted into a List of the appropriate wrapper type. 80 | *

A null source value will be converted to an 81 | * empty List. 82 | * @param source the (potentially primitive) array 83 | * @return the converted List result 84 | * @see Objects#toObjectArray(Object) 85 | */ 86 | public static List arrayToList(Object source) { 87 | return Arrays.asList(Objects.toObjectArray(source)); 88 | } 89 | 90 | /** 91 | * Merge the given array into the given Collection. 92 | * @param array the array to merge (may be null) 93 | * @param collection the target Collection to merge the array into 94 | */ 95 | @SuppressWarnings("unchecked") 96 | public static void mergeArrayIntoCollection(Object array, Collection collection) { 97 | if (collection == null) { 98 | throw new IllegalArgumentException("Collection must not be null"); 99 | } 100 | Object[] arr = Objects.toObjectArray(array); 101 | for (Object elem : arr) { 102 | collection.add(elem); 103 | } 104 | } 105 | 106 | /** 107 | * Merge the given Properties instance into the given Map, 108 | * copying all properties (key-value pairs) over. 109 | *

Uses Properties.propertyNames() to even catch 110 | * default properties linked into the original Properties instance. 111 | * @param props the Properties instance to merge (may be null) 112 | * @param map the target Map to merge the properties into 113 | */ 114 | @SuppressWarnings("unchecked") 115 | public static void mergePropertiesIntoMap(Properties props, Map map) { 116 | if (map == null) { 117 | throw new IllegalArgumentException("Map must not be null"); 118 | } 119 | if (props != null) { 120 | for (Enumeration en = props.propertyNames(); en.hasMoreElements();) { 121 | String key = (String) en.nextElement(); 122 | Object value = props.getProperty(key); 123 | if (value == null) { 124 | // Potentially a non-String value... 125 | value = props.get(key); 126 | } 127 | map.put(key, value); 128 | } 129 | } 130 | } 131 | 132 | 133 | /** 134 | * Check whether the given Iterator contains the given element. 135 | * @param iterator the Iterator to check 136 | * @param element the element to look for 137 | * @return true if found, false else 138 | */ 139 | public static boolean contains(Iterator iterator, Object element) { 140 | if (iterator != null) { 141 | while (iterator.hasNext()) { 142 | Object candidate = iterator.next(); 143 | if (Objects.nullSafeEquals(candidate, element)) { 144 | return true; 145 | } 146 | } 147 | } 148 | return false; 149 | } 150 | 151 | /** 152 | * Check whether the given Enumeration contains the given element. 153 | * @param enumeration the Enumeration to check 154 | * @param element the element to look for 155 | * @return true if found, false else 156 | */ 157 | public static boolean contains(Enumeration enumeration, Object element) { 158 | if (enumeration != null) { 159 | while (enumeration.hasMoreElements()) { 160 | Object candidate = enumeration.nextElement(); 161 | if (Objects.nullSafeEquals(candidate, element)) { 162 | return true; 163 | } 164 | } 165 | } 166 | return false; 167 | } 168 | 169 | /** 170 | * Check whether the given Collection contains the given element instance. 171 | *

Enforces the given instance to be present, rather than returning 172 | * true for an equal element as well. 173 | * @param collection the Collection to check 174 | * @param element the element to look for 175 | * @return true if found, false else 176 | */ 177 | public static boolean containsInstance(Collection collection, Object element) { 178 | if (collection != null) { 179 | for (Object candidate : collection) { 180 | if (candidate == element) { 181 | return true; 182 | } 183 | } 184 | } 185 | return false; 186 | } 187 | 188 | /** 189 | * Return true if any element in 'candidates' is 190 | * contained in 'source'; otherwise returns false. 191 | * @param source the source Collection 192 | * @param candidates the candidates to search for 193 | * @return whether any of the candidates has been found 194 | */ 195 | public static boolean containsAny(Collection source, Collection candidates) { 196 | if (isEmpty(source) || isEmpty(candidates)) { 197 | return false; 198 | } 199 | for (Object candidate : candidates) { 200 | if (source.contains(candidate)) { 201 | return true; 202 | } 203 | } 204 | return false; 205 | } 206 | 207 | /** 208 | * Return the first element in 'candidates' that is contained in 209 | * 'source'. If no element in 'candidates' is present in 210 | * 'source' returns null. Iteration order is 211 | * {@link Collection} implementation specific. 212 | * @param source the source Collection 213 | * @param candidates the candidates to search for 214 | * @return the first present object, or null if not found 215 | */ 216 | public static Object findFirstMatch(Collection source, Collection candidates) { 217 | if (isEmpty(source) || isEmpty(candidates)) { 218 | return null; 219 | } 220 | for (Object candidate : candidates) { 221 | if (source.contains(candidate)) { 222 | return candidate; 223 | } 224 | } 225 | return null; 226 | } 227 | 228 | /** 229 | * Find a single value of the given type in the given Collection. 230 | * @param collection the Collection to search 231 | * @param type the type to look for 232 | * @return a value of the given type found if there is a clear match, 233 | * or null if none or more than one such value found 234 | */ 235 | @SuppressWarnings("unchecked") 236 | public static T findValueOfType(Collection collection, Class type) { 237 | if (isEmpty(collection)) { 238 | return null; 239 | } 240 | T value = null; 241 | for (Object element : collection) { 242 | if (type == null || type.isInstance(element)) { 243 | if (value != null) { 244 | // More than one value found... no clear single value. 245 | return null; 246 | } 247 | value = (T) element; 248 | } 249 | } 250 | return value; 251 | } 252 | 253 | /** 254 | * Find a single value of one of the given types in the given Collection: 255 | * searching the Collection for a value of the first type, then 256 | * searching for a value of the second type, etc. 257 | * @param collection the collection to search 258 | * @param types the types to look for, in prioritized order 259 | * @return a value of one of the given types found if there is a clear match, 260 | * or null if none or more than one such value found 261 | */ 262 | public static Object findValueOfType(Collection collection, Class[] types) { 263 | if (isEmpty(collection) || Objects.isEmpty(types)) { 264 | return null; 265 | } 266 | for (Class type : types) { 267 | Object value = findValueOfType(collection, type); 268 | if (value != null) { 269 | return value; 270 | } 271 | } 272 | return null; 273 | } 274 | 275 | /** 276 | * Determine whether the given Collection only contains a single unique object. 277 | * @param collection the Collection to check 278 | * @return true if the collection contains a single reference or 279 | * multiple references to the same instance, false else 280 | */ 281 | public static boolean hasUniqueObject(Collection collection) { 282 | if (isEmpty(collection)) { 283 | return false; 284 | } 285 | boolean hasCandidate = false; 286 | Object candidate = null; 287 | for (Object elem : collection) { 288 | if (!hasCandidate) { 289 | hasCandidate = true; 290 | candidate = elem; 291 | } 292 | else if (candidate != elem) { 293 | return false; 294 | } 295 | } 296 | return true; 297 | } 298 | 299 | /** 300 | * Find the common element type of the given Collection, if any. 301 | * @param collection the Collection to check 302 | * @return the common element type, or null if no clear 303 | * common type has been found (or the collection was empty) 304 | */ 305 | public static Class findCommonElementType(Collection collection) { 306 | if (isEmpty(collection)) { 307 | return null; 308 | } 309 | Class candidate = null; 310 | for (Object val : collection) { 311 | if (val != null) { 312 | if (candidate == null) { 313 | candidate = val.getClass(); 314 | } 315 | else if (candidate != val.getClass()) { 316 | return null; 317 | } 318 | } 319 | } 320 | return candidate; 321 | } 322 | 323 | /** 324 | * Marshal the elements from the given enumeration into an array of the given type. 325 | * Enumeration elements must be assignable to the type of the given array. The array 326 | * returned will be a different instance than the array given. 327 | */ 328 | public static A[] toArray(Enumeration enumeration, A[] array) { 329 | ArrayList elements = new ArrayList(); 330 | while (enumeration.hasMoreElements()) { 331 | elements.add(enumeration.nextElement()); 332 | } 333 | return elements.toArray(array); 334 | } 335 | 336 | /** 337 | * Adapt an enumeration to an iterator. 338 | * @param enumeration the enumeration 339 | * @return the iterator 340 | */ 341 | public static Iterator toIterator(Enumeration enumeration) { 342 | return new EnumerationIterator(enumeration); 343 | } 344 | 345 | /** 346 | * Iterator wrapping an Enumeration. 347 | */ 348 | private static class EnumerationIterator implements Iterator { 349 | 350 | private Enumeration enumeration; 351 | 352 | public EnumerationIterator(Enumeration enumeration) { 353 | this.enumeration = enumeration; 354 | } 355 | 356 | public boolean hasNext() { 357 | return this.enumeration.hasMoreElements(); 358 | } 359 | 360 | public E next() { 361 | return this.enumeration.nextElement(); 362 | } 363 | 364 | public void remove() throws UnsupportedOperationException { 365 | throw new UnsupportedOperationException("Not supported"); 366 | } 367 | } 368 | } 369 | 370 | -------------------------------------------------------------------------------- /samza-zookeeper/src/main/java/com/stormpath/samza/lang/InstantiationException.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.samza.lang; 2 | 3 | /** 4 | * @since 0.1 5 | */ 6 | public class InstantiationException extends RuntimeException { 7 | 8 | public InstantiationException(String s, Throwable t) { 9 | super(s, t); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samza-zookeeper/src/main/java/com/stormpath/samza/lang/ScalaUtils.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.samza.lang; 2 | 3 | import org.apache.samza.SamzaException; 4 | import scala.Option; 5 | import scala.runtime.AbstractFunction0; 6 | import scala.runtime.AbstractFunction1; 7 | import scala.runtime.AbstractFunction2; 8 | 9 | import java.util.Optional; 10 | import java.util.function.BiConsumer; 11 | import java.util.function.Consumer; 12 | import java.util.function.Function; 13 | import java.util.function.Supplier; 14 | 15 | public class ScalaUtils { 16 | 17 | public static Optional o(scala.Option scalaOption) { 18 | if (scalaOption.isEmpty()) { 19 | return Optional.empty(); 20 | } 21 | return Optional.of(scalaOption.get()); 22 | } 23 | 24 | public static T require(Option option, final String msg) { 25 | return option.getOrElse(new AbstractFunction0() { 26 | @Override 27 | public T apply() { 28 | throw new SamzaException(msg); 29 | } 30 | }); 31 | } 32 | 33 | public static T require(Option option, Supplier supplier) { 34 | return option.getOrElse(new AbstractFunction0() { 35 | @Override 36 | public T apply() { 37 | String msg = supplier.get(); 38 | throw new SamzaException(msg); 39 | } 40 | }); 41 | } 42 | 43 | public static AbstractFunction0 val(final T val) { 44 | return new AbstractFunction0() { 45 | @Override 46 | public T apply() { 47 | return val; 48 | } 49 | }; 50 | } 51 | 52 | public static AbstractFunction0 fun(final Supplier fun) { 53 | return new AbstractFunction0() { 54 | @Override 55 | public T apply() { 56 | return fun.get(); 57 | } 58 | }; 59 | } 60 | 61 | public static AbstractFunction1 fun1(final Consumer fun) { 62 | return new AbstractFunction1() { 63 | @Override 64 | public R apply(T val) { 65 | fun.accept(val); 66 | return null; 67 | } 68 | }; 69 | } 70 | 71 | public static AbstractFunction1 funf(final Function fun) { 72 | return new AbstractFunction1() { 73 | @Override 74 | public R apply(T v1) { 75 | return fun.apply(v1); 76 | } 77 | }; 78 | } 79 | 80 | public static AbstractFunction2 fun2(final BiConsumer fun) { 81 | return new AbstractFunction2() { 82 | @Override 83 | public R apply(T1 v1, T2 v2) { 84 | fun.accept(v1, v2); 85 | return null; 86 | } 87 | }; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /samza-zookeeper/src/main/java/com/stormpath/samza/lang/UnknownClassException.java: -------------------------------------------------------------------------------- 1 | package com.stormpath.samza.lang; 2 | 3 | /** 4 | * A RuntimeException equivalent of the JDK's 5 | * ClassNotFoundException, to maintain a RuntimeException paradigm. 6 | * 7 | * @since 0.1 8 | */ 9 | public class UnknownClassException extends RuntimeException { 10 | 11 | /* 12 | /** 13 | * Creates a new UnknownClassException. 14 | * 15 | public UnknownClassException() { 16 | super(); 17 | }*/ 18 | 19 | /** 20 | * Constructs a new UnknownClassException. 21 | * 22 | * @param message the reason for the exception 23 | */ 24 | public UnknownClassException(String message) { 25 | super(message); 26 | } 27 | 28 | /* 29 | * Constructs a new UnknownClassException. 30 | * 31 | * @param cause the underlying Throwable that caused this exception to be thrown. 32 | * 33 | public UnknownClassException(Throwable cause) { 34 | super(cause); 35 | } 36 | 37 | /** 38 | * Constructs a new UnknownClassException. 39 | * 40 | * @param message the reason for the exception 41 | * @param cause the underlying Throwable that caused this exception to be thrown. 42 | * 43 | public UnknownClassException(String message, Throwable cause) { 44 | super(message, cause); 45 | } 46 | */ 47 | 48 | } --------------------------------------------------------------------------------