Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Java xAPI model, client and tools

License

NotificationsYou must be signed in to change notification settings

BerryCloud/xapi-java

Repository files navigation

xAPI Java helps you to create applications that send or receive xAPIStatements orDocuments.

There are two projects in thisMonorepo, xAPI Client and xAPI Model.

Both the xAPI Client and xAPI Model use afluent interface. Objects areimmutable.

CheckStyle is used to enforce theGoogle Java Style Guide. Sonar performs automatic pull request reviews.CodeQL scans for vulnerabilities. The number of bugs, code smells and vulnerabilities in the codebase can be viewed in SonarCloud. The code coverage and code duplication percentages can also be viewed in SonarCloud. Over three-hundred unit tests ensure conformance with the xAPI specification.

Requirements

xAPI Java requires Java 17 or newer.

xAPI Java Client

The xAPI Java Client can be used by learning record providers (LRP) to communicate with learning record stores (LRS) or a system which follows the LRS requirements of one or more of the xAPI resources.

Getting started

To use the xAPI Java Client include the appropriate XML in thedependencies section of yourpom.xml, as shown in the following example:

<project>    <modelVersion>4.0.0</modelVersion>    <artifactId>getting-started</artifactId><!-- ...-->    <dependencies><!-- ...-->        <dependency>            <groupId>dev.learning.xapi</groupId>            <artifactId>xapi-client</artifactId>            <version>1.1.11</version>        </dependency>    </dependencies></project>

xAPI Java Client is available in theMaven Central Repository.

Configuration

The xAPI Java Client has a Spring AutoConfiguration bean which picks up the following properties:

PropertyDescription
xapi.client.baseUrlThe base url of the LRS endpoint
xapi.client.usernameUsername for basic authorization header
xapi.client.passwordPassword for basic authorization header
xapi.client.authorizationAuthorization header (has precedence over the username and password properties)

Properties can be set using anyexternal configuration method supported by Spring Boot.

If you need more specific customization (eg. your LRS needs specific headers, or you want to set the authorization header dynamically) you can create a custom configurer by implementing theXapiClientConfigurer interface.

Advanced Configuration

The xAPI Java Client uses the Spring WebClient. Spring WebClient has default memory limit of 256KB for buffering data. If this limit is exceeded then a DataBufferLimitException will be thrown.

The default memory limit of 256KB for buffering data could be exceeded if the LRS returns a large number of Statements or if the Statements contain attachments.

It is possible to set the memory limit for buffering data with thespring.codec.max-in-memory-size property.

Example:

spring.codec.max-in-memory-size=1MB

Statement Resource

The xAPI Java Client allows applications to store and fetch xAPIStatements.

Getting a Statement

Example:

varresponse =client.getStatement(r ->r.id("4df42866-40e7-45b6-bf7c-8d5fccbdccd6")).block();Statementstatement =response.getBody();

Getting a Statement with attachments

Example:

varresponse =client.getStatement(r ->r.id("4df42866-40e7-45b6-bf7c-8d5fccbdccd6").attachments(true).block();Statementstatement =response.getBody();

Getting Statements

Example:

varresponse =client.getStatements().block();StatementResultstatementResult =response.getBody();Statement[]statements =statementResult.getStatements();

Getting the next page of Statements

Example:

varresponse =client.getStatements().block();varmoreResponse =client.getMoreStatements(r ->r.more(response.getBody().getMore())).block();StatementResultmoreStatementResult =moreResponse.getBody();Statement[]statements =moreStatementResult.getStatements();

Getting Statements as Iterator (and processing them as a Stream)

In most cases it is preferable to usegetStatementIterator() instead ofgetStatments() andgetMoreStatements().

Example:

varstatements =client.getStatementIterator().block();// process the first 100 Statementsstatements.toStream().limit(100).forEach(s -> {// add logic here...  });

Posting a Statement

Example:

client.postStatement(r ->r.statement(s ->s.agentActor(a ->a.name("A N Other").mbox("mailto:another@example.com"))        .verb(Verb.ATTEMPTED)        .activityObject(o ->o.id("https://example.com/activity/simplestatement")            .definition(d ->d.addName(Locale.ENGLISH,"Simple Statement")))))    .block();

Posting a Statement with an attachment

Example:

client.postStatement(r ->r.statement(s ->s.agentActor(a ->a.name("A N Other").mbox("mailto:another@example.com"))        .verb(Verb.ATTEMPTED)        .activityObject(o ->o.id("https://example.com/activity/simplestatement")            .definition(d ->d.addName(Locale.ENGLISH,"Simple Statement")))        .addAttachment(a ->a.content("Simple attachment").length(17).contentType("text/plain")            .usageType(URI.create("https://example.com/attachments/simplestatement"))            .addDisplay(Locale.ENGLISH,"text attachment"))    )).block();

Posting a Signed Statement

Example:

client.postStatement(r ->r.signedStatement(s ->s.agentActor(a ->a.name("A N Other").mbox("mailto:another@example.com"))        .verb(Verb.ATTEMPTED)        .activityObject(o ->o.id("https://example.com/activity/simplestatement")            .definition(d ->d.addName(Locale.ENGLISH,"Simple Statement"))),keyPair.getPrivate()))    .block();

Posting Statements

Example:

StatementattemptedStatement =Statement.builder()    .agentActor(a ->a.name("A N Other").mbox("mailto:another@example.com")).verb(Verb.ATTEMPTED)    .activityObject(o ->o.id("https://example.com/activity/simplestatement")        .definition(d ->d.addName(Locale.ENGLISH,"Simple Statement")))    .build();StatementpassedStatement =attemptedStatement.toBuilder().verb(Verb.PASSED).build();client.postStatements(r ->r.statements(attemptedStatement,passedStatement)).block();

Getting a voided Statement

Example:

varresponse =client.getVoidedStatement(r ->r.id("4df42866-40e7-45b6-bf7c-8d5fccbdccd6")).block();StatementvoidedStatement =response.getBody();

State Resource

The xAPI Java Client allows applications to store, change, fetch, or deletestate documents.

Getting a state

Example:

varresponse =client.getState(r ->r.activityId("https://example.com/activity/1")    .agent(a ->a.name("A N Other").mbox("mailto:another@example.com"))    .registration("67828e3a-d116-4e18-8af3-2d2c59e27be6")    .stateId("bookmark"),String.class)    .block();Stringstate =response.getBody();

Posting a state

Example:

client.postState(r ->r.activityId("https://example.com/activity/1")    .agent(a ->a.name("A N Other").mbox("mailto:another@example.com"))    .registration("67828e3a-d116-4e18-8af3-2d2c59e27be6")    .stateId("bookmark")    .state("Hello World!"))    .block();

Putting a state

Example:

client.putState(r ->r.activityId("https://example.com/activity/1")    .agent(a ->a.name("A N Other").mbox("mailto:another@example.com"))    .registration("67828e3a-d116-4e18-8af3-2d2c59e27be6")    .stateId("bookmark")    .state("Hello World!"))    .block();

Deleting a state

Example:

client.deleteState(r ->r.activityId("https://example.com/activity/1")    .agent(a ->a.name("A N Other").mbox("mailto:another@example.com"))    .registration("67828e3a-d116-4e18-8af3-2d2c59e27be6")    .stateId("bookmark"))    .block();

Samples

The samples folder in this repository containssample applications that use the xAPI client.

xAPI Model Spring Boot Starter

The xAPI specification has strict rules for API requests/responses formatting. The xAPI Model has inbuilt validation for all of these rules. However, if you plan to use the xAPI Model, you should keep in mind that some activity providers do not fully conform to these rules.

In some cases it may be desirable to turn off some or all of the rules in order to be compatible with a wider range of xAPI activity providers. However, it should be noted that doing this is in violation of the xAPI specification.

The xAPI Model Spring Boot Starter package provides an easy way to turn on/off these validation rules.

Getting started

To use the xAPI Model Spring Boot Starter include the appropriate XML in thedependencies section of yourpom.xml, as shown in the following example:

<dependency>  <groupId>dev.learning.xapi</groupId>  <artifactId>xapi-model-spring-boot-starter</artifactId>  <version>1.1.11</version></dependency>

xAPI Model Spring Boot Starter is available in theMaven Central Repository.

Configuration

The xAPI Model Spring Boot Starter has a Spring AutoConfiguration bean which picks up the following properties:

PropertyDescription
xapi.model.validateJsonFail on trailing JSON tokens
xapi.model.validatePropertiesFail on unknown JSON properties
xapi.model.validateNullValuesFail on null JSON properties
xapi.model.validateLiteralsFail on number and boolean JSON properties defined as string
xapi.model.validateObjectTypeFail on invalid JSON objectType property
xapi.model.validateLocaleFail on invalid Locale strings
xapi.model.validateTimestampFail on negative zero timezone offsets
xapi.model.validateActivityDefinitionFail on invalid xAPI ActivityDefinition (missing properties)
xapi.model.validateActorFail on invalid xAPI Actor (missing or multiple identifiers)
xapi.model.validateAuthorityFail on invalid xAPI Authority object
xapi.model.validateUriSchemeFail on invalid xAPI URI property (missing scheme)
xapi.model.validateMboxFail on invalid xAPI mbox property (invalid email or missing prefix)
xapi.model.validateLocaleNotUndeterminedFail on invalid xAPI locale property (locale is undetermined)
xapi.model.validateScaledScoreFail on invalid xAPI scaledScore property (out of -1 - 1 range)
xapi.model.validateScoreFail on invalid xAPI Score (raw score is out of min/max range)
xapi.model.validateStatementPlatformFail on invalid xAPI context.platform (if present object must be Activity)
xapi.model.validateStatementRevisionFail on invalid xAPI context.revision (if present object must be Activity)
xapi.model.validateStatementListIdsFail on invalid xAPI statement List (conflicting statement ids)
xapi.model.validateStatementVerbFail on invalid xAPI voided statement (object must be StatemnetReference)
xapi.model.validateUuidVariantFail on invalid xAPI UUID property (must be UUID variant 4)

The default value isTRUE for all of the above properties.

xAPI Java Model

The xAPI model can be used by clients that send xAPI data or by servers that receive xAPI data.

Getting started

To use the xAPI Model include the appropriate XML in thedependencies section of yourpom.xml, as shown in the following example:

<project>    <modelVersion>4.0.0</modelVersion>    <artifactId>getting-started</artifactId><!-- ...-->    <dependencies><!-- ...-->        <dependency>            <groupId>dev.learning.xapi</groupId>            <artifactId>xapi-model</artifactId>            <version>1.1.11</version>        </dependency>    </dependencies></project>

xAPI Model is available in theMaven Central Repository.

Creating a statement

Example:

Statementstatement =Statement.builder()    .agentActor(a ->a.name("A N Other").mbox("mailto:another@example.com"))    .verb(Verb.ATTEMPTED)    .activityObject(o ->o.id("https://example.com/activity/simplestatement")        .definition(d ->d.addName(Locale.ENGLISH,"Simple Statement")))    .build();

Deserializing Statements

The Jackson ObjectMapper can be used to deserialize statements into Java objects.

Example:

Stringjson ="""    {        "actor":{            "objectType":"Agent",            "name":"A N Other",            "mbox":"mailto:another@example.com"        },        "verb":{            "id":"http://adlnet.gov/expapi/verbs/attempted",            "display":{                "und":"attempted"            }        },        "object":{            "objectType":"Activity",            "id":"https://example.com/activity/simplestatement",            "definition":{                "name":{                "en":"Simple Statement"                }            }        }    }""";Statementstatement =objectMapper.readValue(json,Statement.class);

Serializing Statements

The Jackson ObjectMapper can be used to serialize Statement objects into JSON.

Example:

Statementstatement =Statement.builder()    .agentActor(a ->a.name("A N Other").mbox("mailto:another@example.com")).verb(Verb.ATTEMPTED)    .activityObject(o ->o.id("https://example.com/activity/simplestatement")        .definition(d ->d.addName(Locale.ENGLISH,"Simple Statement")))    .build();Stringjson =objectMapper.writeValueAsString(statement);

Creating a new statement using an existing statement as template

Example:

Statementpassed =Statement.builder()    .agentActor(a ->a.name("A N Other").mbox("mailto:another@example.com")).verb(Verb.PASSED)    .activityObject(o ->o.id("https://example.com/activity/simplestatement")        .definition(d ->d.addName(Locale.ENGLISH,"Simple Statement")))    .build();Statementcompleted =passed.toBuilder().verb(Verb.COMPLETED).build();

Validating Statements

Statements can be validated programmatically.

Example:

Validatorvalidator =Validation.buildDefaultValidatorFactory().getValidator();Statementstatement =Statement.builder()    .agentActor(a ->a.name("A N Other").mbox("mailto:another@example.com"))    .activityObject(o ->o.id("https://example.com/xapi/activity/simplestatement"))    .build();Set<ConstraintViolation<Statement>>constraintViolations =validator.validate(statement);System.out.println(constraintViolations)// Prints [ConstraintViolationImpl{interpolatedMessage='must not be null', propertyPath=verb, rootBeanClass=class dev.learning.xapi.model.Statement, messageTemplate='{jakarta.validation.constraints.NotNull.message}'}]

Statements can also be validated when they are received by a method in a REST controller. The following example requires Spring MVC and the Hibernate Validator.

@PostMappingpublicResponseEntity<Collection<UUID>>postStatements(@RequestBodyList<@ValidStatement>statements) {// Process the statementsreturnnewResponseEntity<>(HttpStatus.OK);}

[8]ページ先頭

©2009-2025 Movatter.jp