### Postgres Configuration Source: https://docs.factcast.org/setup/_print Example configuration for a Postgres database user. ```properties spring.datasource.username="user" //that user has to be provided sspring.datasource.password="password" ``` -------------------------------- ### Run Docker Container Source: https://docs.factcast.org/setup/_print Command to start the Docker container, specifying the database URL. ```bash docker run -e"SPRING_DATASOURCE_URL=jdbc:postgresql:///?user=&password=" -p 9090:9090 factcast/factcast ``` -------------------------------- ### Access Configuration JSON Source: https://docs.factcast.org/setup/_print Example structure for the factcast-access.json file, defining accounts and roles. ```json { "accounts": [ { "id": "brain", "roles": ["anything"] }, { "id": "pinky", "roles": ["anything", "limited"] }, { "id": "snowball", "roles": ["readOnlyWithoutAudit"] } ], "roles": [ { "id": "anything", "read": { "include": ["*"] }, "write": { "include": ["*"] } }, { "id": "limited", "read": { "include": ["*"], "exclude": ["secret"] }, "write": { "exclude": ["audit*"] } }, { "id": "readOnlyWithoutAudit", "read": { "include": ["*"], "exclude": ["audit*", "secret"] }, "write": { "exclude": ["*"] } } ] } ``` -------------------------------- ### Secret Properties Configuration Source: https://docs.factcast.org/setup/_print Example of configuring secrets for accounts using properties. ```properties factcast.access.secrets.brain=world factcast.access.secrets.pinky=narf factcast.access.secrets.snowball=grim ``` -------------------------------- ### Customizing Credential Loading with UserDetailsService Source: https://docs.factcast.org/setup/_print Java code example for implementing a UserDetailsService to customize credential loading and integrate with FactCast's access configuration. ```java @Bean UserDetailsService userDetailsService(FactCastAccessConfiguration cc, PasswordEncoder passwordEncoder) { return username -> { // fetching account info from fact-access.json Optional account = cc.findAccountById(username); // your way to fetch the user + password User user = loadUserByName(username); return account .map(acc -> new FactCastUser(acc, passwordEncoder.encode(user.getPassword()))) .orElseThrow(() -> new UsernameNotFoundException(username)); }; } ``` -------------------------------- ### Build the example Source: https://docs.factcast.org/usage/lowlevel/cli/fc-schema-cli Command to build the schema registry example. ```bash java -jar target/fc-schema-cli.jar build -p ../factcast-examples/factcast-example-schema-registry/src/main/resources ``` -------------------------------- ### ProjectionMetaData revision example Source: https://docs.factcast.org/about/migration Example of using the 'revision' field in ProjectionMetaData. ```java @ProjectionMetaData(revision = 1) public class MyProjection extends AbstractManagedProjection { ... } ``` -------------------------------- ### Using the fetch method Source: https://docs.factcast.org/usage/factus/projections/types/snapshot-projections An example of how to use the `fetch` method to get an instance of the UserNames projection. ```java UserNames currentUserNames=factus.fetch(UserNames.class); ``` -------------------------------- ### Schema Registry CLI - Build Example Source: https://docs.factcast.org/usage/_print Command to build the Schema Registry example using the fc-schema-cli. ```bash $ java -jar target/fc-schema-cli.jar build -p ../factcast-examples/factcast-example-schema-registry/src/main/resources ``` -------------------------------- ### onCatchup Method Example Source: https://docs.factcast.org/usage/factus/_print An example implementation of the onCatchup method in Java, logging a message and indicating readiness. ```java @Override public void onCatchup() { log.debug("Projection is ready now"); // perform further actions e.g. switch health indicator to "up" } ``` -------------------------------- ### Using fetch to get UserNames projection Source: https://docs.factcast.org/usage/factus/projections/types/_print Example of how to use the fetch method to get an instance of the UserNames projection. ```java UserNames currentUserNames=factus.fetch(UserNames.class); ``` -------------------------------- ### Build Docker Container Source: https://docs.factcast.org/setup/_print Command to build a standard Docker container from source. ```bash mvn docker:build ``` -------------------------------- ### Using The Projection Source: https://docs.factcast.org/usage/factus/_print Example of how to call a projection method to get user names. ```java UserNames userNameProjection = new UserNames(platformTransactionManager, jdbcTemplate); factus.update(userNameProjection); List userNames = userNameProjection.getUserNames(); ``` -------------------------------- ### Postgres Configuration Example Source: https://docs.factcast.org/setup/prerequisites Example of how to configure the FactCast server to connect to a PostgreSQL database, including username and password. ```properties spring.datasource.username="user" //that user has to be provided spring.datasource.password="password" ``` -------------------------------- ### UserAdded Event Definition Source: https://docs.factcast.org/guides/testing An example of a Factus compatible event implementing the EventObject interface. ```java @Getter @Specification(ns = "user", type = "UserAdded", version = 1) public class UserAdded implements EventObject { private UUID userId; private String email; // used by Jackson deserializer protected UserAdded(){} public static UserAdded of(UUID userId, String email) { UserAdded fact = new UserAdded(); fact.userId = userId; fact.email = email; return fact; } @Override public Set aggregateIds() { return Collections.emptySet(); } } ``` -------------------------------- ### Add Snappy Compression Dependency (Pre 0.7.9) Source: https://docs.factcast.org/setup/_print Maven dependency for Snappy compression support in FactCast versions prior to 0.7.9. ```xml org.xerial.snappy snappy-java 1.1.8.4 ``` -------------------------------- ### Add Snappy Compression Dependency Source: https://docs.factcast.org/setup/_print Maven dependency to enable Snappy compression support in FactCast clients and servers. ```xml org.factcast factcast-grpc-snappy ${factcast.version} ``` -------------------------------- ### Factus Core Dependency Source: https://docs.factcast.org/usage/factus/setup The core dependency for Factus itself. ```xml org.factcast factcast-factus ``` -------------------------------- ### Integration Test Example for UserEmailsProjection Source: https://docs.factcast.org/guides/testing An integration test using FactCastExtension to verify that the UserEmailsProjection can be updated by a real FactCast server. ```java @SpringBootTest @ExtendWith(FactCastExtension.class) class UserEmailsProjectionITest { @Autowired FactCast factCast; private final UserEmailsProjection uut = new UserEmailsProjection(); private class FactObserverImpl implements FactObserver { @Override public void onNext(@NonNull Fact fact) { uut.apply(fact); } } @Test void projectionHandlesUserAddedFact() { UUID userId = UUID.randomUUID(); Fact userAdded = Fact.builder() .id(UUID.randomUUID()) .ns("user") .type("UserAdded") .version(1) .build(String.format( "{\"id\":\"%s\", \"email\": \"%s\"}", userId, "user@bar.com")); factCast.publish(userAdded); SubscriptionRequest subscriptionRequest = SubscriptionRequest .catchup(FactSpec.ns("user").type("UserAdded")) .or(FactSpec.ns("user").type("UserRemoved")) .fromScratch(); factCast.subscribe(subscriptionRequest, new FactObserverImpl()).awaitComplete(); Set userEmails = uut.getUserEmails(); assertThat(userEmails).hasSize(1).containsExactly("user@bar.com"); } //... } ``` -------------------------------- ### Unit Test Example for UserAdded Fact Source: https://docs.factcast.org/guides/testing A JUnit test demonstrating how to unit test a projection by handling a UserAdded fact and asserting the email is added to the internal map. ```java @Test void whenHandlingUserAddedFactEmailIsAdded() { // arrange String jsonPayload = String.format( "{\"id\":\"%s\", \"email\": \"%s\"}", UUID.randomUUID(), "user@bar.com"); Fact userAdded = Fact.builder() .id(UUID.randomUUID()) .ns("user") .type("UserAdded") .version(1) .build(jsonPayload); // act uut.handleUserAdded(userAdded); // assert Set emails = uut.getUserEmails(); assertThat(emails).hasSize(1).containsExactly("user@bar.com"); } ``` -------------------------------- ### Create Postgres Extension Source: https://docs.factcast.org/setup/_print Command to create the uuid-ossp extension in Postgres. ```sql CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; ``` -------------------------------- ### Run Example Server Source: https://docs.factcast.org/setup/fatjar Runs a simple example Factcast server using Spring Boot. ```bash mvn spring-boot:run ``` -------------------------------- ### Subscribed Projections - Waiting for Fact Example Source: https://docs.factcast.org/guides/read-after-write Demonstrates how to use `factus.waitFor` to defer a query until a specific fact has been applied to a subscribed projection, ensuring consistency for the user. ```Java factus.waitFor(mySubscribedProjection, factIdOfTheFactToWaitFor [, duration]) ``` -------------------------------- ### Binary Snapshot Serializer Dependency Source: https://docs.factcast.org/usage/factus/setup Optional dependency for a binary snapshot serializer. ```xml org.factcast factcast-factus-bin-snapser ``` -------------------------------- ### Managed Projections - Selective Update Example Source: https://docs.factcast.org/guides/read-after-write Illustrates how to trigger an update for a managed projection after a relevant fact is published to ensure consistency for the user who made the change. ```Java factus.update(myManagedUserCount); ``` -------------------------------- ### Handler method example Source: https://docs.factcast.org/usage/factus/projections/example/_print An example of a handler method that processes a UserCreated event and updates a map within a transaction. ```java @Handler void apply(UserCreated e, RTransaction tx){ Map userNames=tx.getMap(getRedisKey()); userNames.put(e.getAggregateId(),e.getUserName()); } ``` -------------------------------- ### Schema Registry CLI - Serve Example Source: https://docs.factcast.org/usage/_print Command to serve the built Schema Registry example using hugo server. ```bash $ hugo server ``` -------------------------------- ### Full UserNames Projection Example Source: https://docs.factcast.org/usage/factus/projections/example/_print A complete example of a UserNames projection class demonstrating event handling and Redis data management. ```java @ProjectionMetaData(revision = 1) @RedisTransactional public class UserNames extends AbstractRedisTxManagedProjection { private final Map userNames; public UserNames(RedissonClient redisson) { super(redisson); userNames = redisson.getMap(getRedisKey()); } public List getUserNames() { return new ArrayList<>(userNames.values()); } @Handler void apply(UserCreated e, RTransaction tx) { tx.getMap(getRedisKey()).put(e.getAggregateId(), e.getUserName()); } @Handler void apply(UserDeleted e, RTransaction tx) { tx.getMap(getRedisKey()).remove(e.getAggregateId()); } } ``` -------------------------------- ### Run Docker Container Source: https://docs.factcast.org/setup/docker Starts the docker container with the database URL. ```bash docker run -e"SPRING_DATASOURCE_URL=jdbc:postgresql:///?user=&password=" -p 9090:9090 factcast/factcast ``` -------------------------------- ### onCatchup hook example Source: https://docs.factcast.org/usage/factus/projections/callbacks This example shows how to implement the onCatchup method to signal that the projection is ready to serve data after catching up. ```java @Override public void onCatchup() { log.debug("Projection is ready now"); // perform further actions e.g. switch health indicator to "up" } ``` -------------------------------- ### UserNames SnapshotProjection Example Source: https://docs.factcast.org/usage/factus/optimistic-locking An example of a SnapshotProjection that tracks existing usernames. ```java public class UserNames implements SnapshotProjection { private final Map existingNames = new HashMap<>(); @Handler void apply(UserCreated created) { existingNames.put(created.aggregateId(), created.userName()); } @Handler void apply(UserDeleted deleted, FactHeader header) { existingNames.remove(deleted.aggregateId()); } boolean contains(String name) { return existingNames.values().contains(name); } // ... } ```