R2DBC cannot create statement for notifications - postgresql

I am trying to receive asynchronous notifications from postgresql and r2dbc
I use reactivestream and postgres driver but i cannot make statement
I am new to java and reactivestream, i don't to use a framework like spring.
thank you guys
package com.poc.r2dbc_listen;
import io.r2dbc.postgresql.*;
import io.r2dbc.spi.*;
import org.reactivestreams.*;
import reactor.core.publisher.Flux;
public class R2dbc_listen {
public static void main(String[] args) {
PostgresqlConnectionFactory connectionFactory = new PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder()
.host("127.0.0.1")
.port(5442)
.username("postgres")
.password("psswd")
.database("database")
.build());
Publisher<? extends Connection> connectionPublisher = connectionFactory.create();
Flux<Notification> listen = connectionPublisher.createStatement("LISTEN mymessage")
.execute()
.flatMap(PostgresqlResult::getRowsUpdated)
.thenMany(receiver.getNotifications());
}
}

It works:
private void listen() {
connection = Mono.from(connectionFactory.create())
.cast(PostgresqlConnection.class)
.block(Duration.ofSeconds(10));
connection.createStatement("LISTEN channel")
.execute()
.flatMap(PostgresqlResult::getRowsUpdated)
.subscribe();
connection.getNotifications()
.delayElements(Duration.ofSeconds(1))
.subscribe(System.out::println);
}

Related

#DynamicPropertySource not being invoked (Kotlin, Spring Boot and TestContainers)

I'm trying to define a #TestConfiguration class that is executed once before all integration tests to run a MongoDB TestContainer in Kotlin in a Spring Boot project.
Here is the code:
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.testcontainers.containers.MongoDBContainer
import org.testcontainers.utility.DockerImageName
#TestConfiguration
class TestContainerMongoConfig {
companion object {
#JvmStatic
private val MONGO_CONTAINER: MongoDBContainer = MongoDBContainer(DockerImageName.parse("mongo").withTag("latest")).withReuse(true)
#JvmStatic
#DynamicPropertySource
private fun emulatorProperties(registry: DynamicPropertyRegistry) {
registry.add("spring.data.mongodb.uri", MONGO_CONTAINER::getReplicaSetUrl)
}
init { MONGO_CONTAINER.start() }
}
}
The issue seems to be that emulatorProperties method is not being called.
The regular flow should be that the container is started and then the properties are set.
The first step happens, the second does not.
I know there is an alternative for which I can do this configuration in each functional test class but I don't like it as it adds not needed noise to the test class.
For example, with a Java project that uses Postgres I managed to make it work with the following code:
import javax.sql.DataSource;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.DockerImageName;
#TestConfiguration
public class PostgresqlTestContainersConfig {
static final PostgreSQLContainer POSTGRES_CONTAINER;
private final static DockerImageName IMAGE = DockerImageName.parse("postgres").withTag("latest");
static {
POSTGRES_CONTAINER = new PostgreSQLContainer(IMAGE);
POSTGRES_CONTAINER.start();
}
#Bean
DataSource dataSource() {
return DataSourceBuilder.create()
.username(POSTGRES_CONTAINER.getUsername())
.password(POSTGRES_CONTAINER.getPassword())
.driverClassName(POSTGRES_CONTAINER.getDriverClassName())
.url(POSTGRES_CONTAINER.getJdbcUrl())
.build();
}
}
I'm trying to achieve the same thing but in Kotlin and using MongoDB.
Any idea on what may be the issue causing the #DynamicPropertySource not being called?
#DynamicPropertySource is part of the Spring-Boot context lifecycle. Since you want to replicate the Java setup in a way, it is not required to use #DynamicPropertySource. Instead you can follow the Singleton Container Pattern, and replicate it in Kotlin as well.
Instead of setting the config on the registry, you can set them as a System property and Spring Autoconfig will pick it up:
init {
MONGO_CONTAINER.start()
System.setProperty("spring.data.mongodb.uri", MONGO_CONTAINER.getReplicaSetUrl());
}
I was able to resolve similar problem in Groovy by:
Having static method annotated with #DynamicPropetySource directly in the test class (probably it would also work in superclass.
But I didn't want to copy the code into every test class that needs MongoDB.
I resolved the issue by using ApplicationContexInitializer
The example is written in groovy
class MongoTestContainer implements ApplicationContextInitializer<ConfigurableApplicationContext>{
static final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:6.0.2"))
#Override
void initialize(ConfigurableApplicationContext applicationContext) {
mongoDBContainer.start()
def testValues = TestPropertyValues.of("spring.data.mongodb.uri="+ mongoDBContainer.getReplicaSetUrl())
testValues.applyTo(applicationContext.getEnvironment())
}
}
To make it complete, in the test class, you just need to add #ContextConfiguration(initializers = MongoTestContainer) to activate context initializer for the test.
For this you could also create custom annotation which would combine #DataMongoTest with previous annotation.
This solution works for me.
Method with #DynamicPropertySource is inside companion object(also added #JvmStatic) and added org.testcontainers.junit.jupiter.Testcontainers on the test class
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.springframework.test.context.junit.jupiter.SpringExtension
import org.testcontainers.containers.PostgreSQLContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers
import javax.sql.DataSource
#ExtendWith(SpringExtension::class)
#Testcontainers
#TestConfiguration
#ContextConfiguration(classes = [PostgresqlTestContainersConfig::class])
class PostgresqlTestContainersConfig {
#Autowired
var dataSource: DataSource? = null
#Test
internal fun name() {
dataSource!!.connection.close()
}
#Bean
fun dataSource(): DataSource? {
return DataSourceBuilder.create()
.username(POSTGRES_CONTAINER.getUsername())
.password(POSTGRES_CONTAINER.getPassword())
.driverClassName(POSTGRES_CONTAINER.getDriverClassName())
.url(POSTGRES_CONTAINER.getJdbcUrl())
.build()
}
companion object {
#JvmStatic
#Container
private val POSTGRES_CONTAINER: PostgreSQLContainer<*> = PostgreSQLContainer("postgres:9.6.12")
.withDatabaseName("integration-tests-db")
.withUsername("sa")
.withPassword("sa")
#JvmStatic
#DynamicPropertySource
fun postgreSQLProperties(registry: DynamicPropertyRegistry) {
registry.add("db.url") { POSTGRES_CONTAINER.jdbcUrl }
registry.add("db.user") { POSTGRES_CONTAINER.username }
registry.add("db.password") { POSTGRES_CONTAINER.password }
}
}
}

Send push notification from springboot

I have a springboot application which I’m hosting on my own home server. I have sql database setup on the same.
And for front end I’m planning to use android for initial testing phase then shift it to flutter.
I was wonder how do I send notifications from my spring boot to my front end application. I have seen a few articles on how to send it through fire base but I was wondering if there’s another way of achieving the same without using an external service.
I have setup my server running Ubuntu on on 3 pc which loadbalances my app and want to use one of them to send push notifications.
Please follow the below steps
Install Dependency (Gradle/ Maven)
Gradle
implementation 'com.google.firebase:firebase-admin:8.1.0'
Maven
<dependency>
<groupId>com.google.firebase</groupId>
<artifactId>firebase-admin</artifactId>
<version>8.1.0</version>
</dependency>
Add firebase-service-account.json file
../src/main/resources/firebase-service-account.json
Open MainApplication java class
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.messaging.FirebaseMessaging;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
#SpringBootApplication
public class BackendApplication {
public static void main(String[] args) {
SpringApplication.run(BackendApplication.class, args);
}
#Bean
FirebaseMessaging firebaseMessaging() throws IOException {
GoogleCredentials googleCredentials = GoogleCredentials
.fromStream(new ClassPathResource("firebase-service-account.json").getInputStream());
FirebaseOptions firebaseOptions = FirebaseOptions
.builder()
.setCredentials(googleCredentials)
.build();
FirebaseApp app = FirebaseApp.initializeApp(firebaseOptions, "YOUR APP NAME");
return FirebaseMessaging.getInstance(app);
}
}
Create Service
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.FirebaseMessagingException;
import com.google.firebase.messaging.Message;
import com.google.firebase.messaging.Notification;
import org.springframework.stereotype.Service;
#Service
public class FirebaseMessagingService {
private final FirebaseMessaging firebaseMessaging;
public FirebaseMessagingService(FirebaseMessaging firebaseMessaging) {
this.firebaseMessaging = firebaseMessaging;
}
public void sendNotification(String title, String body, String token) throws FirebaseMessagingException {
Notification notification = Notification
.builder()
.setTitle(title)
.setBody(body)
.build();
Message message = Message
.builder()
.setToken(token)
.setNotification(notification)
// .putAllData(note.getData())
.build();
firebaseMessaging.send(message);
// For Send to multiple devices use Multicast Message Builder
MulticastMessage message = MulticastMessage
.builder()
.addAllTokens(<List Of Tokens>)
.setNotification(notification)
// .putAllData(note.getData())
.build();
firebaseMessaging.send(message);
}
}
Usage of service inside controller
#Autowired
private FirebaseMessagingService firebaseService;
public void sendPushMessage(){
firebaseService.sendNotification("Notification title", "Notification Text", "Receiver device token");
}

REST API script taking longer time to execute

I am new to API automation. When trying to execute the basic script in selenium I am getting the below error. Can some one please help me with it.
package GetRequest;
import static io.restassured.RestAssured.given;
import io.restassured.RestAssured;
public class trying {
public static void main(String[] args) {
// base url
RestAssured.baseURI="https://maps.googleapis.com";
given().
param("location","-33.8670522,151.1957362").
param("radius","1500").
param("Key","AIzaSyBBuJ-3wBy1VKGUMtNqO8PpAHWGESIItAo").
when().
get("/maps/api/place/nearbysearch/json").
then().
assertThat().statusCode(200);
}
}
What is the port you are connecting at ? Have you specified that somewhere ? Are you using proxy ?
Why not try something like?
#BeforeClass
public void setProxy()
{
System.setProperty("http.proxyHost", YOUR_PROXY_HOST_HERE);
System.setProperty("http.proxyPort", YOUR_PROXY_PORT_HERE);
}

How to enable ssl in reactive mongodb client in spring boot?

I am currently running into an issue while creating a reactive mongoclient when I provide the URL with ssl=true option.
I am creating configuration class in spring boot where I create Reactive mongoclient using the following option:
MongoClients.create(Connections ring Conn)
Here when I try to connect to a DB with no ssl settings it works, but with ssl enabled option I am getting error saying NettyEventLoop class is not found.
Can anyone suggest what I can do to fix this issue
It seems that the API has changed, so since MongoDB driver v3.8, the method is "applyToSslSettings":
import com.mongodb.Block;
import com.mongodb.connection.SslSettings;
import com.mongodb.connection.SslSettings.Builder;
import com.mongodb.connection.netty.NettyStreamFactoryFactory;
import io.netty.channel.nio.NioEventLoopGroup;
#Configuration
public class Config {
private NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup();
#Bean
public MongoClientSettingsBuilderCustomizer sslCustomizer() {
Block<SslSettings.Builder> sslSettingsBlock = new Block<SslSettings.Builder>() {
#Override
public void apply(Builder t) {
t.applySettings(SslSettings.builder()
.enabled(true)
.invalidHostNameAllowed(true)
.build());
}
};
return clientSettingsBuilder -> clientSettingsBuilder
.applyToSslSettings(sslSettingsBlock)
.streamFactoryFactory(NettyStreamFactoryFactory.builder()
.eventLoopGroup(eventLoopGroup).build());
}
#PreDestroy
public void shutDownEventLoopGroup() {
eventLoopGroup.shutdownGracefully();
}
}
I was able to overcome this issue by configuring MongoClientSettingsBuilderCustomizer and NioEventLoop Group.
Please find below the code:
private NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup();
#Bean
public MongoClientSettingsBuilderCustomizer sslCustomizer() {
return clientSettingsBuilder -> clientSettingsBuilder
.sslSettings(SslSettings.builder()
.enabled(true)
.invalidHostNameAllowed(true)
.build())
.streamFactoryFactory(NettyStreamFactoryFactory.builder()
.eventLoopGroup(eventLoopGroup).build());
}

Unable to find the org.drools.builder.KnowledgeType drrols class

While am trying to execute the Helloword process example from the section 2.3 in
https://hudson.jboss.org/hudson/job/drools/lastSuccessfulBuild/artifact/trunk/target/docs/drools-flow/html_single/index.html#d4e24 site am unable to find the below mentioned class.
org.drools.builder.KnowledgeType
Could anyone please tell from which package can i get this class?
Thanks!
That part of the documentation seems a little outdated. You should use ResourceType. I've updated the docs with the following code fragment instead (should also appear on the link you're using once the build succeeds):
package com.sample;
import org.drools.KnowledgeBase;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.logger.KnowledgeRuntimeLogger;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.runtime.StatefulKnowledgeSession;
/**
* This is a sample file to launch a process.
*/
public class ProcessTest {
public static final void main(String[] args) {
try {
// load up the knowledge base
KnowledgeBase kbase = readKnowledgeBase();
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
// start a new process instance
ksession.startProcess("com.sample.ruleflow");
logger.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
private static KnowledgeBase readKnowledgeBase() throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("ruleflow.rf"), ResourceType.DRF);
return kbuilder.newKnowledgeBase();
}
}