diff --git a/Dockerfile b/Dockerfile
index 7d88a608d..e475ff340 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -26,9 +26,11 @@ COPY --from=source /src/.docker/config /app/config
WORKDIR /app
+ENV AMY_SOCKET_CONFIG_WEB_SOCKET_PORT 6661
ENV AMY_SERVER_CONFIG_SERVER_SOCKET_PORT 80
ENV AMY_SERVER_CONFIG_SERVER_URL http://localhost:80/
EXPOSE $AMY_SERVER_CONFIG_SERVER_SOCKET_PORT
+EXPOSE $AMY_SOCKET_CONFIG_WEB_SOCKET_PORT
RUN mkdir /config
RUN mkdir /data
diff --git a/README.md b/README.md
index 9d2d8240e..6fb7caf44 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,9 @@
[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=de.unistuttgart.iaas.amyassist%3Aamy&metric=bugs)](https://sonarcloud.io/component_measures?id=de.unistuttgart.iaas.amyassist%3Aamy&metric=Reliability)
[![Reliability](https://sonarcloud.io/api/project_badges/measure?project=de.unistuttgart.iaas.amyassist%3Aamy&metric=reliability_rating)](https://sonarcloud.io/component_measures?id=de.unistuttgart.iaas.amyassist%3Aamy&metric=Reliability)
+[![Docker](http://dockeri.co/image/amyassist/amy)](https://hub.docker.com/r/amyassist/amy/)
+
+
### Personal Assistance System
This is a research project from students of the University of Stuttgart. No functionality is tested. There may be harmful errors.
@@ -76,7 +79,9 @@ Direct links:
## Deployment
-TODO
+Best use our docker compose [project](https://github.com/amyassist/amy-all).
+Otherwise build the master node as a jar and every plugin as a jar and place all plugin jars in a directory.
+Then create a directory named config and place all required configs in there. In the plugin.config set the plugin path acordingly.
## Built With
@@ -88,7 +93,7 @@ Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduc
## Versioning
-TODO
+This project uses [Semantic Versioning](https://semver.org/).
## Authors
diff --git a/amy-master-node/pom.xml b/amy-master-node/pom.xml
index 0cbfefa24..5d88dcc9e 100644
--- a/amy-master-node/pom.xml
+++ b/amy-master-node/pom.xml
@@ -8,7 +8,7 @@
de.unistuttgart.iaas.amyassist
amy
- 0.5.0
+ 0.6.0
../pom.xml
@@ -55,6 +55,11 @@
amy-natlang
${amy.natlang.version}
+
+ de.unistuttgart.iaas.amyassist
+ amy-chat-socket
+ ${amy.chatsocket.version}
+
diff --git a/amy-message-hub-api/pom.xml b/amy-message-hub-api/pom.xml
index d9e96487a..b073512f7 100644
--- a/amy-message-hub-api/pom.xml
+++ b/amy-message-hub-api/pom.xml
@@ -8,7 +8,7 @@
de.unistuttgart.iaas.amyassist
amy
- 0.5.0
+ 0.6.0
../pom.xml
diff --git a/amy-message-hub/pom.xml b/amy-message-hub/pom.xml
index 240de58bb..29b70d9fe 100644
--- a/amy-message-hub/pom.xml
+++ b/amy-message-hub/pom.xml
@@ -5,7 +5,7 @@
de.unistuttgart.iaas.amyassist
amy
- 0.5.0
+ 0.6.0
amy-message-hub
diff --git a/api/pom.xml b/api/pom.xml
index bd330c138..7f5c066c0 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -8,7 +8,7 @@
de.unistuttgart.iaas.amyassist
amy
- 0.5.0
+ 0.6.0
../pom.xml
diff --git a/api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/taskscheduler/api/TaskScheduler.java b/api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/taskscheduler/api/TaskScheduler.java
index 3ecad8b78..c5679eaca 100644
--- a/api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/taskscheduler/api/TaskScheduler.java
+++ b/api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/taskscheduler/api/TaskScheduler.java
@@ -24,6 +24,10 @@
package de.unistuttgart.iaas.amyassist.amy.core.taskscheduler.api;
import java.time.Instant;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nonnull;
/**
* Service to schedule and execute concurrent tasks.
@@ -46,6 +50,22 @@ public interface TaskScheduler {
* the task to execute
* @param instant
* The instant at which to execute that task
+ * @return the reference to the scheduled task
+ */
+ @Nonnull
+ ScheduledFuture> schedule(Runnable task, Instant instant);
+
+ /**
+ * Schedules the given task to execute at the given delay
+ *
+ * @param task
+ * the task to execute
+ * @param delay
+ * the delay
+ * @param timeUnit
+ * the time unit of the delay
+ * @return the reference to the scheduled task
*/
- void schedule(Runnable task, Instant instant);
+ @Nonnull
+ ScheduledFuture> schedule(Runnable task, long delay, TimeUnit timeUnit);
}
diff --git a/chat-socket/.settings/org.eclipse.jdt.core.prefs b/chat-socket/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..47397d9d2
--- /dev/null
+++ b/chat-socket/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,431 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=javax.annotation.Nonnull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=javax.annotation.ParametersAreNonnullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=javax.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=default
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=error
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_module_statements=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0
+org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=120
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=mixed
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/chat-socket/.settings/org.eclipse.jdt.ui.prefs b/chat-socket/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..81e418a00
--- /dev/null
+++ b/chat-socket/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,67 @@
+cleanup.add_default_serial_version_id=false
+cleanup.add_generated_serial_version_id=true
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=true
+cleanup.always_use_blocks=false
+cleanup.always_use_parentheses_in_expressions=true
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=true
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=false
+cleanup.organize_imports=true
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=false
+cleanup.remove_trailing_whitespaces_ignore_empty=true
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=true
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=_Amy-CleanUp
+cleanup_settings_version=2
+eclipse.preferences.version=1
+formatter_profile=_Amy-Formatter
+formatter_settings_version=13
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.ondemandthreshold=5
+org.eclipse.jdt.ui.staticondemandthreshold=1
+org.eclipse.jdt.ui.text.custom_code_templates=/**\n * Get's {@link \#${field} ${bare_field_name}}\n * @return ${bare_field_name}\n *//**\n * Set's {@link \#${field} ${bare_field_name}}\n * @param ${param} ${bare_field_name}\n *//**\n * ${tags}\n *//*\n * This source file is part of the Amy open source project.\n * For more information see github.com/AmyAssist\n * \n * Copyright (c) 2018 the Amy project authors.\n *\n * SPDX-License-Identifier\: Apache-2.0\n * \n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at \n * \n * http\://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * For more information see notice.md\n */\n/**\n * TODO\: Description\n * @author\n * ${tags}\n *//**\n * \n *//**\n * ${tags}\n *//**\n * ${see_to_overridden}\n *//**\n * ${tags}\n * ${see_to_target}\n */${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}\n\n\n\n// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();// ${todo} Auto-generated method stub\n${body_statement}${body_statement}\n// ${todo} Auto-generated constructor stubreturn this.${field};${field} \= ${param};
diff --git a/chat-socket/.settings/org.eclipse.m2e.core.prefs b/chat-socket/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 000000000..f897a7f1c
--- /dev/null
+++ b/chat-socket/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/chat-socket/pom.xml b/chat-socket/pom.xml
new file mode 100644
index 000000000..11b2b258f
--- /dev/null
+++ b/chat-socket/pom.xml
@@ -0,0 +1,57 @@
+
+ 4.0.0
+ amy-chat-socket
+ Amy chat socket
+
+ de.unistuttgart.iaas.amyassist
+ amy
+ 0.6.0
+ ../pom.xml
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+ de.unistuttgart.iaas.amyassist
+ amy-natlang-api
+
+
+ de.unistuttgart.iaas.amyassist
+ amy-di-api
+
+
+ de.unistuttgart.iaas.amyassist
+ amy-api
+
+
+ org.java-websocket
+ Java-WebSocket
+ 1.3.9
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.8.10
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.8.10
+
+
+ com.fasterxml.jackson.module
+ jackson-module-jaxb-annotations
+ 2.9.5
+ compile
+
+
+ javax.ws.rs
+ javax.ws.rs-api
+
+
+ Socket for chat communication
+
diff --git a/chat-socket/src/main/java/de/unistuttgart/iaas/amyassist/amy/socket/ChatConfig.java b/chat-socket/src/main/java/de/unistuttgart/iaas/amyassist/amy/socket/ChatConfig.java
new file mode 100644
index 000000000..12e69209a
--- /dev/null
+++ b/chat-socket/src/main/java/de/unistuttgart/iaas/amyassist/amy/socket/ChatConfig.java
@@ -0,0 +1,53 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.socket;
+
+import de.unistuttgart.iaas.amyassist.amy.core.configuration.ConfigurationManager;
+import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Reference;
+import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Service;
+
+import java.util.Properties;
+
+/**
+ * Config helper class for websocket server
+ *
+ * @author Benno Krauß
+ */
+@Service
+public class ChatConfig {
+ /** The name of the config used by this class */
+ private static final String CONFIG_NAME = "socket.config";
+ /** The name of the property, which specifies the port */
+ static final String PROPERTY_PORT = "webSocketPort";
+ /** The name of the property which specifies the websocket endpoint URL */
+ static final String WEBSOCKET_URL = "webSocketURL";
+
+ @Reference
+ private ConfigurationManager configurationManager;
+
+ String get(String key) {
+ Properties conf = this.configurationManager.getConfigurationWithDefaults(CONFIG_NAME);
+ return conf.getProperty(key);
+ }
+}
diff --git a/chat-socket/src/main/java/de/unistuttgart/iaas/amyassist/amy/socket/ChatServer.java b/chat-socket/src/main/java/de/unistuttgart/iaas/amyassist/amy/socket/ChatServer.java
new file mode 100644
index 000000000..b15181625
--- /dev/null
+++ b/chat-socket/src/main/java/de/unistuttgart/iaas/amyassist/amy/socket/ChatServer.java
@@ -0,0 +1,84 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.socket;
+
+import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Reference;
+import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Service;
+import de.unistuttgart.iaas.amyassist.amy.core.natlang.DialogHandler;
+import de.unistuttgart.iaas.amyassist.amy.core.service.RunnableService;
+import org.slf4j.Logger;
+
+import java.io.IOException;
+
+import static de.unistuttgart.iaas.amyassist.amy.socket.ChatConfig.PROPERTY_PORT;
+
+/**
+ * the class running the server socket for the chat
+ *
+ * @author Christian Bräuner
+ */
+@Service(ChatServer.class)
+public class ChatServer implements RunnableService {
+
+ @Reference
+ private ChatConfig config;
+
+ @Reference
+ private Logger logger;
+
+ @Reference
+ private DialogHandler handler;
+
+ private ChatWebSocket socket;
+
+
+ /**
+ * @see de.unistuttgart.iaas.amyassist.amy.core.service.RunnableService#start()
+ */
+ @Override
+ public void start() {
+
+ int port = Integer.parseInt(config.get(PROPERTY_PORT));
+ this.socket = new ChatWebSocket(port, this.handler);
+ this.socket.start();
+
+ }
+
+ /**
+ * @see de.unistuttgart.iaas.amyassist.amy.core.service.RunnableService#stop()
+ */
+ @Override
+ public void stop() {
+ try {
+ this.socket.stop();
+ } catch (IOException e) {
+ this.logger.error("Can't close chatserver", e);
+ } catch (InterruptedException e) {
+ this.logger.error("Interrupt while stoping", e);
+ Thread.currentThread().interrupt();
+ }
+ this.logger.info("ChatServer shutdown");
+ }
+
+}
diff --git a/chat-socket/src/main/java/de/unistuttgart/iaas/amyassist/amy/socket/ChatWebSocket.java b/chat-socket/src/main/java/de/unistuttgart/iaas/amyassist/amy/socket/ChatWebSocket.java
new file mode 100644
index 000000000..e8b94deef
--- /dev/null
+++ b/chat-socket/src/main/java/de/unistuttgart/iaas/amyassist/amy/socket/ChatWebSocket.java
@@ -0,0 +1,132 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.socket;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.AnnotationIntrospector;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
+import de.unistuttgart.iaas.amyassist.amy.core.natlang.DialogHandler;
+import de.unistuttgart.iaas.amyassist.amy.core.natlang.Response;
+import org.java_websocket.WebSocket;
+import org.java_websocket.handshake.ClientHandshake;
+import org.java_websocket.server.WebSocketServer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetSocketAddress;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * A web socket for the chat communication
+ *
+ * @author Christian Bräuner, Benno Krauß
+ */
+public class ChatWebSocket extends WebSocketServer {
+
+ private Logger logger = LoggerFactory.getLogger(ChatWebSocket.class);
+
+ private DialogHandler handler;
+
+ private Map dialogMap = new HashMap<>();
+
+ private ObjectMapper mapper;
+
+ /**
+ *creates a new web socket server
+ *
+ *@param port the port of the server
+ *@param handler the dialog handler of the backend
+ *
+ */
+ public ChatWebSocket(int port, DialogHandler handler) {
+ super(new InetSocketAddress(port));
+ this.handler = handler;
+
+ AnnotationIntrospector firstInspector = new JacksonAnnotationIntrospector();
+ AnnotationIntrospector secondInspector = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
+ AnnotationIntrospector inspectors = AnnotationIntrospector.pair(firstInspector, secondInspector);
+
+ mapper = new ObjectMapper();
+ mapper.setAnnotationIntrospector(inspectors);
+ }
+
+ /**
+ * @see org.java_websocket.server.WebSocketServer#onClose(org.java_websocket.WebSocket, int, java.lang.String, boolean)
+ */
+ @Override
+ public void onClose(WebSocket clientSocket, int code, String reason, boolean remote) {
+ this.logger.debug("{} closed connection", clientSocket);
+ this.logger.debug("Code was {}. Reason was {}.", code, reason);
+
+ }
+
+ /**
+ * @see org.java_websocket.server.WebSocketServer#onError(org.java_websocket.WebSocket, java.lang.Exception)
+ */
+ @Override
+ public void onError(WebSocket conn, Exception ex) {
+ this.logger.error("Web Socket exception", ex);
+ }
+
+ /**
+ * @see org.java_websocket.server.WebSocketServer#onMessage(org.java_websocket.WebSocket, java.lang.String)
+ */
+ @Override
+ public void onMessage(WebSocket conn, String message) {
+ this.handler.process(message, this.dialogMap.get(conn.getRemoteSocketAddress()));
+ }
+
+ /**
+ * @see org.java_websocket.server.WebSocketServer#onOpen(org.java_websocket.WebSocket, org.java_websocket.handshake.ClientHandshake)
+ */
+ @Override
+ public void onOpen(WebSocket conn, ClientHandshake handshake) {
+ send(conn, Response.text("Hello, I am Amy").build());
+ UUID uuid = this.handler.createDialog(msg -> send(conn, msg));
+ this.dialogMap.put(conn.getRemoteSocketAddress(), uuid);
+ }
+
+ private void send(WebSocket socket, Response response) {
+ try {
+ socket.send(mapper.writeValueAsString(response));
+ } catch (JsonProcessingException e) {
+ logger.error("Error serializing Response-object", e);
+ }
+ }
+
+ /**
+ * @see org.java_websocket.server.WebSocketServer#onStart()
+ */
+ @Override
+ public void onStart() {
+ this.logger.info("Chatserver started");
+ setConnectionLostTimeout(100);
+ }
+
+}
diff --git a/chat-socket/src/main/java/de/unistuttgart/iaas/amyassist/amy/socket/RestResource.java b/chat-socket/src/main/java/de/unistuttgart/iaas/amyassist/amy/socket/RestResource.java
new file mode 100644
index 000000000..e909ca529
--- /dev/null
+++ b/chat-socket/src/main/java/de/unistuttgart/iaas/amyassist/amy/socket/RestResource.java
@@ -0,0 +1,52 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.socket;
+
+import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Reference;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import static de.unistuttgart.iaas.amyassist.amy.socket.ChatConfig.WEBSOCKET_URL;
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+
+/**
+ * Rest class to provide the web client the websocket endpoint URL
+ *
+ * @author Benno Krauß
+ */
+@Path("chat")
+public class RestResource {
+
+ @Reference
+ ChatConfig config;
+
+ @Path("url")
+ @Produces(TEXT_PLAIN)
+ @GET
+ public String getChatURL() {
+ return config.get(WEBSOCKET_URL);
+ }
+}
diff --git a/chat-socket/src/main/resources/META-INF/de.unistuttgart.iaas.amyassist.amy.core.di.Services b/chat-socket/src/main/resources/META-INF/de.unistuttgart.iaas.amyassist.amy.core.di.Services
new file mode 100644
index 000000000..f18ef90ab
--- /dev/null
+++ b/chat-socket/src/main/resources/META-INF/de.unistuttgart.iaas.amyassist.amy.core.di.Services
@@ -0,0 +1,2 @@
+de.unistuttgart.iaas.amyassist.amy.socket.ChatServer
+de.unistuttgart.iaas.amyassist.amy.socket.ChatConfig
diff --git a/chat-socket/src/main/resources/META-INF/javax.ws.rs.Path b/chat-socket/src/main/resources/META-INF/javax.ws.rs.Path
new file mode 100644
index 000000000..b531cea18
--- /dev/null
+++ b/chat-socket/src/main/resources/META-INF/javax.ws.rs.Path
@@ -0,0 +1 @@
+de.unistuttgart.iaas.amyassist.amy.socket.RestResource
diff --git a/chat-socket/src/main/resources/META-INF/socket.config.properties b/chat-socket/src/main/resources/META-INF/socket.config.properties
new file mode 100644
index 000000000..60e907346
--- /dev/null
+++ b/chat-socket/src/main/resources/META-INF/socket.config.properties
@@ -0,0 +1,2 @@
+webSocketPort=6661
+webSocketURL=ws://localhost:6661/
diff --git a/core/pom.xml b/core/pom.xml
index 1c86536db..650b94636 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -9,7 +9,7 @@
de.unistuttgart.iaas.amyassist
amy
- 0.5.0
+ 0.6.0
../pom.xml
@@ -145,7 +145,7 @@
de.unistuttgart.iaas.amyassist
amy-remote-sr
- 0.5.0
+ 0.6.0
diff --git a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/Core.java b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/Core.java
index 693fca29e..164a9ff19 100644
--- a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/Core.java
+++ b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/Core.java
@@ -28,12 +28,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import de.unistuttgart.iaas.amyassist.amy.core.console.ExitConsole;
import de.unistuttgart.iaas.amyassist.amy.core.di.Context;
import de.unistuttgart.iaas.amyassist.amy.core.di.DependencyInjection;
-import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescriptionImpl;
import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumerImpl;
import de.unistuttgart.iaas.amyassist.amy.core.di.provider.SingletonServiceProvider;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceDescriptionImpl;
import de.unistuttgart.iaas.amyassist.amy.core.io.CommandLineArgumentHandlerService;
import de.unistuttgart.iaas.amyassist.amy.core.io.CommandLineArgumentInfo;
import de.unistuttgart.iaas.amyassist.amy.core.pluginloader.PluginManager;
@@ -48,6 +47,9 @@
*/
public class Core {
+ private static final int EXIT_CODE_ALL_GOOD = 0;
+ private static final int EXIT_CODE_CMA_FLAGS_INVALID = 11;
+
private final Logger logger = LoggerFactory.getLogger(Core.class);
private final DependencyInjection di;
@@ -76,12 +78,17 @@ public Core() {
void start(String[] args) {
this.registerAllCoreServices();
this.init();
- CommandLineArgumentHandlerService cmaHandler = this.di.getService(new ServiceConsumerImpl<>(this.getClass(),
- new ServiceDescriptionImpl<>(CommandLineArgumentHandlerService.class))).getService();
+ CommandLineArgumentHandlerService cmaHandler = this.di.getServiceLocator()
+ .getService(new ServiceConsumerImpl<>(this.getClass(),
+ new ServiceDescriptionImpl<>(CommandLineArgumentHandlerService.class)))
+ .getService();
cmaHandler.load(args, System.out::println);
if (cmaHandler.shouldProgramContinue()) {
- this.di.register(new SingletonServiceProvider<>(CommandLineArgumentInfo.class, cmaHandler.getInfo()));
+ this.di.getConfiguration()
+ .register(new SingletonServiceProvider<>(CommandLineArgumentInfo.class, cmaHandler.getInfo()));
this.run();
+ } else {
+ System.exit(cmaHandler.areFlagsValid() ? EXIT_CODE_ALL_GOOD : EXIT_CODE_CMA_FLAGS_INVALID); // NOSONAR
}
}
@@ -100,8 +107,6 @@ private void run() {
* register all instances and classes in the DI
*/
private void registerAllCoreServices() {
- this.di.register(new SingletonServiceProvider<>(Core.class, this));
-
this.di.loadServices();
}
@@ -113,7 +118,7 @@ private void init() {
}
private void loadPlugins() {
- PluginManager pluginManager = this.di
+ PluginManager pluginManager = this.di.getServiceLocator()
.getService(
new ServiceConsumerImpl<>(this.getClass(), new ServiceDescriptionImpl<>(PluginManager.class)))
.getService();
@@ -122,7 +127,8 @@ private void loadPlugins() {
} catch (IOException e) {
throw new IllegalStateException("Could not load plugins due to an IOException.", e);
}
- this.di.registerContextProvider(Context.PLUGIN, new PluginProvider(pluginManager.getPlugins()));
+ this.di.getConfiguration().registerContextProvider(Context.PLUGIN,
+ new PluginProvider(pluginManager.getPlugins()));
}
/**
@@ -138,18 +144,9 @@ private void start() {
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
- /**
- * stop all Threads and terminate the application. This is call form the {@link ExitConsole}
- */
- public void stop() {
- Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
- this.doStop();
- }
-
private void doStop() {
this.logger.info("stop");
this.runnableServiceExtension.stop();
- this.di.shutdown();
this.logger.info("stopped");
}
diff --git a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/configuration/PropertiesProvider.java b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/configuration/PropertiesProvider.java
index 3bbf51e1a..535abf11a 100644
--- a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/configuration/PropertiesProvider.java
+++ b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/configuration/PropertiesProvider.java
@@ -32,10 +32,9 @@
import de.unistuttgart.iaas.amyassist.amy.core.di.*;
import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ConsumerFactory;
import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
-import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceHandle;
-import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceHandleImpl;
-import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceImplementationDescriptionImpl;
import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceProvider;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceDescriptionImpl;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceInstantiationDescriptionImpl;
import de.unistuttgart.iaas.amyassist.amy.core.pluginloader.IPlugin;
/**
@@ -53,35 +52,36 @@ public class PropertiesProvider implements ServiceProvider {
}
@Override
- public ServiceImplementationDescription getServiceImplementationDescription(
+ public ServiceInstantiationDescription getServiceInstantiationDescription(
@Nonnull ContextLocator locator, @Nonnull ServiceConsumer serviceConsumer) {
Map context = new HashMap<>();
context.put(Context.PLUGIN, locator.getContextProvider(Context.PLUGIN).getContext(serviceConsumer));
context.put(CONTEXT_WITH_DEFAULT, serviceConsumer.getServiceDescription().getAnnotations().stream()
.anyMatch(a -> a instanceof WithDefault));
- return new ServiceImplementationDescriptionImpl<>(serviceConsumer.getServiceDescription(), context,
+ return new ServiceInstantiationDescriptionImpl<>(serviceConsumer.getServiceDescription(), context,
Properties.class);
}
@Override
- public @Nonnull ServiceHandle createService(@Nonnull SimpleServiceLocator locator,
- @Nonnull ServiceImplementationDescription serviceImplementationDescription) {
+ public @Nonnull Properties createService(@Nonnull SimpleServiceLocator locator,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
ConfigurationManager configurationLoader = locator.getService(ConsumerFactory.build(PropertiesProvider.class,
new ServiceDescriptionImpl<>(ConfigurationManager.class))).getService();
- IPlugin plugin = (IPlugin) serviceImplementationDescription.getContext().get(Context.PLUGIN);
+ IPlugin plugin = (IPlugin) serviceInstantiationDescription.getContext().get(Context.PLUGIN);
String uniqueName = plugin.getUniqueName();
- boolean withDefault = (boolean) serviceImplementationDescription.getContext().get(CONTEXT_WITH_DEFAULT);
+ boolean withDefault = (boolean) serviceInstantiationDescription.getContext().get(CONTEXT_WITH_DEFAULT);
if (withDefault) {
ClassLoader classLoader = plugin.getClassLoader();
- return new ServiceHandleImpl<>(configurationLoader.getConfigurationWithDefaults(uniqueName, classLoader));
+ return configurationLoader.getConfigurationWithDefaults(uniqueName, classLoader);
}
- return new ServiceHandleImpl<>(configurationLoader.getConfiguration(uniqueName));
+ return configurationLoader.getConfiguration(uniqueName);
}
@Override
- public void dispose(ServiceHandle properties) {
- // TODO maybe save the properties
+ public void dispose(@Nonnull Properties properties,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
+ // nothing to do here
}
}
diff --git a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/console/ExitConsole.java b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/console/ExitConsole.java
index cdff3a016..fcf32a9fa 100644
--- a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/console/ExitConsole.java
+++ b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/console/ExitConsole.java
@@ -24,8 +24,6 @@
package de.unistuttgart.iaas.amyassist.amy.core.console;
import asg.cliche.Command;
-import de.unistuttgart.iaas.amyassist.amy.core.Core;
-import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Reference;
/**
* The Exit Command to shutdown Amy.
@@ -34,11 +32,11 @@
*/
public class ExitConsole {
- @Reference
- private Core core;
-
+ /**
+ * Stops the program
+ */
@Command
public void exit() {
- this.core.stop();
+ System.exit(0); // NOSONAR
}
}
diff --git a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/io/CommandLineArgumentHandlerService.java b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/io/CommandLineArgumentHandlerService.java
index 6f9aa044a..f3618a9cc 100644
--- a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/io/CommandLineArgumentHandlerService.java
+++ b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/io/CommandLineArgumentHandlerService.java
@@ -163,6 +163,15 @@ private void processFlagParameter(FlagParameterInformation flagParaInfo, String
}
}
+ /**
+ * Checks whether the flags are valid.
+ *
+ * @return Whether the flags are valid.
+ */
+ public boolean areFlagsValid() {
+ return this.flagsValid;
+ }
+
/**
* @return Whether the program should continue execution.
* @throws IllegalStateException
diff --git a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/logger/LoggerProvider.java b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/logger/LoggerProvider.java
index 6027dfb5e..1eda9895f 100644
--- a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/logger/LoggerProvider.java
+++ b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/logger/LoggerProvider.java
@@ -30,17 +30,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import de.unistuttgart.iaas.amyassist.amy.core.di.Context;
-import de.unistuttgart.iaas.amyassist.amy.core.di.ContextLocator;
-import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescription;
-import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescriptionImpl;
-import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceImplementationDescription;
-import de.unistuttgart.iaas.amyassist.amy.core.di.SimpleServiceLocator;
+import de.unistuttgart.iaas.amyassist.amy.core.di.*;
import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
-import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceHandle;
-import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceHandleImpl;
-import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceImplementationDescriptionImpl;
import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceProvider;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceDescriptionImpl;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceInstantiationDescriptionImpl;
/**
* The Logger Provider for all Services
@@ -55,21 +49,22 @@ public class LoggerProvider implements ServiceProvider {
}
@Override
- public ServiceImplementationDescription getServiceImplementationDescription(@Nonnull ContextLocator locator,
+ public ServiceInstantiationDescription getServiceInstantiationDescription(@Nonnull ContextLocator locator,
@Nonnull ServiceConsumer serviceConsumer) {
- return new ServiceImplementationDescriptionImpl<>(serviceConsumer.getServiceDescription(),
+ return new ServiceInstantiationDescriptionImpl<>(serviceConsumer.getServiceDescription(),
Collections.singletonMap(Context.CLASS, serviceConsumer.getConsumerClass()), LoggerFactory.class);
}
@Override
- public @Nonnull ServiceHandle createService(@Nonnull SimpleServiceLocator locator,
- @Nonnull ServiceImplementationDescription serviceImplementationDescription) {
- Class> cls = (Class>) serviceImplementationDescription.getContext().get(Context.CLASS);
- return new ServiceHandleImpl<>(LoggerFactory.getLogger(cls));
+ public @Nonnull Logger createService(@Nonnull SimpleServiceLocator locator,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
+ Class> cls = (Class>) serviceInstantiationDescription.getContext().get(Context.CLASS);
+ return LoggerFactory.getLogger(cls);
}
@Override
- public void dispose(ServiceHandle service) {
+ public void dispose(@Nonnull Logger service,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
// Logger MUST NOT be disposed
}
diff --git a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/persistence/storage/DatabaseStorage.java b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/persistence/storage/DatabaseStorage.java
index abc1108cd..db7afbdc0 100644
--- a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/persistence/storage/DatabaseStorage.java
+++ b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/persistence/storage/DatabaseStorage.java
@@ -78,8 +78,13 @@ public boolean has(String key) {
@Override
public void delete(String key) {
- SimpleData find = this.entityManager.find(SimpleData.class, this.prefix + key);
- this.entityManager.remove(find);
+ this.entityManager.getTransaction().begin();
+ try {
+ SimpleData find = this.entityManager.find(SimpleData.class, this.prefix + key);
+ this.entityManager.remove(find);
+ } finally {
+ this.entityManager.getTransaction().commit();
+ }
}
@PreDestroy
diff --git a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/service/DeploymentContainerServiceExtension.java b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/service/DeploymentContainerServiceExtension.java
index 19ffdde1e..526c0b1e3 100644
--- a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/service/DeploymentContainerServiceExtension.java
+++ b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/service/DeploymentContainerServiceExtension.java
@@ -28,6 +28,7 @@
import de.unistuttgart.iaas.amyassist.amy.core.di.DependencyInjection;
import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescription;
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceLocator;
import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumerImpl;
import de.unistuttgart.iaas.amyassist.amy.core.di.extension.Extension;
@@ -38,13 +39,13 @@
*/
public class DeploymentContainerServiceExtension implements Extension {
- private DependencyInjection di;
+ private ServiceLocator serviceLocator;
private final Set> deploymentContainerServices = new HashSet<>();
@Override
public void postConstruct(DependencyInjection dependencyInjection) {
- this.di = dependencyInjection;
+ this.serviceLocator = dependencyInjection.getServiceLocator();
}
@Override
@@ -59,7 +60,7 @@ public void onRegister(ServiceDescription serviceDescription, Class ext
*/
public void deploy() {
for (ServiceDescription> deploymentContainerServiceDescription : this.deploymentContainerServices) {
- DeploymentContainerService deploymentContainerService = (DeploymentContainerService) this.di
+ DeploymentContainerService deploymentContainerService = (DeploymentContainerService) this.serviceLocator
.getService(new ServiceConsumerImpl<>(this.getClass(), deploymentContainerServiceDescription))
.getService();
deploymentContainerService.deploy();
diff --git a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/service/RunnableServiceExtension.java b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/service/RunnableServiceExtension.java
index ff04656b7..08ee778d6 100644
--- a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/service/RunnableServiceExtension.java
+++ b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/service/RunnableServiceExtension.java
@@ -28,6 +28,7 @@
import de.unistuttgart.iaas.amyassist.amy.core.di.DependencyInjection;
import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescription;
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceLocator;
import de.unistuttgart.iaas.amyassist.amy.core.di.extension.Extension;
/**
@@ -37,13 +38,13 @@
*/
public class RunnableServiceExtension implements Extension {
- private DependencyInjection di;
+ private ServiceLocator serviceLocator;
private final Set> runnableServices = new HashSet<>();
@Override
public void postConstruct(DependencyInjection dependencyInjection) {
- this.di = dependencyInjection;
+ this.serviceLocator = dependencyInjection.getServiceLocator();
}
@Override
@@ -57,7 +58,7 @@ public void onRegister(ServiceDescription serviceDescription, Class ext
* Deploy all registered RunnableServies
*/
public void deploy() {
- ServiceManagerImpl service = this.di.getService(ServiceManagerImpl.class);
+ ServiceManagerImpl service = this.serviceLocator.getService(ServiceManagerImpl.class);
this.runnableServices.forEach(service::register);
}
@@ -65,14 +66,14 @@ public void deploy() {
* Start all registered RunnableServies
*/
public void start() {
- this.di.getService(ServiceManagerImpl.class).start();
+ this.serviceLocator.getService(ServiceManagerImpl.class).start();
}
/**
* Stop all running Services
*/
public void stop() {
- this.di.getService(ServiceManagerImpl.class).stop();
+ this.serviceLocator.getService(ServiceManagerImpl.class).stop();
}
}
diff --git a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/speech/SpeechManager.java b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/speech/SpeechManager.java
index 6357b967b..5fac3f2ef 100644
--- a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/speech/SpeechManager.java
+++ b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/speech/SpeechManager.java
@@ -95,7 +95,7 @@ public class SpeechManager implements RunnableService {
private void init() {
loadAndCheckProperties();
if (this.recognitionEnabled) {
- this.dialogId = this.dialogHandler.createDialog(this::voiceOutput);
+ this.dialogId = this.dialogHandler.createDialog(response -> this.voiceOutput(response.getText()));
this.sphinxGrammarCreator.createGrammar(SPHINX_MAIN_GARMMAR_NAME, this.keywordStartSingle,
this.keywordStartMulti, this.keywordEndMulti, this.keywordStopOutput);
}
diff --git a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/taskscheduler/TaskSchedulerImpl.java b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/taskscheduler/TaskSchedulerImpl.java
index e1b505316..54e04218b 100644
--- a/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/taskscheduler/TaskSchedulerImpl.java
+++ b/core/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/taskscheduler/TaskSchedulerImpl.java
@@ -27,8 +27,11 @@
import java.time.temporal.ChronoUnit;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
+import javax.annotation.Nonnull;
+
import org.slf4j.Logger;
import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.PostConstruct;
@@ -58,30 +61,41 @@ private void setup() {
this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(r -> new Thread(r, "TaskScheduler"));
}
+ private Runnable handleException(Runnable task) {
+ return () -> {
+ try {
+ task.run();
+ } catch (RuntimeException e) {
+ this.logger.error("Exception while executing scheduled task.", e);
+ throw e;
+ }
+ };
+ }
+
@Override
public void execute(Runnable runnable) {
- this.scheduledExecutorService.execute(runnable);
+ this.scheduledExecutorService.execute(this.handleException(runnable));
}
@Override
- public void schedule(Runnable task, Instant instant) {
+ public @Nonnull ScheduledFuture> schedule(Runnable task, Instant instant) {
this.logger.debug("schedule task for {}", instant);
long delay = ChronoUnit.MILLIS.between(this.environment.getCurrentDateTime().toInstant(), instant);
this.logger.debug("the delay of the task is {} ms", delay);
- this.scheduledExecutorService.schedule(task, delay, TimeUnit.MILLISECONDS);
+ return this.scheduledExecutorService.schedule(this.handleException(task), delay, TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ public @Nonnull ScheduledFuture> schedule(Runnable task, long delay, TimeUnit timeUnit) {
+ this.logger.debug("schedule task with delay of {} {}", delay, timeUnit);
+ return this.scheduledExecutorService.schedule(this.handleException(task), delay, timeUnit);
}
- /**
- * @see de.unistuttgart.iaas.amyassist.amy.core.service.RunnableService#start()
- */
@Override
public void start() {
// Do nothing.
}
- /**
- * @see de.unistuttgart.iaas.amyassist.amy.core.service.RunnableService#stop()
- */
@Override
public void stop() {
this.scheduledExecutorService.shutdownNow();
diff --git a/core/src/main/resources/META-INF/core.config.properties b/core/src/main/resources/META-INF/core.config.properties
index 6a27be405..a83d0d3d8 100644
--- a/core/src/main/resources/META-INF/core.config.properties
+++ b/core/src/main/resources/META-INF/core.config.properties
@@ -1,3 +1 @@
enableConsole=true
-enableStemmer=true
-chooseLanguage=en
diff --git a/core/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/console/ConsoleTest.java b/core/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/console/ConsoleTest.java
index 7840b7595..3827db8fc 100644
--- a/core/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/console/ConsoleTest.java
+++ b/core/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/console/ConsoleTest.java
@@ -53,9 +53,9 @@ void init() {
ConfigurationManager configurationManager = Mockito.mock(ConfigurationManager.class);
this.properties = new Properties();
Mockito.when(configurationManager.getConfigurationWithDefaults("core.config")).thenReturn(this.properties);
- this.dependencyInjection
+ this.dependencyInjection.getConfiguration()
.register(new SingletonServiceProvider<>(ConfigurationManager.class, configurationManager));
- this.dependencyInjection.register(new LoggerProvider());
+ this.dependencyInjection.getConfiguration().register(new LoggerProvider());
}
@Test
@@ -68,8 +68,9 @@ void test() {
Mockito.when(handler.createDialog(ArgumentMatchers.any())).thenReturn(uuid);
- this.dependencyInjection.register(new SingletonServiceProvider<>(DialogHandler.class, handler));
- SpeechConsole console = this.dependencyInjection.createAndInitialize(SpeechConsole.class);
+ this.dependencyInjection.getConfiguration()
+ .register(new SingletonServiceProvider<>(DialogHandler.class, handler));
+ SpeechConsole console = this.dependencyInjection.getServiceLocator().createAndInitialize(SpeechConsole.class);
console.say(testInput);
Mockito.verify(handler).process(expected, uuid);
diff --git a/core/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/service/ServiceManagerImplTest.java b/core/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/service/ServiceManagerImplTest.java
index 083d308cf..626edcb15 100644
--- a/core/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/service/ServiceManagerImplTest.java
+++ b/core/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/service/ServiceManagerImplTest.java
@@ -45,7 +45,7 @@ class ServiceManagerImplTest {
public void setup() {
this.runnableServiceExtension = new RunnableServiceExtension();
this.di = new DependencyInjection(this.runnableServiceExtension);
- this.di.register(ServiceManagerImpl.class);
+ this.di.getConfiguration().register(ServiceManagerImpl.class);
}
/**
@@ -53,12 +53,11 @@ public void setup() {
*/
@Test
void testStart() {
-
- this.di.register(TestRunnableService.class);
+ this.di.getConfiguration().register(TestRunnableService.class);
this.runnableServiceExtension.deploy();
this.runnableServiceExtension.start();
- TestRunnableService service = this.di.getService(TestRunnableService.class);
+ TestRunnableService service = this.di.getServiceLocator().getService(TestRunnableService.class);
assertThat(service.run, is(true));
this.runnableServiceExtension.stop();
assertThat(service.run, is(false));
@@ -80,12 +79,11 @@ void testStartDouble() {
*/
@Test
void testStartRunnableServiceFromInterface() {
-
- this.di.register(SimpleServiceImpl.class);
+ this.di.getConfiguration().register(SimpleServiceImpl.class);
this.runnableServiceExtension.deploy();
this.runnableServiceExtension.start();
- SimpleService service = this.di.getService(SimpleService.class);
+ SimpleService service = this.di.getServiceLocator().getService(SimpleService.class);
assertThat(service.getRun(), is(true));
this.runnableServiceExtension.stop();
assertThat(service.getRun(), is(false));
diff --git a/deployment-descriptor-utility/pom.xml b/deployment-descriptor-utility/pom.xml
index 40433bb8f..ea9562acf 100644
--- a/deployment-descriptor-utility/pom.xml
+++ b/deployment-descriptor-utility/pom.xml
@@ -8,7 +8,7 @@
de.unistuttgart.iaas.amyassist
amy
- 0.5.0
+ 0.6.0
../pom.xml
diff --git a/di-api/pom.xml b/di-api/pom.xml
index 0a651f98c..7656c32ce 100644
--- a/di-api/pom.xml
+++ b/di-api/pom.xml
@@ -8,7 +8,7 @@
de.unistuttgart.iaas.amyassist
amy
- 0.5.0
+ 0.6.0
../pom.xml
diff --git a/di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceImplementationDescription.java b/di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceInstantiationDescription.java
similarity index 75%
rename from di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceImplementationDescription.java
rename to di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceInstantiationDescription.java
index dc3e9a49c..c523a5ec2 100644
--- a/di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceImplementationDescription.java
+++ b/di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceInstantiationDescription.java
@@ -27,16 +27,20 @@
import javax.annotation.Nonnull;
+import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
+import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceProvider;
+
/**
- * Information about the implementation of a Service and the context in which the service is provided. This Descriptor
- * is created from The ServiceProvider which should provide the Service. The Informations is needed by the Dependency
- * Injection to manage the Service instance.
+ * Information needed to instantiate the Service. This includes information about the implementation of a Service and
+ * the context in which the service is provided. This Descriptor is created from the
+ * {@link ServiceProvider#getServiceInstantiationDescription(ContextLocator, ServiceConsumer)} which should provide the
+ * Service. The Informations is needed by the Dependency Injection to manage the Service instance.
*
* @author Leon Kiefer
* @param
* the type of the service
*/
-public interface ServiceImplementationDescription {
+public interface ServiceInstantiationDescription {
/**
* The Service description independent of this implementation specific description. It is used to find a matching
* ServiceProvider.
@@ -65,5 +69,5 @@ public interface ServiceImplementationDescription {
* that implements the contract types
*/
@Nonnull
- public Class> getImplementationClass();
+ Class> getImplementationClass();
}
diff --git a/di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/SimpleServiceLocator.java b/di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/SimpleServiceLocator.java
index 5215ae74d..1b013431a 100644
--- a/di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/SimpleServiceLocator.java
+++ b/di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/SimpleServiceLocator.java
@@ -23,19 +23,21 @@
package de.unistuttgart.iaas.amyassist.amy.core.di;
+import javax.annotation.Nonnull;
+
import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceHandle;
import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceProvider;
/**
- * SimpleServiceLocator is used in {@link ServiceProvider} to get dependencies. The normal extended {@link ServiceLocator} interface
- * should not be used in ServiceProviders.
+ * SimpleServiceLocator is used in {@link ServiceProvider} to get dependencies. The normal extended
+ * {@link ServiceLocator} interface should not be used in ServiceProviders.
*
* @author Leon Kiefer
*/
public interface SimpleServiceLocator {
/**
- * Get a service for the given service consumer. This Method track the caller to prevent the service get created
+ * Get a service for the given service consumer. This method track the caller to prevent the service get created
* twice and to run in a dependency circle.
*
* @param serviceConsumer
@@ -44,6 +46,6 @@ public interface SimpleServiceLocator {
* @param
* the type of the service
*/
- ServiceHandle getService(ServiceConsumer serviceConsumer);
+ ServiceHandle getService(@Nonnull ServiceConsumer serviceConsumer);
}
diff --git a/di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ServiceProvider.java b/di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ServiceProvider.java
index 8a57faf43..460db426d 100644
--- a/di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ServiceProvider.java
+++ b/di-api/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ServiceProvider.java
@@ -28,7 +28,7 @@
import de.unistuttgart.iaas.amyassist.amy.core.di.ContextLocator;
import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescription;
-import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceImplementationDescription;
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceInstantiationDescription;
import de.unistuttgart.iaas.amyassist.amy.core.di.SimpleServiceLocator;
import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
@@ -55,43 +55,45 @@ public interface ServiceProvider {
/**
* Refine the ServiceDescription of a ServiceConsumer. The ServiceProvider can decide if it can provide the
* requested service. If this ServiceProvider can provide the service, it returns the
- * ServiceImplementationDescription for the Service. The ServiceImplementationDescription contains all information
- * needed to create the requested Service for the Consumer.
+ * ServiceInstantiationDescription for the Service. The ServiceInstantiationDescription contains all information
+ * needed to create the requested Service for the ServiceConsumer.
*
* @param locator
* the ContextLocator which can be used to lookup ContextProvider
* @param serviceConsumer
* the consumer of the Service. This can be used to extract context information.
- * @return the ServiceImplementationDescription for the Service this Provider can provide or null if this provider
+ * @return the ServiceInstantiationDescription for the Service this Provider can provide or null if this provider
* can not provide the requested Service.
*/
@CheckForNull
- ServiceImplementationDescription getServiceImplementationDescription(@Nonnull ContextLocator locator,
+ ServiceInstantiationDescription getServiceInstantiationDescription(@Nonnull ContextLocator locator,
@Nonnull ServiceConsumer serviceConsumer);
/**
- * Create a new Service from the given ServiceImplementationDescription. Using the ServiceLocator to lookup
+ * Create a new Service from the given ServiceInstantiationDescription. Using the ServiceLocator to lookup
* dependencies.
*
* @param locator
- * the ServiceLocator to lookup services
- * @param serviceImplementationDescription
+ * the ServiceLocator to lookup services, don't pass this reference to any created Service
+ * @param serviceInstantiationDescription
* the description of the Service which must be created
*
- * @return the created service of this ServiceProvider for the given ServiceImplementationDescription
+ * @return the created service of this ServiceProvider for the given ServiceInstantiationDescription
*/
@Nonnull
- ServiceHandle createService(@Nonnull SimpleServiceLocator locator,
- @Nonnull ServiceImplementationDescription serviceImplementationDescription);
+ T createService(@Nonnull SimpleServiceLocator locator,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription);
/**
* Dispose a Service that was provided by this ServiceProvider.
*
* @param service
* the Service that should be disposed
+ * @param serviceInstantiationDescription
+ * the description of the Service which should be disposed
* @throws IllegalArgumentException
* if the given Service was not provided by this ServiceProvider.
*/
- void dispose(ServiceHandle service);
+ void dispose(@Nonnull T service, @Nonnull ServiceInstantiationDescription serviceInstantiationDescription);
}
diff --git a/di/pom.xml b/di/pom.xml
index e6fdf3efd..6364327fb 100644
--- a/di/pom.xml
+++ b/di/pom.xml
@@ -8,7 +8,7 @@
de.unistuttgart.iaas.amyassist
amy
- 0.5.0
+ 0.6.0
../pom.xml
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjection.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjection.java
index 4e9aacb6d..c87d72286 100644
--- a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjection.java
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjection.java
@@ -23,36 +23,17 @@
package de.unistuttgart.iaas.amyassist.amy.core.di;
-import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
-import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNullableByDefault;
-import org.apache.commons.lang3.reflect.FieldUtils;
-
-import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Reference;
-import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Service;
-import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ConsumerFactory;
-import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumerImpl;
-import de.unistuttgart.iaas.amyassist.amy.core.di.context.provider.ClassProvider;
-import de.unistuttgart.iaas.amyassist.amy.core.di.context.provider.StaticProvider;
import de.unistuttgart.iaas.amyassist.amy.core.di.extension.Extension;
import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ClassServiceProvider;
-import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceHandle;
-import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceProvider;
-import de.unistuttgart.iaas.amyassist.amy.core.di.provider.SingletonServiceProvider;
-import de.unistuttgart.iaas.amyassist.amy.core.di.util.Util;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceDescriptionImpl;
/**
* Dependency Injection Used to manage dependencies and Service instantiation at runtime. A Service that relies on DI is
@@ -65,21 +46,11 @@
* @author Leon Kiefer, Tim Neumann
*/
@ParametersAreNullableByDefault
-public class DependencyInjection implements ServiceLocator, Configuration {
- /**
- * A register which maps a service description to it's service provider.
- */
- private final Map, ServiceProvider>> register;
-
- private final Map, ServiceHandle>> servicePool;
-
- private final Map, ServiceCreation>> serviceCreationInfos;
-
- @Nonnull
- private final ContextLocatorImpl contextLocator;
-
+public class DependencyInjection {
private final Set extensions;
+ private final InternalServiceLocator internalServiceLocator;
+
/**
* Creates a new Dependency Injection
*
@@ -87,18 +58,17 @@ public class DependencyInjection implements ServiceLocator, Configuration {
* for the dependency injection
*/
public DependencyInjection(Extension... extensions) {
- this.register = new ConcurrentHashMap<>();
- this.servicePool = new ConcurrentHashMap<>();
- this.serviceCreationInfos = new ConcurrentHashMap<>();
- this.contextLocator = new ContextLocatorImpl();
- this.extensions = new HashSet<>(Arrays.asList(extensions));
+ this.internalServiceLocator = new InternalServiceLocator(this::onRegister);
- this.registerContextProvider("class", new ClassProvider());
- this.register(new SingletonServiceProvider<>(ServiceLocator.class, this));
- this.register(new SingletonServiceProvider<>(Configuration.class, this));
+ this.extensions = new HashSet<>(Arrays.asList(extensions));
this.extensions.forEach(ext -> ext.postConstruct(this));
}
+ private void onRegister(ClassServiceProvider classServiceProvider) {
+ this.extensions.forEach(ext -> ext.onRegister(classServiceProvider.getServiceDescription(),
+ classServiceProvider.getImplementationClass()));
+ }
+
/**
* Loads Services using the provider configuration file
* META-INF/services/de.unistuttgart.iaas.amyassist.amy.core.di.ServiceProviderLoader and the
@@ -107,227 +77,29 @@ public DependencyInjection(Extension... extensions) {
* @see java.util.ServiceLoader
*/
public void loadServices() {
- ServiceLoader.load(ServiceProviderLoader.class).forEach(s -> s.load(this));
- }
-
- @Override
- public void register(@Nonnull ServiceProvider serviceProvider) {
- ServiceDescription serviceDescription = serviceProvider.getServiceDescription();
- ServiceKey serviceKey = new ServiceKey<>(serviceDescription);
- synchronized (this.register) {
- if (this.register.containsKey(serviceKey))
- throw new DuplicateServiceException(serviceDescription);
- this.register.put(serviceKey, serviceProvider);
- }
- }
-
- @Override
- public void register(@Nonnull Class> cls) {
- Service annotation = cls.getAnnotation(Service.class);
- if (annotation == null)
- throw new ClassIsNotAServiceException(cls);
- @Nonnull
- Class> serviceType = annotation.value();
- if (serviceType.equals(Void.class)) {
- Class>[] interfaces = cls.getInterfaces();
- if (interfaces.length == 1) {
- // annotations can not have null values
- serviceType = interfaces[0];
- } else if (interfaces.length == 0) {
- serviceType = cls;
- } else {
- throw new IllegalArgumentException("The type of the service implementation " + cls.getName()
- + " is ambiguous, because the type is not given by the annotation and multiple interfaces are implemented."
- + " Please specify which type this service should have.");
- }
- }
- this.registerClass(cls, serviceType);
- }
-
- private void registerClass(@Nonnull Class cls, @Nonnull Class serviceType) {
- if (!serviceType.isAssignableFrom(cls)) {
- throw new IllegalArgumentException(
- "The specified service type " + serviceType.getName() + " is not assignable from " + cls.getName());
- }
- Class extends T> implementationClass = (Class extends T>) cls;
- ClassServiceProvider classServiceProvider = new ClassServiceProvider<>(serviceType, implementationClass);
- this.register(classServiceProvider);
- this.extensions
- .forEach(ext -> ext.onRegister(classServiceProvider.getServiceDescription(), implementationClass));
- }
-
- @Override
- public void registerContextProvider(String key, StaticProvider> staticProvider) {
- this.contextLocator.registerContextProvider(key, staticProvider);
- }
-
- @Override
- public T getService(Class serviceType) {
- return this.getService(new ServiceDescriptionImpl<>(serviceType)).getService();
- }
-
- @Override
- public ServiceHandle getService(ServiceDescription serviceDescription) {
- return this.getService(new ServiceConsumerImpl<>(this.getClass(), serviceDescription));
- }
-
- @Override
- public ServiceHandle getService(@Nonnull ServiceConsumer serviceConsumer) {
- return this.getService(new ServiceCreation<>(serviceConsumer.getConsumerClass().getName()), serviceConsumer);
+ ServiceLoader.load(ServiceProviderLoader.class).forEach(s -> s.load(this.getConfiguration()));
}
/**
- * Get the service with the tracking of the dependency hierarchy.
- *
- * @param dependentServiceCreation
- * @param serviceConsumer
- * @param
- * the type of the service
- * @return the service handle of the service
+ * @return the instance of the Configuration owned by the DependencyInjection
*/
- ServiceHandle getService(@Nonnull ServiceCreation> dependentServiceCreation,
- @Nonnull ServiceConsumer serviceConsumer) {
- ServiceProvider provider = this.getServiceProvider(serviceConsumer.getServiceDescription(),
- dependentServiceCreation);
- ServiceImplementationDescription serviceImplementationDescription = provider
- .getServiceImplementationDescription(this.contextLocator, serviceConsumer);
- if (serviceImplementationDescription == null) {
- throw new ServiceNotFoundException(serviceConsumer.getServiceDescription(), dependentServiceCreation);
- }
- return this.lookUpOrCreateService(dependentServiceCreation, provider, serviceImplementationDescription);
- }
-
- @SuppressWarnings("unchecked")
- @CheckForNull
- private ServiceHandle lookUpService(@Nonnull ServiceProvider serviceProvider,
- @Nonnull ServiceImplementationDescription serviceImplementationDescription) {
-
- ServicePoolKey> servicePoolKey = new ServicePoolKey<>(serviceProvider, serviceImplementationDescription);
-
- if (!this.servicePool.containsKey(servicePoolKey)) {
- return null;
- }
- return (ServiceHandle) this.servicePool.get(servicePoolKey);
- }
-
- @SuppressWarnings("unchecked")
- private Future> createService(@Nonnull ServiceCreation> dependentServiceCreation,
- @Nonnull ServiceProvider serviceProvider,
- @Nonnull ServiceImplementationDescription serviceImplementationDescription) {
- ServicePoolKey key = new ServicePoolKey<>(serviceProvider, serviceImplementationDescription);
- synchronized (this.servicePool) {
- ServiceCreation serviceCreation;
- if (this.serviceCreationInfos.containsKey(key)) {
- serviceCreation = (ServiceCreation) this.serviceCreationInfos.get(key);
- } else {
- serviceCreation = new ServiceCreation<>(
- serviceImplementationDescription.getImplementationClass().getName());
-
- serviceCreation.completableFuture = CompletableFuture.supplyAsync(() -> {
- ServiceHandle service = serviceProvider.createService(
- new SimpleServiceLocatorImpl(this, serviceCreation), serviceImplementationDescription);
- this.servicePool.put(key, service);
- return service;
- });
-
- this.serviceCreationInfos.put(key, serviceCreation);
- }
- serviceCreation.addDependent(dependentServiceCreation);
-
- return serviceCreation.completableFuture;
- }
- }
-
- private ServiceHandle lookUpOrCreateService(@Nonnull ServiceCreation> dependentServiceCreationInfo,
- @Nonnull ServiceProvider serviceProvider,
- @Nonnull ServiceImplementationDescription serviceImplementationDescription) {
- ServiceHandle lookUpService = this.lookUpService(serviceProvider, serviceImplementationDescription);
- if (lookUpService == null) {
- Future> createService = this.createService(dependentServiceCreationInfo, serviceProvider,
- serviceImplementationDescription);
- try {
- lookUpService = createService.get();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new IllegalStateException(e);
- } catch (ExecutionException e) {
- if (e.getCause() instanceof RuntimeException) {
- throw (RuntimeException) e.getCause();
- }
- throw new IllegalStateException("Checked exception thrown", e);
- }
- }
- return lookUpService;
- }
-
- @Override
- public void inject(@Nonnull Object instance) {
- Class extends Object> classOfInstance = instance.getClass();
- Field[] dependencyFields = FieldUtils.getFieldsWithAnnotation(classOfInstance, Reference.class);
- for (Field field : dependencyFields) {
- ServiceDescription> serviceDescription = Util.serviceDescriptionFor(field);
- serviceDescription.getAnnotations().removeIf(annotation -> annotation instanceof Reference);
- Class> declaredClass = field.getDeclaringClass();
- Object object = this.getService(ConsumerFactory.build(declaredClass, serviceDescription)).getService();
- Util.inject(instance, object, field);
- }
- }
-
- @Override
- public void postConstruct(@Nonnull Object postConstructMe) {
- Util.postConstruct(postConstructMe);
+ public Configuration getConfiguration() {
+ return this.internalServiceLocator
+ .getService(
+ new ServiceConsumerImpl<>(this.getClass(), new ServiceDescriptionImpl<>(Configuration.class)))
+ .getService();
}
/**
- * This is the only method that gets ServiceProvider from the register and casts them to the correct return type
+ * The ServiceLocator of the DependencyInjection
*
- * @param
- * the type of the service
- * @param serviceDescription
- * the description of the wanted service
- * @return the ServiceProvider that can provide matching services for the given ServiceDescription
- * @throws ServiceNotFoundException
- * if no service is found for the given ServiceDescription
+ * @return the instance of the ServiceLocator owned by the DependencyInjection
*/
- @Nonnull
- @SuppressWarnings("unchecked")
- private ServiceProvider getServiceProvider(ServiceDescription serviceDescription,
- ServiceCreation> serviceCreation) {
- ServiceKey serviceKey = new ServiceKey<>(serviceDescription);
- synchronized (this.register) {
- if (!this.register.containsKey(serviceKey))
- throw new ServiceNotFoundException(serviceDescription, serviceCreation);
- return (ServiceProvider) this.register.get(serviceKey);
- }
- }
-
- @Override
- public T createAndInitialize(@Nonnull Class serviceClass) {
- if (!Util.isValidServiceClass(serviceClass)) {
- throw new IllegalArgumentException(
- "There is a problem with the class " + serviceClass.getName() + ". It can't be used as a Service");
- }
- T newInstance;
- try {
- newInstance = serviceClass.newInstance();
- } catch (InstantiationException | IllegalAccessException e) {
- throw new IllegalStateException(
- "The constructor of " + serviceClass.getName() + " should have been checked", e);
- }
- this.inject(newInstance);
- this.postConstruct(newInstance);
-
- return newInstance;
- }
-
- @Override
- public void preDestroy(@Nonnull Object destroyMe) {
- Util.preDestroy(destroyMe);
- }
-
- @Override
- public void shutdown() {
- // TODO manage the lifecycle
+ public ServiceLocator getServiceLocator() {
+ return this.internalServiceLocator
+ .getService(
+ new ServiceConsumerImpl<>(this.getClass(), new ServiceDescriptionImpl<>(ServiceLocator.class)))
+ .getService();
}
}
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/InternalServiceLocator.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/InternalServiceLocator.java
new file mode 100644
index 000000000..316dda523
--- /dev/null
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/InternalServiceLocator.java
@@ -0,0 +1,213 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.core.di;
+
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.function.Consumer;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.annotation.ParametersAreNullableByDefault;
+
+import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
+import de.unistuttgart.iaas.amyassist.amy.core.di.context.provider.ClassProvider;
+import de.unistuttgart.iaas.amyassist.amy.core.di.context.provider.StaticProvider;
+import de.unistuttgart.iaas.amyassist.amy.core.di.exception.DuplicateServiceException;
+import de.unistuttgart.iaas.amyassist.amy.core.di.exception.ServiceNotFoundException;
+import de.unistuttgart.iaas.amyassist.amy.core.di.provider.*;
+
+/**
+ * This is the core of the dependency injection. It contains the maps with ServiceProviders and instantiated Services.
+ * It is responsible for managing the services and creating new Services by need. All Operations are Thread safe and be
+ * mostly processed concurrently.
+ *
+ * @author Leon Kiefer
+ */
+@ParametersAreNullableByDefault
+public class InternalServiceLocator implements SimpleServiceLocator {
+ /**
+ * A register which maps a service description to it's service provider.
+ */
+ private final Map, ServiceProvider>> register;
+
+ private final Map, ServiceHandle>> servicePool;
+
+ private final Map, ServiceCreation>> serviceCreationInfos;
+
+ @Nonnull
+ private final ContextLocatorImpl contextLocator;
+
+ private Consumer> onRegister;
+
+ /**
+ *
+ * @param onRegister
+ */
+ public InternalServiceLocator(Consumer> onRegister) {
+ this.onRegister = onRegister;
+ this.register = new ConcurrentHashMap<>();
+ this.servicePool = new ConcurrentHashMap<>();
+ this.serviceCreationInfos = new ConcurrentHashMap<>();
+ this.contextLocator = new ContextLocatorImpl();
+
+ this.registerContextProvider("class", new ClassProvider());
+ this.register(new ServiceLocatorProvider(this));
+ this.register(new ConfigurationProvider(this));
+ }
+
+ public void register(@Nonnull ServiceProvider serviceProvider) {
+ ServiceDescription serviceDescription = serviceProvider.getServiceDescription();
+ ServiceKey serviceKey = new ServiceKey<>(serviceDescription);
+ synchronized (this.register) {
+ if (this.register.containsKey(serviceKey))
+ throw new DuplicateServiceException(serviceDescription);
+ this.register.put(serviceKey, serviceProvider);
+ }
+ }
+
+ public void onRegister(ClassServiceProvider classServiceProvider) {
+ this.onRegister.accept(classServiceProvider);
+ }
+
+ public void registerContextProvider(String key, StaticProvider> staticProvider) {
+ this.contextLocator.registerContextProvider(key, staticProvider);
+ }
+
+ @Override
+ public ServiceHandle getService(@Nonnull ServiceConsumer serviceConsumer) {
+ return this.getService(new ServiceCreation<>(serviceConsumer.getConsumerClass().getName()), serviceConsumer);
+ }
+
+ /**
+ * Get the service with the tracking of the dependency hierarchy.
+ *
+ * @param dependentServiceCreation
+ * @param serviceConsumer
+ * @param
+ * the type of the service
+ * @return the service handle of the service
+ */
+ ServiceHandle getService(@Nonnull ServiceCreation> dependentServiceCreation,
+ @Nonnull ServiceConsumer serviceConsumer) {
+ ServiceProvider provider = this.getServiceProvider(serviceConsumer.getServiceDescription(),
+ dependentServiceCreation);
+ ServiceInstantiationDescription serviceInstantiationDescription = provider
+ .getServiceInstantiationDescription(this.contextLocator, serviceConsumer);
+ if (serviceInstantiationDescription == null) {
+ throw new ServiceNotFoundException(serviceConsumer.getServiceDescription(), dependentServiceCreation);
+ }
+ return this.lookUpOrCreateService(dependentServiceCreation, provider, serviceInstantiationDescription);
+ }
+
+ @SuppressWarnings("unchecked")
+ @CheckForNull
+ private ServiceHandle lookUpService(@Nonnull ServiceProvider serviceProvider,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
+ ServicePoolKey> servicePoolKey = new ServicePoolKey<>(serviceProvider, serviceInstantiationDescription);
+
+ if (!this.servicePool.containsKey(servicePoolKey)) {
+ return null;
+ }
+ return (ServiceHandle) this.servicePool.get(servicePoolKey);
+ }
+
+ @SuppressWarnings("unchecked")
+ private Future> createService(@Nonnull ServiceCreation> dependentServiceCreation,
+ @Nonnull ServiceProvider serviceProvider,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
+ ServicePoolKey key = new ServicePoolKey<>(serviceProvider, serviceInstantiationDescription);
+ synchronized (this.servicePool) {
+ ServiceCreation serviceCreation;
+ if (this.serviceCreationInfos.containsKey(key)) {
+ serviceCreation = (ServiceCreation) this.serviceCreationInfos.get(key);
+ } else {
+ serviceCreation = new ServiceCreation<>(
+ serviceInstantiationDescription.getImplementationClass().getName());
+
+ serviceCreation.completableFuture = CompletableFuture.supplyAsync(() -> {
+ SimpleServiceLocatorImpl tempLocator = new SimpleServiceLocatorImpl(this, serviceCreation);
+ T service = serviceProvider.createService(tempLocator, serviceInstantiationDescription);
+ tempLocator.destroy();
+ ServiceHandle serviceHandle = new ServiceHandleImpl<>(service);
+ this.servicePool.put(key, serviceHandle);
+ return serviceHandle;
+ });
+
+ this.serviceCreationInfos.put(key, serviceCreation);
+ }
+ serviceCreation.addDependent(dependentServiceCreation);
+
+ return serviceCreation.completableFuture;
+ }
+ }
+
+ private ServiceHandle lookUpOrCreateService(@Nonnull ServiceCreation> dependentServiceCreationInfo,
+ @Nonnull ServiceProvider serviceProvider,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
+ ServiceHandle lookUpService = this.lookUpService(serviceProvider, serviceInstantiationDescription);
+ if (lookUpService == null) {
+ Future> createService = this.createService(dependentServiceCreationInfo, serviceProvider,
+ serviceInstantiationDescription);
+ try {
+ lookUpService = createService.get();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException(e);
+ } catch (ExecutionException e) {
+ if (e.getCause() instanceof RuntimeException) {
+ throw (RuntimeException) e.getCause();
+ }
+ throw new IllegalStateException("Checked exception thrown", e);
+ }
+ }
+ return lookUpService;
+ }
+
+ /**
+ * This is the only method that gets ServiceProvider from the register and casts them to the correct return type
+ *
+ * @param
+ * the type of the service
+ * @param serviceDescription
+ * the description of the wanted service
+ * @return the ServiceProvider that can provide matching services for the given ServiceDescription
+ * @throws ServiceNotFoundException
+ * if no service is found for the given ServiceDescription
+ */
+ @Nonnull
+ @SuppressWarnings("unchecked")
+ private ServiceProvider getServiceProvider(ServiceDescription serviceDescription,
+ ServiceCreation> serviceCreation) {
+ ServiceKey serviceKey = new ServiceKey<>(serviceDescription);
+ synchronized (this.register) {
+ if (!this.register.containsKey(serviceKey))
+ throw new ServiceNotFoundException(serviceDescription, serviceCreation);
+ return (ServiceProvider) this.register.get(serviceKey);
+ }
+ }
+}
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceCreation.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceCreation.java
index ea551c76d..77cb7d57b 100644
--- a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceCreation.java
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceCreation.java
@@ -38,7 +38,7 @@
* @param
* the type of the created service
*/
-class ServiceCreation {
+public class ServiceCreation {
CompletableFuture> completableFuture;
private final Set> dependents = new HashSet<>();
private final String name;
@@ -48,7 +48,7 @@ class ServiceCreation {
* the name for the debugging
*
*/
- public ServiceCreation(String name) {
+ ServiceCreation(String name) {
this.name = name;
}
@@ -91,6 +91,11 @@ public String toString() {
return this.print();
}
+ /**
+ * Create a tree of the dependents.
+ *
+ * @return the tree as string to print to the console
+ */
public String print() {
return this.print("\n");
}
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ServiceHandleImpl.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceHandleImpl.java
similarity index 87%
rename from di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ServiceHandleImpl.java
rename to di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceHandleImpl.java
index fc017566f..702599e63 100644
--- a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ServiceHandleImpl.java
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceHandleImpl.java
@@ -21,16 +21,18 @@
* For more information see notice.md
*/
-package de.unistuttgart.iaas.amyassist.amy.core.di.provider;
+package de.unistuttgart.iaas.amyassist.amy.core.di;
import javax.annotation.Nonnull;
+import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceHandle;
+
/**
* The implementation of the ServiceHandle
*
* @author Leon Kiefer
*/
-public class ServiceHandleImpl implements ServiceHandle {
+class ServiceHandleImpl implements ServiceHandle {
@Nonnull
private final T service;
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServicePoolKey.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServicePoolKey.java
index 6b0b56b0c..f3b9086d9 100644
--- a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServicePoolKey.java
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServicePoolKey.java
@@ -70,13 +70,13 @@ public ServicePoolKey(@Nonnull ServiceProvider serviceProvider, Map serviceProvider,
- ServiceImplementationDescription serviceImplementationDescription) {
- this(serviceProvider, serviceImplementationDescription.getContext(),
- serviceImplementationDescription.getServiceDescription().getServiceType(),
- serviceImplementationDescription.getImplementationClass());
+ ServiceInstantiationDescription serviceInstantiationDescription) {
+ this(serviceProvider, serviceInstantiationDescription.getContext(),
+ serviceInstantiationDescription.getServiceDescription().getServiceType(),
+ serviceInstantiationDescription.getImplementationClass());
}
@Override
@@ -96,7 +96,7 @@ public boolean equals(Object obj) {
return false;
if (this.getClass() != obj.getClass())
return false;
- ServicePoolKey other = (ServicePoolKey) obj;
+ ServicePoolKey> other = (ServicePoolKey>) obj;
if (!this.serviceProvider.equals(other.serviceProvider))
return false;
if (!this.context.equals(other.context))
@@ -106,8 +106,8 @@ public boolean equals(Object obj) {
@Override
public String toString() {
- return "Service type: " + this.serviceType.getName() + " ServiceProvider: " + this.serviceProvider
- + " Implementation class: " + this.implementationClass.getName() + " Context: " + this.context;
+ return "Service type: " + this.serviceType.getName() + "\nServiceProvider: " + this.serviceProvider
+ + "\nImplementation class: " + this.implementationClass.getName() + "\nContext: " + this.context;
}
}
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/SimpleServiceLocatorImpl.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/SimpleServiceLocatorImpl.java
index 2fef65fa8..ccebfce15 100644
--- a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/SimpleServiceLocatorImpl.java
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/SimpleServiceLocatorImpl.java
@@ -23,6 +23,8 @@
package de.unistuttgart.iaas.amyassist.amy.core.di;
+import javax.annotation.Nonnull;
+
import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceHandle;
@@ -31,22 +33,31 @@
*
* @author Leon Kiefer
*/
-public class SimpleServiceLocatorImpl implements SimpleServiceLocator {
+class SimpleServiceLocatorImpl implements SimpleServiceLocator {
- private DependencyInjection dependencyInjection;
+ private InternalServiceLocator internalServiceLocator;
private ServiceCreation> serviceCreationInfo;
/**
- * @param dependencyInjection
+ * @param internalServiceLocator
* @param serviceCreationInfo
*/
- public SimpleServiceLocatorImpl(DependencyInjection dependencyInjection, ServiceCreation> serviceCreationInfo) {
- this.dependencyInjection = dependencyInjection;
+ public SimpleServiceLocatorImpl(InternalServiceLocator internalServiceLocator,
+ ServiceCreation> serviceCreationInfo) {
+ this.internalServiceLocator = internalServiceLocator;
this.serviceCreationInfo = serviceCreationInfo;
}
@Override
- public ServiceHandle getService(ServiceConsumer serviceConsumer) {
- return this.dependencyInjection.getService(this.serviceCreationInfo, serviceConsumer);
+ public ServiceHandle getService(@Nonnull ServiceConsumer serviceConsumer) {
+ return this.internalServiceLocator.getService(this.serviceCreationInfo, serviceConsumer);
+ }
+
+ /**
+ * destroy the references
+ */
+ public void destroy() {
+ this.internalServiceLocator = null;
+ this.serviceCreationInfo = null;
}
}
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ClassIsNotAServiceException.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/exception/ClassIsNotAServiceException.java
similarity index 95%
rename from di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ClassIsNotAServiceException.java
rename to di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/exception/ClassIsNotAServiceException.java
index dfcaffe84..e9328e6a2 100644
--- a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ClassIsNotAServiceException.java
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/exception/ClassIsNotAServiceException.java
@@ -21,7 +21,7 @@
* For more information see notice.md
*/
-package de.unistuttgart.iaas.amyassist.amy.core.di;
+package de.unistuttgart.iaas.amyassist.amy.core.di.exception;
/**
* A exception of the dependency injection, signaling, that a given class is not a service.
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/DuplicateServiceException.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/exception/DuplicateServiceException.java
similarity index 91%
rename from di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/DuplicateServiceException.java
rename to di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/exception/DuplicateServiceException.java
index 3462aebe8..63e331dc1 100644
--- a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/DuplicateServiceException.java
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/exception/DuplicateServiceException.java
@@ -21,7 +21,9 @@
* For more information see notice.md
*/
-package de.unistuttgart.iaas.amyassist.amy.core.di;
+package de.unistuttgart.iaas.amyassist.amy.core.di.exception;
+
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescription;
/**
* A exception of the dependency injection, signaling, that a service is already registered
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceNotFoundException.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/exception/ServiceNotFoundException.java
similarity index 92%
rename from di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceNotFoundException.java
rename to di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/exception/ServiceNotFoundException.java
index 3b390b9e6..6c9347061 100644
--- a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceNotFoundException.java
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/exception/ServiceNotFoundException.java
@@ -21,7 +21,10 @@
* For more information see notice.md
*/
-package de.unistuttgart.iaas.amyassist.amy.core.di;
+package de.unistuttgart.iaas.amyassist.amy.core.di.exception;
+
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceCreation;
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescription;
/**
* A exception of the dependency injection
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ClassServiceProvider.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ClassServiceProvider.java
index c3f4f96d9..6c12c278c 100644
--- a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ClassServiceProvider.java
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ClassServiceProvider.java
@@ -35,12 +35,13 @@
import de.unistuttgart.iaas.amyassist.amy.core.di.ContextLocator;
import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescription;
-import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescriptionImpl;
-import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceImplementationDescription;
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceInstantiationDescription;
import de.unistuttgart.iaas.amyassist.amy.core.di.SimpleServiceLocator;
import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Context;
import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Reference;
import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceDescriptionImpl;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceInstantiationDescriptionImpl;
import de.unistuttgart.iaas.amyassist.amy.core.di.util.Util;
/**
@@ -70,10 +71,22 @@ public ClassServiceProvider(@Nonnull Class serviceType, @Nonnull Class exte
this(new ServiceDescriptionImpl<>(serviceType), cls);
}
+ /**
+ * The class which is the implementation of the Service.
+ *
+ * @return the class
+ */
+ @Nonnull
+ public Class extends T> getImplementationClass() {
+ return this.cls;
+ }
+
/**
*
* @param serviceDescription
+ * the description of the service that should be provided
* @param cls
+ * the service implementation class
*/
public ClassServiceProvider(@Nonnull ServiceDescription serviceDescription, @Nonnull Class extends T> cls) {
this.serviceDescription = serviceDescription;
@@ -99,7 +112,7 @@ public ClassServiceProvider(@Nonnull ServiceDescription serviceDescription, @
}
@Override
- public ServiceImplementationDescription getServiceImplementationDescription(@Nonnull ContextLocator locator,
+ public ServiceInstantiationDescription getServiceInstantiationDescription(@Nonnull ContextLocator locator,
@Nonnull ServiceConsumer serviceConsumer) {
HashMap map = new HashMap<>();
for (ContextInjectionPoint c : this.contextInjectionPoints) {
@@ -107,27 +120,28 @@ public ServiceImplementationDescription getServiceImplementationDescription(@
map.put(key, locator.getContextProvider(key).getContext(serviceConsumer));
}
- return new ServiceImplementationDescriptionImpl<>(serviceConsumer.getServiceDescription(), map, this.cls);
+ return new ServiceInstantiationDescriptionImpl<>(serviceConsumer.getServiceDescription(), map, this.cls);
}
@Override
- public @Nonnull ServiceHandle createService(@Nonnull SimpleServiceLocator locator,
- @Nonnull ServiceImplementationDescription serviceImplementationDescription) {
+ public @Nonnull T createService(@Nonnull SimpleServiceLocator locator,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
- @Nonnull T serviceInstance = this.createService();
+ @Nonnull
+ T serviceInstance = this.createService();
for (InjectionPoint injectionPoint : this.injectionPoints) {
ServiceConsumer> serviceConsumer = injectionPoint.getServiceConsumer();
ServiceHandle> serviceHandle = locator.getService(serviceConsumer);
injectionPoint.inject(serviceInstance, serviceHandle.getService());
}
- Map context = serviceImplementationDescription.getContext();
+ Map context = serviceInstantiationDescription.getContext();
for (ContextInjectionPoint contextInjectionPoint : this.contextInjectionPoints) {
contextInjectionPoint.inject(serviceInstance, context.get(contextInjectionPoint.getContextIdentifier()));
}
Util.postConstruct(serviceInstance);
- return new ServiceHandleImpl<>(serviceInstance);
+ return serviceInstance;
}
private T createService() {
@@ -140,8 +154,9 @@ private T createService() {
}
@Override
- public void dispose(ServiceHandle service) {
- Util.preDestroy(service.getService());
+ public void dispose(@Nonnull T service,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
+ Util.preDestroy(service);
}
}
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ConfigurationImpl.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ConfigurationImpl.java
new file mode 100644
index 000000000..74e05c7ab
--- /dev/null
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ConfigurationImpl.java
@@ -0,0 +1,67 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.core.di.provider;
+
+import javax.annotation.Nonnull;
+
+import de.unistuttgart.iaas.amyassist.amy.core.di.Configuration;
+import de.unistuttgart.iaas.amyassist.amy.core.di.InternalServiceLocator;
+import de.unistuttgart.iaas.amyassist.amy.core.di.context.provider.StaticProvider;
+import de.unistuttgart.iaas.amyassist.amy.core.di.util.ConfigurationUtil;
+
+/**
+ * Implementation of Configuration using the InternalServiceLocator.
+ *
+ * @author Leon Kiefer
+ */
+public class ConfigurationImpl implements Configuration {
+
+ private InternalServiceLocator internalServiceLocator;
+
+ /**
+ * @param internalServiceLocator
+ */
+ public ConfigurationImpl(InternalServiceLocator internalServiceLocator) {
+ this.internalServiceLocator = internalServiceLocator;
+ }
+
+ @Override
+ public void registerContextProvider(String key, StaticProvider> staticProvider) {
+ this.internalServiceLocator.registerContextProvider(key, staticProvider);
+ }
+
+ @Override
+ public void register(@Nonnull Class> cls) {
+ ClassServiceProvider> classServiceProvider = ConfigurationUtil.getClassServiceProvider(cls);
+
+ this.register(classServiceProvider);
+ this.internalServiceLocator.onRegister(classServiceProvider);
+ }
+
+ @Override
+ public void register(@Nonnull ServiceProvider serviceProvider) {
+ this.internalServiceLocator.register(serviceProvider);
+ }
+
+}
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ConfigurationProvider.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ConfigurationProvider.java
new file mode 100644
index 000000000..e7fe1ec44
--- /dev/null
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ConfigurationProvider.java
@@ -0,0 +1,74 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.core.di.provider;
+
+import javax.annotation.Nonnull;
+
+import de.unistuttgart.iaas.amyassist.amy.core.di.*;
+import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceDescriptionImpl;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceInstantiationDescriptionImpl;
+
+/**
+ * Creates the ConfigurationImpl service.
+ *
+ * @author Leon Kiefer
+ */
+public class ConfigurationProvider implements ServiceProvider {
+
+ private final InternalServiceLocator internalServiceLocator;
+
+ /**
+ * @param internalServiceLocator
+ */
+ public ConfigurationProvider(InternalServiceLocator internalServiceLocator) {
+ this.internalServiceLocator = internalServiceLocator;
+ }
+
+ @Override
+ @Nonnull
+ public ServiceDescription getServiceDescription() {
+ return new ServiceDescriptionImpl<>(Configuration.class);
+ }
+
+ @Override
+ public ServiceInstantiationDescription getServiceInstantiationDescription(
+ @Nonnull ContextLocator locator, @Nonnull ServiceConsumer serviceConsumer) {
+ return new ServiceInstantiationDescriptionImpl<>(this.getServiceDescription(), Configuration.class);
+ }
+
+ @Override
+ @Nonnull
+ public Configuration createService(@Nonnull SimpleServiceLocator locator,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
+ return new ConfigurationImpl(this.internalServiceLocator);
+ }
+
+ @Override
+ public void dispose(@Nonnull Configuration service,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
+ // nothing to do here
+ }
+
+}
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/InjectableServiceLocator.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/InjectableServiceLocator.java
new file mode 100644
index 000000000..5f12f6351
--- /dev/null
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/InjectableServiceLocator.java
@@ -0,0 +1,99 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.core.di.provider;
+
+import javax.annotation.Nonnull;
+
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescription;
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceLocator;
+import de.unistuttgart.iaas.amyassist.amy.core.di.SimpleServiceLocator;
+import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
+import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumerImpl;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceDescriptionImpl;
+import de.unistuttgart.iaas.amyassist.amy.core.di.util.ServiceLocatorUtil;
+import de.unistuttgart.iaas.amyassist.amy.core.di.util.Util;
+
+/**
+ * Facade for the {@link SimpleServiceLocator}
+ *
+ * @author Leon Kiefer
+ */
+class InjectableServiceLocator implements ServiceLocator {
+ @Nonnull
+ private final SimpleServiceLocator locator;
+ @Nonnull
+ private final Class> consumerClass;
+
+ /**
+ * @param locator
+ * the simple service locator used to resolve Services.
+ * @param consumerClass
+ * the class this instance is injected in
+ */
+ public InjectableServiceLocator(@Nonnull SimpleServiceLocator locator, @Nonnull Class> consumerClass) {
+ this.locator = locator;
+ this.consumerClass = consumerClass;
+ }
+
+ @Override
+ public T createAndInitialize(@Nonnull Class serviceClass) {
+ return ServiceLocatorUtil.createAndInitialize(serviceClass, this.locator);
+ }
+
+ @Override
+ public T getService(Class serviceType) {
+ return this.getService(new ServiceDescriptionImpl<>(serviceType)).getService();
+ }
+
+ @Override
+ public ServiceHandle getService(ServiceDescription serviceDescription) {
+ return this.getService(new ServiceConsumerImpl<>(this.consumerClass, serviceDescription));
+ }
+
+ @Override
+ public ServiceHandle getService(@Nonnull ServiceConsumer serviceConsumer) {
+ return this.locator.getService(serviceConsumer);
+ }
+
+ @Override
+ public void inject(@Nonnull Object injectMe) {
+ ServiceLocatorUtil.inject(injectMe, this.locator);
+ }
+
+ @Override
+ public void postConstruct(@Nonnull Object postConstructMe) {
+ Util.postConstruct(postConstructMe);
+ }
+
+ @Override
+ public void preDestroy(@Nonnull Object destroyMe) {
+ Util.preDestroy(destroyMe);
+ }
+
+ @Override
+ public void shutdown() {
+ throw new UnsupportedOperationException("InjectableServiceLocator can't be shutdown!");
+ }
+
+}
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ServiceLocatorProvider.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ServiceLocatorProvider.java
new file mode 100644
index 000000000..4fadb6c8b
--- /dev/null
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ServiceLocatorProvider.java
@@ -0,0 +1,81 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.core.di.provider;
+
+import java.util.Collections;
+
+import javax.annotation.Nonnull;
+
+import de.unistuttgart.iaas.amyassist.amy.core.di.*;
+import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceDescriptionImpl;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceInstantiationDescriptionImpl;
+
+/**
+ * Provider for the ServiceLocator in the DI with the correct consumer class.
+ *
+ * @author Leon Kiefer
+ */
+public class ServiceLocatorProvider implements ServiceProvider {
+
+ private SimpleServiceLocator simpleServiceLocator;
+
+ /**
+ * @param simpleServiceLocator
+ * used by the created ServiceLocators to resolve Services
+ */
+ public ServiceLocatorProvider(SimpleServiceLocator simpleServiceLocator) {
+ this.simpleServiceLocator = simpleServiceLocator;
+ }
+
+ @Override
+ @Nonnull
+ public ServiceDescription getServiceDescription() {
+ return new ServiceDescriptionImpl<>(ServiceLocator.class);
+ }
+
+ @Override
+ public ServiceInstantiationDescription getServiceInstantiationDescription(
+ @Nonnull ContextLocator locator, @Nonnull ServiceConsumer serviceConsumer) {
+ return new ServiceInstantiationDescriptionImpl<>(this.getServiceDescription(),
+ Collections.singletonMap("consumerClass",
+ locator.getContextProvider("class").getContext(serviceConsumer)),
+ InjectableServiceLocator.class);
+ }
+
+ @Override
+ @Nonnull
+ public ServiceLocator createService(@Nonnull SimpleServiceLocator locator,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
+ return new InjectableServiceLocator(this.simpleServiceLocator,
+ (Class>) serviceInstantiationDescription.getContext().get("consumerClass"));
+ }
+
+ @Override
+ public void dispose(@Nonnull ServiceLocator service,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
+ // nothing to do here
+ }
+
+}
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/SingletonServiceProvider.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/SingletonServiceProvider.java
index c7a6b19fb..3ed2a8196 100644
--- a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/SingletonServiceProvider.java
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/SingletonServiceProvider.java
@@ -27,10 +27,11 @@
import de.unistuttgart.iaas.amyassist.amy.core.di.ContextLocator;
import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescription;
-import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescriptionImpl;
-import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceImplementationDescription;
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceInstantiationDescription;
import de.unistuttgart.iaas.amyassist.amy.core.di.SimpleServiceLocator;
import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceDescriptionImpl;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceInstantiationDescriptionImpl;
/**
* A ServiceProvider which provides only a single existing instance
@@ -63,20 +64,21 @@ public SingletonServiceProvider(@Nonnull Class serviceType, @Nonnull T instan
}
@Override
- public ServiceImplementationDescription getServiceImplementationDescription(@Nonnull ContextLocator locator,
+ public ServiceInstantiationDescription getServiceInstantiationDescription(@Nonnull ContextLocator locator,
@Nonnull ServiceConsumer serviceConsumer) {
- return new ServiceImplementationDescriptionImpl<>(serviceConsumer.getServiceDescription(),
+ return new ServiceInstantiationDescriptionImpl<>(serviceConsumer.getServiceDescription(),
this.instance.getClass());
}
@Override
- public @Nonnull ServiceHandle createService(@Nonnull SimpleServiceLocator locator,
- @Nonnull ServiceImplementationDescription serviceImplementationDescription) {
- return new ServiceHandleImpl<>(this.instance);
+ public @Nonnull T createService(@Nonnull SimpleServiceLocator locator,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
+ return this.instance;
}
@Override
- public void dispose(ServiceHandle service) {
+ public void dispose(@Nonnull T service,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
// singleton can not be disposed
}
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceDescriptionImpl.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/runtime/ServiceDescriptionImpl.java
similarity index 84%
rename from di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceDescriptionImpl.java
rename to di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/runtime/ServiceDescriptionImpl.java
index 9e25ffb20..5071914f9 100644
--- a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceDescriptionImpl.java
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/runtime/ServiceDescriptionImpl.java
@@ -21,13 +21,15 @@
* For more information see notice.md
*/
-package de.unistuttgart.iaas.amyassist.amy.core.di;
+package de.unistuttgart.iaas.amyassist.amy.core.di.runtime;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescription;
+
/**
* Implementation of ServiceDescription interface
*
@@ -42,8 +44,9 @@ public class ServiceDescriptionImpl implements ServiceDescription {
/**
* @param serviceType
+ * the type of the Service given as class
* @param annotations
- *
+ * the qualifier annotations
*/
public ServiceDescriptionImpl(Class serviceType, Set annotations) {
this.serviceType = serviceType;
@@ -51,7 +54,10 @@ public ServiceDescriptionImpl(Class serviceType, Set annotations)
}
/**
- * @param serviceType2
+ * Create a Service description with no qualifiers
+ *
+ * @param serviceType
+ * the type of the Service given as class
*/
public ServiceDescriptionImpl(Class serviceType) {
this.serviceType = serviceType;
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ServiceImplementationDescriptionImpl.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/runtime/ServiceInstantiationDescriptionImpl.java
similarity index 68%
rename from di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ServiceImplementationDescriptionImpl.java
rename to di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/runtime/ServiceInstantiationDescriptionImpl.java
index 4f80a9f31..e96e0034d 100644
--- a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/provider/ServiceImplementationDescriptionImpl.java
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/runtime/ServiceInstantiationDescriptionImpl.java
@@ -21,7 +21,7 @@
* For more information see notice.md
*/
-package de.unistuttgart.iaas.amyassist.amy.core.di.provider;
+package de.unistuttgart.iaas.amyassist.amy.core.di.runtime;
import java.util.Collections;
import java.util.Map;
@@ -29,16 +29,16 @@
import javax.annotation.Nonnull;
import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescription;
-import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceImplementationDescription;
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceInstantiationDescription;
/**
- * Immutable implementation of the ServiceImplementationDescription
+ * Immutable implementation of the ServiceInstantiationDescription
*
* @author Leon Kiefer
* @param
* the type of the service
*/
-public class ServiceImplementationDescriptionImpl implements ServiceImplementationDescription {
+public class ServiceInstantiationDescriptionImpl implements ServiceInstantiationDescription {
@Nonnull
private final ServiceDescription serviceDescription;
@Nonnull
@@ -48,10 +48,13 @@ public class ServiceImplementationDescriptionImpl implements ServiceImplement
/**
* @param serviceDescription
+ * {@link #getServiceDescription()}
* @param context
+ * {@link #getContext()}
* @param cls
+ * the implementation of the Service {@link #getImplementationClass()}
*/
- public ServiceImplementationDescriptionImpl(@Nonnull ServiceDescription serviceDescription,
+ public ServiceInstantiationDescriptionImpl(@Nonnull ServiceDescription serviceDescription,
@Nonnull Map context, @Nonnull Class> cls) {
this.serviceDescription = serviceDescription;
this.context = context;
@@ -59,12 +62,15 @@ public ServiceImplementationDescriptionImpl(@Nonnull ServiceDescription servi
}
/**
- * Create a new ServiceImplementationDescription with a empty context.
+ * Create a new ServiceInstantiationDescription with a empty context.
*
* @param serviceDescription
+ * {@link #getServiceDescription()}
* @param cls
+ * the implementation of the Service {@link #getImplementationClass()}
*/
- public ServiceImplementationDescriptionImpl(@Nonnull ServiceDescription serviceDescription, @Nonnull Class> cls) {
+ public ServiceInstantiationDescriptionImpl(@Nonnull ServiceDescription serviceDescription,
+ @Nonnull Class> cls) {
this.serviceDescription = serviceDescription;
this.context = Collections.emptyMap();
this.cls = cls;
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/util/ConfigurationUtil.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/util/ConfigurationUtil.java
new file mode 100644
index 000000000..a82c00570
--- /dev/null
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/util/ConfigurationUtil.java
@@ -0,0 +1,84 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.core.di.util;
+
+import javax.annotation.Nonnull;
+
+import de.unistuttgart.iaas.amyassist.amy.core.di.Configuration;
+import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Service;
+import de.unistuttgart.iaas.amyassist.amy.core.di.exception.ClassIsNotAServiceException;
+import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ClassServiceProvider;
+
+/**
+ * Utility for the registration of classes with the ClassServiceProvider.
+ *
+ * @author Leon Kiefer
+ */
+public class ConfigurationUtil {
+
+ private ConfigurationUtil() {
+ // hide constructor
+ }
+
+ /**
+ *
+ * @param cls
+ * the implementation class for which the ClassServiceProvider should be created
+ * @return the ClassServiceProvider which provides Services of the given class
+ * @throws ClassIsNotAServiceException
+ * if the @Service annotation is not present on the given class
+ * @see Configuration#register(Class)
+ */
+ public static ClassServiceProvider> getClassServiceProvider(@Nonnull Class> cls) {
+ Service annotation = cls.getAnnotation(Service.class);
+ if (annotation == null)
+ throw new ClassIsNotAServiceException(cls);
+ @Nonnull
+ Class> serviceType = annotation.value();
+ if (serviceType.equals(Void.class)) {
+ Class>[] interfaces = cls.getInterfaces();
+ if (interfaces.length == 1) {
+ // annotations can not have null values
+ serviceType = interfaces[0];
+ } else if (interfaces.length == 0) {
+ serviceType = cls;
+ } else {
+ throw new IllegalArgumentException("The type of the service implementation " + cls.getName()
+ + " is ambiguous, because the type is not given by the annotation and multiple interfaces are implemented."
+ + " Please specify which type this service should have.");
+ }
+ }
+ return registerClass(cls, serviceType);
+ }
+
+ private static ClassServiceProvider registerClass(@Nonnull Class cls, @Nonnull Class serviceType) {
+ if (!serviceType.isAssignableFrom(cls)) {
+ throw new IllegalArgumentException(
+ "The specified service type " + serviceType.getName() + " is not assignable from " + cls.getName());
+ }
+ @SuppressWarnings("unchecked")
+ Class extends T> implementationClass = (Class extends T>) cls;
+ return new ClassServiceProvider<>(serviceType, implementationClass);
+ }
+}
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/util/ServiceLocatorUtil.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/util/ServiceLocatorUtil.java
new file mode 100644
index 000000000..f98a1d24d
--- /dev/null
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/util/ServiceLocatorUtil.java
@@ -0,0 +1,90 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.core.di.util;
+
+import java.lang.reflect.Field;
+
+import javax.annotation.Nonnull;
+
+import org.apache.commons.lang3.reflect.FieldUtils;
+
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescription;
+import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceLocator;
+import de.unistuttgart.iaas.amyassist.amy.core.di.SimpleServiceLocator;
+import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Reference;
+import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ConsumerFactory;
+
+/**
+ * Implementation of operations using the SimpleServiceLocator.
+ *
+ * @author Leon Kiefer
+ */
+public class ServiceLocatorUtil {
+ private ServiceLocatorUtil() {
+ // hide constructor
+ }
+
+ /**
+ *
+ * @param
+ * @param serviceClass
+ * @param locator
+ * @return the created instance of the given class
+ * @see ServiceLocator#createAndInitialize(Class)
+ */
+ public static T createAndInitialize(@Nonnull Class serviceClass, @Nonnull SimpleServiceLocator locator) {
+ if (!Util.isValidServiceClass(serviceClass)) {
+ throw new IllegalArgumentException(
+ "There is a problem with the class " + serviceClass.getName() + ". It can't be used as a Service");
+ }
+ T newInstance;
+ try {
+ newInstance = serviceClass.newInstance();
+ } catch (InstantiationException | IllegalAccessException e) {
+ throw new IllegalStateException(
+ "The constructor of " + serviceClass.getName() + " should have been checked", e);
+ }
+ inject(newInstance, locator);
+ Util.postConstruct(newInstance);
+
+ return newInstance;
+ }
+
+ /**
+ * @param instance
+ * @param locator
+ * @see ServiceLocator#inject(Object)
+ */
+ public static void inject(@Nonnull Object instance, @Nonnull SimpleServiceLocator locator) {
+ Class extends Object> classOfInstance = instance.getClass();
+ Field[] dependencyFields = FieldUtils.getFieldsWithAnnotation(classOfInstance, Reference.class);
+ for (Field field : dependencyFields) {
+ ServiceDescription> serviceDescription = Util.serviceDescriptionFor(field);
+ serviceDescription.getAnnotations().removeIf(annotation -> annotation instanceof Reference);
+ Class> declaredClass = field.getDeclaringClass();
+ Object object = locator.getService(ConsumerFactory.build(declaredClass, serviceDescription)).getService();
+ Util.inject(instance, object, field);
+ }
+ }
+}
diff --git a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/util/Util.java b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/util/Util.java
index 7780cb1b3..a9fd809ce 100644
--- a/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/util/Util.java
+++ b/di/src/main/java/de/unistuttgart/iaas/amyassist/amy/core/di/util/Util.java
@@ -38,11 +38,11 @@
import org.apache.commons.lang3.reflect.MethodUtils;
import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescription;
-import de.unistuttgart.iaas.amyassist.amy.core.di.ServiceDescriptionImpl;
import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Context;
import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.PostConstruct;
import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.PreDestroy;
import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Reference;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceDescriptionImpl;
/**
* Util for checks and java reflection
diff --git a/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjectionProviderTest.java b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjectionProviderTest.java
new file mode 100644
index 000000000..2ba1d91c3
--- /dev/null
+++ b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjectionProviderTest.java
@@ -0,0 +1,97 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.core.di;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import javax.annotation.Nonnull;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import de.unistuttgart.iaas.amyassist.amy.core.di.consumer.ServiceConsumer;
+import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceProvider;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceDescriptionImpl;
+import de.unistuttgart.iaas.amyassist.amy.core.di.runtime.ServiceInstantiationDescriptionImpl;
+import uk.org.lidalia.slf4jtest.TestLoggerFactory;
+
+/**
+ * Test for DependencyInjection
+ *
+ * @author Leon Kiefer
+ */
+class DependencyInjectionProviderTest {
+
+ private DependencyInjection dependencyInjection;
+
+ @BeforeEach
+ public void setup() {
+ this.dependencyInjection = new DependencyInjection();
+ }
+
+ @Test
+ void testServiceAnnotation() {
+ this.dependencyInjection.getConfiguration().register(new ServiceProvider() {
+
+ @Override
+ @Nonnull
+ public ServiceDescription getServiceDescription() {
+ return new ServiceDescriptionImpl<>(ServiceWithServiceLocator.class);
+ }
+
+ @Override
+ public ServiceInstantiationDescription getServiceInstantiationDescription(
+ @Nonnull ContextLocator locator,
+ @Nonnull ServiceConsumer serviceConsumer) {
+ return new ServiceInstantiationDescriptionImpl<>(this.getServiceDescription(),
+ ServiceWithServiceLocator.class);
+ }
+
+ @Override
+ @Nonnull
+ public ServiceWithServiceLocator createService(@Nonnull SimpleServiceLocator locator,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
+ return new ServiceWithServiceLocator(locator);
+ }
+
+ @Override
+ public void dispose(@Nonnull ServiceWithServiceLocator service,
+ @Nonnull ServiceInstantiationDescription serviceInstantiationDescription) {
+ }
+ });
+ ServiceWithServiceLocator service = this.dependencyInjection.getServiceLocator()
+ .getService(ServiceWithServiceLocator.class);
+
+ ServiceConsumer serviceConsumer = Mockito.mock(ServiceConsumer.class);
+ assertThrows(RuntimeException.class, () -> service.getLocator().getService(serviceConsumer));
+ }
+
+ @AfterEach
+ public void clearLoggers() {
+ TestLoggerFactory.clear();
+ }
+
+}
diff --git a/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjectionScopeTest.java b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjectionScopeTest.java
index 43a73b7f3..4befdb700 100644
--- a/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjectionScopeTest.java
+++ b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjectionScopeTest.java
@@ -45,6 +45,8 @@
*/
public class DependencyInjectionScopeTest {
private DependencyInjection dependencyInjection;
+ private Configuration configuration;
+ private ServiceLocator serviceLocator;
/**
* Setup
@@ -52,6 +54,8 @@ public class DependencyInjectionScopeTest {
@BeforeEach
public void setup() {
this.dependencyInjection = new DependencyInjection();
+ this.configuration = this.dependencyInjection.getConfiguration();
+ this.serviceLocator = this.dependencyInjection.getServiceLocator();
}
// Scope GLOBAL and once are already being tested by the other test.
@@ -61,14 +65,14 @@ public void setup() {
*/
@Test
public void testScopeClass() {
- this.dependencyInjection.register(Service11.class);
- this.dependencyInjection.register(Service12.class);
- this.dependencyInjection.register(Service13.class);
+ this.configuration.register(Service11.class);
+ this.configuration.register(Service12.class);
+ this.configuration.register(Service13.class);
- Service11 s1 = this.dependencyInjection.getService(Service11.class);
+ Service11 s1 = this.serviceLocator.getService(Service11.class);
s1.s.id = 4;
- Service13 s2 = this.dependencyInjection.getService(Service13.class);
+ Service13 s2 = this.serviceLocator.getService(Service13.class);
assertThat(s1.s, not(theInstance(s2.s1)));
assertThat(s1, theInstance(s2.s2));
assertThat(s1.s, theInstance(s2.s2.s));
@@ -79,13 +83,13 @@ public void testScopeClass() {
*/
@Test
public void testScopePlugin() {
- this.dependencyInjection.register(Service14.class);
- this.dependencyInjection.register(Service15.class);
- this.dependencyInjection.register(Service16.class);
- this.dependencyInjection.register(ServiceForPlugins.class);
+ this.configuration.register(Service14.class);
+ this.configuration.register(Service15.class);
+ this.configuration.register(Service16.class);
+ this.configuration.register(ServiceForPlugins.class);
Map, Integer> plugins = new HashMap<>();
- this.dependencyInjection.registerContextProvider("custom", new CustomProvider<>(plugins));
+ this.configuration.registerContextProvider("custom", new CustomProvider<>(plugins));
Class> cls1 = Service14.class;
Class> cls2 = Service15.class;
@@ -95,10 +99,10 @@ public void testScopePlugin() {
plugins.put(cls2, 1);
plugins.put(cls3, 2);
- Service14 s1 = this.dependencyInjection.getService(Service14.class);
- Service15 s2 = this.dependencyInjection.getService(Service15.class);
+ Service14 s1 = this.serviceLocator.getService(Service14.class);
+ Service15 s2 = this.serviceLocator.getService(Service15.class);
- Service16 s3 = this.dependencyInjection.getService(Service16.class);
+ Service16 s3 = this.serviceLocator.getService(Service16.class);
assertThat(s1.s, theInstance(s2.s));
assertThat(s1.s, not(theInstance(s3.s)));
@@ -106,42 +110,42 @@ public void testScopePlugin() {
@Test
public void testContextValue() {
- this.dependencyInjection.register(Service11.class);
- this.dependencyInjection.register(Service12.class);
- this.dependencyInjection.register(Service13.class);
+ this.configuration.register(Service11.class);
+ this.configuration.register(Service12.class);
+ this.configuration.register(Service13.class);
- Service11 s1 = this.dependencyInjection.getService(Service11.class);
+ Service11 s1 = this.serviceLocator.getService(Service11.class);
assertThat(s1.s.getConsumerClass(), notNullValue());
assertThat(s1.s.getConsumerClass(), equalTo(Service11.class));
}
@Test
public void testInjectContextValue() {
- this.dependencyInjection.register(Service12.class);
+ this.configuration.register(Service12.class);
Service11 s1 = new Service11();
- this.dependencyInjection.inject(s1);
+ this.serviceLocator.inject(s1);
assertThat(s1.s.getConsumerClass(), notNullValue());
assertThat(s1.s.getConsumerClass(), equalTo(Service11.class));
}
@Test
public void testNoContextProvider() {
- this.dependencyInjection.register(Service16.class);
- this.dependencyInjection.register(ServiceForPlugins.class);
+ this.configuration.register(Service16.class);
+ this.configuration.register(ServiceForPlugins.class);
String message = assertThrows(NoSuchElementException.class,
- () -> this.dependencyInjection.getService(Service16.class)).getMessage();
+ () -> this.serviceLocator.getService(Service16.class)).getMessage();
assertThat(message, equalTo("custom"));
}
@Test
public void testContextProviderWithAbstractClass() {
- this.dependencyInjection.register(Service12.class);
- this.dependencyInjection.register(ServiceTemplate1.class);
+ this.configuration.register(Service12.class);
+ this.configuration.register(ServiceTemplate1.class);
- ServiceTemplate1 service = this.dependencyInjection.getService(ServiceTemplate1.class);
+ ServiceTemplate1 service = this.serviceLocator.getService(ServiceTemplate1.class);
assertThat(service.getService12(), is(notNullValue()));
assertThat(service.getService12FromAbstractServiceTemplate(), is(notNullValue()));
diff --git a/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjectionTest.java b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjectionTest.java
index f596371e5..31ae55feb 100644
--- a/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjectionTest.java
+++ b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/DependencyInjectionTest.java
@@ -33,6 +33,9 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import de.unistuttgart.iaas.amyassist.amy.core.di.exception.ClassIsNotAServiceException;
+import de.unistuttgart.iaas.amyassist.amy.core.di.exception.DuplicateServiceException;
+import de.unistuttgart.iaas.amyassist.amy.core.di.exception.ServiceNotFoundException;
import de.unistuttgart.iaas.amyassist.amy.core.di.provider.ServiceProvider;
import de.unistuttgart.iaas.amyassist.amy.core.di.provider.SingletonServiceProvider;
import uk.org.lidalia.slf4jtest.TestLogger;
@@ -46,57 +49,61 @@
class DependencyInjectionTest {
private DependencyInjection dependencyInjection;
+ private Configuration configuration;
+ private ServiceLocator serviceLocator;
@BeforeEach
public void setup() {
this.dependencyInjection = new DependencyInjection();
- this.dependencyInjection.register(Service1.class);
- this.dependencyInjection.register(Service2.class);
- this.dependencyInjection.register(Service3.class);
+ this.configuration = this.dependencyInjection.getConfiguration();
+ this.serviceLocator = this.dependencyInjection.getServiceLocator();
+ this.configuration.register(Service1.class);
+ this.configuration.register(Service2.class);
+ this.configuration.register(Service3.class);
}
@Test
void testServiceAnnotation() {
- Service1 service1 = this.dependencyInjection.getService(Service1.class);
+ Service1 service1 = this.serviceLocator.getService(Service1.class);
assertThat(service1, is(instanceOf(Service1.class)));
}
@Test
void testDependencyInjection() {
- Service2 service2 = this.dependencyInjection.getService(Service2.class);
+ Service2 service2 = this.serviceLocator.getService(Service2.class);
assertThat(service2.checkServices(), is(true));
}
@Test
void testServiceRegistry() {
- Service1 s1 = this.dependencyInjection.getService(Service1.class);
- Service1 s2 = this.dependencyInjection.getService(Service1.class);
+ Service1 s1 = this.serviceLocator.getService(Service1.class);
+ Service1 s2 = this.serviceLocator.getService(Service1.class);
assertThat(s1, theInstance(s2));
}
@Test
void testCircularDependencies() {
- this.dependencyInjection.register(Service4.class);
- this.dependencyInjection.register(Service5.class);
+ this.configuration.register(Service4.class);
+ this.configuration.register(Service5.class);
assertTimeoutPreemptively(Duration.ofSeconds(1), () -> {
- assertThrows(RuntimeException.class, () -> this.dependencyInjection.getService(Service4.class));
+ assertThrows(RuntimeException.class, () -> this.serviceLocator.getService(Service4.class));
});
}
@Test()
void testRegisterNotAService() {
String message = assertThrows(ClassIsNotAServiceException.class,
- () -> this.dependencyInjection.register(NotAService.class)).getMessage();
+ () -> this.configuration.register(NotAService.class)).getMessage();
assertThat(message, equalTo("The class " + NotAService.class.getName() + " is not a Service"));
}
@Test()
void testServiceNotFoundException() {
- this.dependencyInjection.register(Service6.class);
+ this.configuration.register(Service6.class);
String message = assertThrows(ServiceNotFoundException.class,
- () -> this.dependencyInjection.getService(Service6.class)).getMessage();
+ () -> this.serviceLocator.getService(Service6.class)).getMessage();
assertThat(message, equalTo("No Service of type " + Service7API.class.getName()
+ " with qualifier [] is registered in the DI." + "\nRequired by:"
@@ -114,21 +121,21 @@ void testServiceNotFoundException() {
@Test()
void testDuplicateServiceException() {
- this.dependencyInjection.register(Service6.class);
- assertThrows(DuplicateServiceException.class, () -> this.dependencyInjection.register(Service6.class));
+ this.configuration.register(Service6.class);
+ assertThrows(DuplicateServiceException.class, () -> this.configuration.register(Service6.class));
}
@Test()
void testDuplicateServiceException2() {
- this.dependencyInjection.register(new SingletonServiceProvider<>(Service7API.class, new Service7()));
- assertThrows(DuplicateServiceException.class, () -> this.dependencyInjection
- .register(new SingletonServiceProvider<>(Service7API.class, new Service7())));
+ this.configuration.register(new SingletonServiceProvider<>(Service7API.class, new Service7()));
+ assertThrows(DuplicateServiceException.class,
+ () -> this.configuration.register(new SingletonServiceProvider<>(Service7API.class, new Service7())));
}
@Test()
void testConstructorCheck() {
String message = assertThrows(IllegalArgumentException.class,
- () -> this.dependencyInjection.register(ServiceWithConstructor.class)).getMessage();
+ () -> this.configuration.register(ServiceWithConstructor.class)).getMessage();
assertThat(message, equalTo("There is a problem with the class " + ServiceWithConstructor.class.getName()
+ ". It can't be used as a Service"));
@@ -138,49 +145,48 @@ void testConstructorCheck() {
void testServiceWithDuplicateDependency() {
TestLogger logger = TestLoggerFactory.getTestLogger(ServiceProvider.class);
- this.dependencyInjection.register(ServiceWithDuplicateDependency.class);
- ServiceWithDuplicateDependency service = this.dependencyInjection
- .getService(ServiceWithDuplicateDependency.class);
+ this.configuration.register(ServiceWithDuplicateDependency.class);
+ ServiceWithDuplicateDependency service = this.serviceLocator.getService(ServiceWithDuplicateDependency.class);
assertThat(service, is(notNullValue()));
}
@Test()
void testPostConstruct() {
- Service1 service1 = this.dependencyInjection.getService(Service1.class);
+ Service1 service1 = this.serviceLocator.getService(Service1.class);
assertThat(service1.init, is(1));
- this.dependencyInjection.postConstruct(service1);
+ this.serviceLocator.postConstruct(service1);
assertThat(service1.init, is(2));
}
@Test()
void testCreateAndInitializeService() {
- Service2 s2_1 = this.dependencyInjection.getService(Service2.class);
- Service2 s2_2 = this.dependencyInjection.createAndInitialize(Service2.class);
+ Service2 s2_1 = this.serviceLocator.getService(Service2.class);
+ Service2 s2_2 = this.serviceLocator.createAndInitialize(Service2.class);
assertThat(s2_1, not(theInstance(s2_2)));
assertThat(s2_1.getService3(), theInstance(s2_2.getService3()));
}
@Test()
void testCreateAndInitializeServicePostConstruct() {
- Service18 service18 = this.dependencyInjection.createAndInitialize(Service18.class);
+ Service18 service18 = this.serviceLocator.createAndInitialize(Service18.class);
assertThat(service18.setup, is(true));
}
@Test()
void testCreateNotAService() {
- NotAService2 nas = this.dependencyInjection.createAndInitialize(NotAService2.class);
+ NotAService2 nas = this.serviceLocator.createAndInitialize(NotAService2.class);
assertThat(nas.getInit(), is(1));
- Service1 s1 = this.dependencyInjection.getService(Service1.class);
- this.dependencyInjection.postConstruct(s1);
+ Service1 s1 = this.serviceLocator.getService(Service1.class);
+ this.serviceLocator.postConstruct(s1);
assertThat(nas.getInit(), is(2));
- NotAService2 nas2 = this.dependencyInjection.createAndInitialize(NotAService2.class);
+ NotAService2 nas2 = this.serviceLocator.createAndInitialize(NotAService2.class);
assertThat(nas2, not(theInstance(nas)));
}
@Test()
void testCreateIllegalAccessException() {
String message = assertThrows(IllegalArgumentException.class,
- () -> this.dependencyInjection.createAndInitialize(Service8.class)).getMessage();
+ () -> this.serviceLocator.createAndInitialize(Service8.class)).getMessage();
assertThat(message, equalTo(
"There is a problem with the class " + Service8.class.getName() + ". It can't be used as a Service"));
@@ -189,19 +195,19 @@ void testCreateIllegalAccessException() {
@Test()
void testSingletonServiceProvider() {
Service7 service7 = new Service7();
- this.dependencyInjection.register(new SingletonServiceProvider<>(Service7API.class, service7));
- assertThat(this.dependencyInjection.getService(Service7API.class), is(theInstance(service7)));
+ this.configuration.register(new SingletonServiceProvider<>(Service7API.class, service7));
+ assertThat(this.serviceLocator.getService(Service7API.class), is(theInstance(service7)));
}
@Test()
void testAbstractService() {
- assertThrows(IllegalArgumentException.class, () -> this.dependencyInjection.register(AbstractService.class));
+ assertThrows(IllegalArgumentException.class, () -> this.configuration.register(AbstractService.class));
}
@Test()
void testInject() {
Service10 service10 = new Service10(10);
- this.dependencyInjection.inject(service10);
+ this.serviceLocator.inject(service10);
assertThat(service10.isInit(), is(false));
assertThat(service10.getService1(), is(notNullValue()));
assertThat(service10.getService1(), is(instanceOf(Service1.class)));
@@ -209,24 +215,24 @@ void testInject() {
@Test()
void testServiceType() {
- assertThrows(IllegalArgumentException.class, () -> this.dependencyInjection.register(Service17.class));
+ assertThrows(IllegalArgumentException.class, () -> this.configuration.register(Service17.class));
}
@Test()
void testRegisterServiceTypeFromInterface() {
- this.dependencyInjection.register(Service7Impl.class);
- assertThat(this.dependencyInjection.getService(Service7API.class), is(notNullValue()));
+ this.configuration.register(Service7Impl.class);
+ assertThat(this.serviceLocator.getService(Service7API.class), is(notNullValue()));
}
@Test()
void testRegisterServiceTypeFromMultipleInterfaces() {
assertThrows(IllegalArgumentException.class,
- () -> this.dependencyInjection.register(ServiceImplementingMultipleInterfaces.class));
+ () -> this.configuration.register(ServiceImplementingMultipleInterfaces.class));
}
@Test()
void testCreateAndInitialize() {
- Service1 service1 = this.dependencyInjection.createAndInitialize(Service1.class);
+ Service1 service1 = this.serviceLocator.createAndInitialize(Service1.class);
assertThat(service1, notNullValue());
assertThat(service1.init, is(1));
}
diff --git a/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceWithServiceLocator.java b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceWithServiceLocator.java
new file mode 100644
index 000000000..e78060ea6
--- /dev/null
+++ b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/ServiceWithServiceLocator.java
@@ -0,0 +1,46 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.core.di;
+
+/**
+ * Test Service to test the use of the ServiceLocator.
+ *
+ * @author Leon Kiefer
+ */
+public class ServiceWithServiceLocator {
+
+ private SimpleServiceLocator locator;
+
+ public SimpleServiceLocator getLocator() {
+ return this.locator;
+ }
+
+ /**
+ * @param locator
+ */
+ public ServiceWithServiceLocator(SimpleServiceLocator locator) {
+ this.locator = locator;
+ }
+
+}
diff --git a/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/context/provider/TestStaticProvider.java b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/context/provider/TestStaticProvider.java
index 022e71e07..ecb0ec648 100644
--- a/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/context/provider/TestStaticProvider.java
+++ b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/context/provider/TestStaticProvider.java
@@ -45,15 +45,16 @@ public void setup() {
@Test
void testUseAnnoations() {
- this.dependencyInjection.register(ServiceWithAnnotationContext.class);
- this.dependencyInjection.register(ServiceWithDependencies.class);
+ this.dependencyInjection.getConfiguration().register(ServiceWithAnnotationContext.class);
+ this.dependencyInjection.getConfiguration().register(ServiceWithDependencies.class);
- this.dependencyInjection.registerContextProvider("annotation",
+ this.dependencyInjection.getConfiguration().registerContextProvider("annotation",
consumer -> consumer.getServiceDescription().getAnnotations().stream()
.filter(annotation -> annotation instanceof AnnotatoinWithValue).findFirst()
.map(annotation -> ((AnnotatoinWithValue) annotation).value()).orElse(null));
- ServiceWithDependencies service = this.dependencyInjection.getService(ServiceWithDependencies.class);
+ ServiceWithDependencies service = this.dependencyInjection.getServiceLocator()
+ .getService(ServiceWithDependencies.class);
assertThat(service.getValueOfService1(), is("1"));
assertThat(service.getValueOfService2(), is("2"));
}
diff --git a/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/extension/ExtensionTest.java b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/extension/ExtensionTest.java
index 31b1bf22d..6cb80436e 100644
--- a/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/extension/ExtensionTest.java
+++ b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/extension/ExtensionTest.java
@@ -55,7 +55,17 @@ void testPostConstruct() {
@Test
void testOnRegister() {
- this.dependencyInjection.register(Service1.class);
+ this.dependencyInjection.getConfiguration().register(Service1.class);
+
+ Mockito.verify(this.mockExtension).onRegister(ArgumentMatchers.any(), ArgumentMatchers.eq(Service1.class));
+ }
+
+ @Test
+ void testOnRegisterFromService() {
+ this.dependencyInjection.getConfiguration().register(ServiceConfigurationChange.class);
+ Mockito.verify(this.mockExtension).onRegister(ArgumentMatchers.any(),
+ ArgumentMatchers.eq(ServiceConfigurationChange.class));
+ this.dependencyInjection.getServiceLocator().getService(ServiceConfigurationChange.class).install();
Mockito.verify(this.mockExtension).onRegister(ArgumentMatchers.any(), ArgumentMatchers.eq(Service1.class));
}
diff --git a/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/extension/ServiceConfigurationChange.java b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/extension/ServiceConfigurationChange.java
new file mode 100644
index 000000000..994d2b72f
--- /dev/null
+++ b/di/src/test/java/de/unistuttgart/iaas/amyassist/amy/core/di/extension/ServiceConfigurationChange.java
@@ -0,0 +1,45 @@
+/*
+ * This source file is part of the Amy open source project.
+ * For more information see github.com/AmyAssist
+ *
+ * Copyright (c) 2018 the Amy project authors.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For more information see notice.md
+ */
+
+package de.unistuttgart.iaas.amyassist.amy.core.di.extension;
+
+import de.unistuttgart.iaas.amyassist.amy.core.di.Configuration;
+import de.unistuttgart.iaas.amyassist.amy.core.di.Service1;
+import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Reference;
+import de.unistuttgart.iaas.amyassist.amy.core.di.annotation.Service;
+
+/**
+ * Test Service which uses Configuration
+ *
+ * @author Leon Kiefer
+ */
+@Service
+public class ServiceConfigurationChange {
+ @Reference
+ private Configuration configuration;
+
+ public void install() {
+ this.configuration.register(Service1.class);
+ }
+
+}
diff --git a/http-server-api/pom.xml b/http-server-api/pom.xml
index 793101f9d..8660322ea 100644
--- a/http-server-api/pom.xml
+++ b/http-server-api/pom.xml
@@ -8,7 +8,7 @@