Spring Cloud Stream Supplier function model - spring-boot

I am trying to use spring cloud stream and the new functions support for configuration but I am having a problem to understand how to achieve the same result I would have with annotation configuration.
I need to send a message to the brooker, every time a user is created. With the annotation based configuration I could accomplish it like this:
public UserProducer {
#Autowired
private final Source source;
#Autowired
private final UserRepository repository;
public void saveUser(User user) {
repository.save(user);
source.output().send(MessageBuilder.withPayload(user).build());
}
}
Is it possible to use spring cloud stream functions to achieve the same result?

You can use the new StreamBridge API for doing that. See the docs here: https://cloud.spring.io/spring-cloud-static/spring-cloud-stream/3.0.6.RELEASE/reference/html/spring-cloud-stream.html#_using_streambridge

Related

Micrometer timer metrics not displayed in Cloudwatch when #Timed is used

I am trying to send my API application metrics to AWS Cloudwatch using the mircometer registry's timer. I have successfully managed to send custom metrics by implementing it manually so far. But, I want to send the metrics using the #Timed annotation, and it doesn't work. Here are the things I have tried so far:
#Timed("test")
#RestController
public class TempHandler{
#GetMapping(value="/path")
#Timed(value="ping")
public ResponseEntity ping(#RequestHeader Map<String,String> headers){
return applyHeaders(Response.status(200).entity("ok"));
}
}
I have created a #Configuration class as well to return a TimedAspect object.
#Configuration
public class TimedConfiguration {
#Bean
public TimedAspect timedAspect(MeterRegistry registry) {
return new TimedAspect(registry);
}
}
I have included the spring AOP dependancy in my build.gradle as well. Please help me to figure out what I am doing wrong. Thanks!

How to make OAuth2 server read client from database rather than write in memory?

So I want to find a way to read Client credentials (client_id, client_secret,...) from database. I'm currently using SpringBoot 2.7.3.
Every tutorial I found is from 4+ years ago and use deprecated dependencies.
You are probably using the InMemoryClientRegistrationRepository implementation of the ClientRegistrationRepository interface. If you want to retrieve the clients from another place, you have to create a new implementation of that interface. If you are using Spring Data JPA, you can do something like:
public interface ClientRegistrationSpringDataRepository extends JpaRepository<ClientRegistrationEntity, String> {
}
#Repository
public class DaoClientRegistrationRepository implement ClientRegistrationRepository {
private final ClientRegistrationSpringDataRepository repository;
// constructor
#Override
public ClientRegistration findByRegistrationId(String registrationId) {
ClientRegistrationEntity entity = this.repository.getById(registrationId);
return mapToClientRegistration(entity);
}
private ClientRegistration mapToClientRegistration(ClientRegistrationEntity entity) {
// your logic
}
}

Rest API send websocket message as well as response entity

I'm using spring boot and I was wondering if I can create a REST API that also sends a message to a websocket channel? so anyone subscribed to it can get it. Since it's a rest api, there would also be a response entity when it's done as well. If so, can i see an example of how that would work? i've been googling everywhere.
Good starting points to build a Spring Boot application with Websocket support are
WebSockets chapter in the official Spring documentation
WebSocket Security chapter in the Spring security documentation
Baeldung post Intro to Security and WebSockets
To determine connected users you can use SimpUserRegistry bean and to send messages to them you can use SimpMessagingTemplate, for example:
#RestController
public class ApiController {
private final SimpMessagingTemplate template;
private final SimpUserRegistry userRegistry;
public ApiController(SimpMessagingTemplate template, SimpUserRegistry userRegistry) {
this.template = template;
this.userRegistry = userRegistry;
}
#PostMapping("/api/users/{username}/send")
public ResponseEntity<?> sendMessage(#RequestBody Message message, #PathVariable String username) {
Set<SimpUser> users = userRegistry.getUsers();
if (users.stream().anyMatch(simpUser -> simpUser.getName().equals(username))) {
template.convertAndSendToUser(username, "/messages", message);
return ResponseEntity.noContent().build();
} else {
return ResponseEntity.notFound().build();
}
}
}
You can check my minimal example of working Websockets demo application.

Spring cloud stream output destination to object

I am testing a spring cloud stream channel like this:
#RunWith(SpringRunner.class)
#IntegrationTest
#SpringBootTest
#AutoConfigureStubRunner(
stubsMode = StubRunnerProperties.StubsMode.LOCAL,
ids = "br.com.marco.cadeacerva:users:+:stubs:8090")
public class UsersConsumerTest {
#Autowired
StubTrigger trigger;
#MockBean
UserInterestsAggregator consumer;
#Autowired
OutputDestination output;
#Test
public void shouldConsumeUsersEvents() {
trigger.trigger("sendUserMessage");
Message<byte[]> message = output.receive();
verify(consumer).aggregate(any(UserDTO.class));
}
}
I am triggering the message via spring cloud contract machinery, and would like to know if there is a way to receive the message payload of a specific type T instead of a byte[]?
If not, what is the best way to convert the bytes to the original type?

Use multiple ClientAuthentiation with spring-vault

We have an application using spring-vault. It authenticates to Vault using an AppRole. We use the token we get from that operation to read and write secrets. The configuration for the VaultEndpoint and AppRoleAuthentication are auto-configured from a properties file.
Code looks like this:
#Autowired
private ApplicationContext context;
#Autowired
private VaultOperations vault;
private Logger logger = LoggerFactory.getLogger(VaultFacade.class);
public VaultFacadeImpl() {
logger.debug("Creating VaultFacade with autowired context");
context = new AnnotationConfigApplicationContext(VaultConfig.class);
vault = context.getBean(VaultTemplate.class);
//vault variable ready to use with vault.read or vault.write
//in our VaultFacadeImpl
}
I would like to keep autowire capabilities, but also support two other ClientAuthentication implementations:
The existing TokenAuthentication
A custom ClientAuthentication implementation (LDAP auth backend)
The end result would be having two authentication mechanism available at the same time. Some operations would be carried out with the application's credentials (AppRole in Vault), others with the user's credentials (LDAP in Vault).
I think I can create multiple AbstractVaultConfiguration classes, each returning a different ClientAuthentication derivative. But how can I create a VaultTemplate for configuration class?
If you want to have an additional VaultTemplate bean, then you need to configure and declare the bean yourself. You can keep the foundation provided by AbstractVaultConfiguration. Your config could look like:
#Configuration
public class CustomConfiguration {
#Bean
public VaultTemplate ldapAuthVaultTemplate(ClientFactoryWrapper clientHttpRequestFactoryWrapper,
ThreadPoolTaskScheduler threadPoolTaskScheduler) {
return new VaultTemplate(…,
clientHttpRequestFactoryWrapper.getClientHttpRequestFactory(),
ldapSessionManager(threadPoolTaskScheduler));
}
#Bean
public SessionManager ldapSessionManager(ThreadPoolTaskScheduler threadPoolTaskScheduler) {
ClientAuthentication clientAuthentication = new MyLdapClientAuthentication(…);
return new LifecycleAwareSessionManager(clientAuthentication,
threadPoolTaskScheduler,
…);
}
}
On the client side (using the second VaultTemplate) you need to make sure to look up the appropriate instance. Spring doesn't limit you to a bean per type but allows registration of multiple beans of the same type.

Resources