Spring boot doesn't commit changes with cassandra - spring-boot

I have a very simple spring boot application that communicate with cassandra . In my sample When I run myApplication keySpace "myTestKeySpace" created but when i stop application that automatically dropped from database . what's wrong?
#Configuration
public class CassandraConfig extends AbstractCassandraConfiguration {
public static final String KEYSPACE = "myTestKeySpace";
#Override
public SchemaAction getSchemaAction() {
return SchemaAction.CREATE;
}
#Override
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
CreateKeyspaceSpecification specification = CreateKeyspaceSpecification.createKeyspace(KEYSPACE);
return Arrays.asList(specification);
}
#Override
protected List<DropKeyspaceSpecification> getKeyspaceDrops() {
return Arrays.asList(DropKeyspaceSpecification.dropKeyspace(KEYSPACE));
}
#Override
protected String getKeyspaceName() {
return KEYSPACE;
}
#Override
public String[] getEntityBasePackages() {
return new String[]{"com.mySite"};
}
}
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class , args);
}
}

I have never use Springdata with Cassandra, but I guess the method getKeyspaceDrops will drop the keyspace in the same manner the getKeyspaceCreations will create it.

Related

Picocli Spring boot CLI Application

I am trying to create a spring boot CLI App using picocli. I followed the steps as mentioned in the tutorial, but when I start the service the whole flow runs.
What I want is to call the command from the terminal then only the flow should trigger.Can anyone please help me resolving this.
Below is my code.
Component class
public class AppCLI implements CommandLineRunner {
#Autowired
AppCLI appCLI;
public String hello(){
return "hello";
}
#CommandLine.Command(name = "command")
public void command() {
System.out.println("Adding some files to the staging area");
}
#Override
public void run(String... args) throws Exception {
CommandLine commandLine = new CommandLine(appCLI);
commandLine.parseWithHandler(new CommandLine.RunLast(), args);
System.out.println("In the main method");
hello();
command();
}
}
Command class
#Controller
#CommandLine.Command(name = "xyz",description = "Performs ", mixinStandardHelpOptions = true, version = "1.0")
public class AppCLI implements Runnable{
#Override
public void run() {
System.out.println("Hello");
}
}
Main Class
#SpringBootApplication
public class Application {
private static Logger LOG = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Thanks in advance.
If you want to add command line parsing to Spring Boot's external
configuration in the #SpringBootApplication, do something like (see
Connect.java):
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine;
#SpringBootApplication
#Command
#NoArgsConstructor #ToString #Log4j2
public class Connect implements ApplicationRunner {
#Option(description = { "connection_file" }, names = { "-f" }, arity = "1")
#Value("${connection-file:#{null}}")
private String connection_file = null;
#Override
public void run(ApplicationArguments arguments) throws Exception {
new CommandLine(this)
.setCaseInsensitiveEnumValuesAllowed(true)
.parseArgs(arguments.getNonOptionArgs().toArray(new String [] { }));
/*
* Command implementation; command completes when this method
* completes.
*/
}
}
There is a similar example in
Install.java.

Flutter Client Subscription to Spring Boot Websocket Server

Below is my Spring Boot Code for scheduling messages to its connected clients.
But my FLUTTER application is not able to receive the the pushed messages from the websocket server.
#Service
public class GreetingService {
private final SimpMessagingTemplate simpMessagingTemplate;
private static final String WS_MESSAGE_TRANSFER_DESTINATION = "/topic/greetings";
private List<String> userNames = new ArrayList<>();
GreetingService(SimpMessagingTemplate simpMessagingTemplate) {
this.simpMessagingTemplate = simpMessagingTemplate;
}
public void sendMessages() {
for (String userName : userNames) {
simpMessagingTemplate.convertAndSendToUser(userName, WS_MESSAGE_TRANSFER_DESTINATION,
"Hallo " + userName + " at " + new Date().toString());
}
}
public void addUserName(String username) {
userNames.add(username);
}
}
Flutter Code :-
var channel = IOWebSocketChannel.connect("ws://1f470ad1bdc8.ngrok.io/ws");
channel.stream.listen((message) {
channel.sink.add("received!");
});
You have to create a Spring Configuration class for initializing the subscription paths.
#Configuration
#EnableWebSocketMessageBroker
public class WSocketBrokerConfiguration implements WebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/socket")
.setAllowedOrigins("*");
}
}

Session management in a Neo4J Flink sink

I am developing a data analytics app with Apache Flink and Neo4J (Community Edition).
In this application, the Flink sink must save/update relations in Neo4J.
Which is the best way for Neo4J session management, and why?
First implementation:
public class MySink extends RichSinkFunction<Link> {
private DbConfiguration dbconfig;
private Driver driver;
#Override
public void open(Configuration parameters) throws Exception {
this.driver = Neo4JManager.open(this.dbconfig);
}
#Override
public void close() throws Exception {
this.driver.close();
}
#Override
public void invoke(Link link) throws Exception {
Session session = this.driver.session();
Neo4JManager.saveLink(session, link);
session.close();
}
}
Second implementation:
public class MySink extends RichSinkFunction<Link> {
private DbConfiguration dbconfig;
private Driver driver;
private Session session;
#Override
public void open(Configuration parameters) throws Exception {
this.driver = Neo4JManager.open(this.dbconfig);
this.session = driver.session();
}
#Override
public void close() throws Exception {
this.session.close();
this.driver.close();
}
#Override
public void invoke(Link link) throws Exception {
Neo4JManager.saveLink(this.session, link);
}
}
In both implementations, the following functions have been used:
public class Neo4JManager {
public static Driver open(DbConfiguration dbconf) {
AuthToken auth = AuthTokens.basic(dbconf.getUsername(), dbconf.getPassword());
Config config = Config.build().withEncryptionLevel(Config.EncryptionLevel.NONE ).toConfig();
return GraphDatabase.driver(dbconf.getHostname(), auth, config);
}
public static void saveLink(Session session, Link link) {
Value params = parameters("x", link.x, "y", link.y);
session.run('CREATE (Person {id:{x}}-[FOLLOWS]->(Person {id:{y}}))'
}
}
Thank you.

Spring boot check external service status on boot

I want check some external http service before my Spring Boot is ready.
The url to the external web service are stored in a property file with a #ConfigurationProperties class.
How do this check i tried using a springApplication.addListner() with a ping method. But the property class have not then been initialized.
public class ApplicationStartListener implements ApplicationListener<ApplicationPreparedEvent> {
#Override
public void onApplicationEvent(ApplicationPreparedEvent event) {
String url = AppProp.getURL();
inet = InetAddress.getByName(url );
inet.isReachable(5000)
...
application.yml
tops:
http://service.com
#Component
#ConfigurationProperties("tops")
public class AppProp{
private static String url;
public static String getUrl() {
The easiest way to accomplish this is to implement the ApplicationRunner interface.
From the Spring Boot documentation [1]
If you need to run some specific code once the SpringApplication has started, you can implement the ApplicationRunner or CommandLineRunner interfaces. Both interfaces work in the same way and offer a single run method which will be called just before SpringApplication.run(…​) completes.
[1] https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-spring-application.html#boot-features-command-line-runner
Assuming you have url defined in application.properties:
#SpringBootApplication
public class MyApplication implements ApplicationRunner
{
#Inject
private AppConfig appConfig;
#Inject
private ConfigurableApplicationContext applicationContext;
public static void main(String[] args)
{
SpringApplication.run(MyApplication.class, args);
}
#Override
public void run(ApplicationArguments args) throws Exception
{
InetAddress inetAddress = InetAddress.getByName(appConfig.getUrl());
if (!inetAddress.isReachable(5000))
{
// Stop the application or do other things
}
}
#Component
#ConfigurationProperties
public static class AppConfig
{
private String url;
public String getUrl()
{
return url;
}
public void setUrl(String url)
{
this.url = url;
}
}
}
If you need even more control than this, you can use SpringApplicationRunListener [2]
[2] http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/SpringApplicationRunListener.html
#SpringBootApplication
public class MyApplication implements SpringApplicationRunListener
{
public MyApplication() { }
public MyApplication(SpringApplication springApplication, String[] args) { }
public static void main(String[] args)
{
SpringApplication.run(MyApplication.class, args);
}
#Override
public void started() { }
#Override
public void environmentPrepared(ConfigurableEnvironment environment)
{
// 1st opportunity
InetAddress inetAddress = InetAddress.getByName(environment.getProperty("url"));
if (!inetAddress.isReachable(5000))
{
// Stop the application or do other things
}
}
#Override
public void contextPrepared(ConfigurableApplicationContext context)
{
// 2nd opportunity
InetAddress inetAddress = InetAddress.getByName(context.getEnvironment().getProperty("url"));
if (!inetAddress.isReachable(5000))
{
// Stop the application or do other things
}
}
#Override
public void contextLoaded(ConfigurableApplicationContext context)
{
// 3rd opportunity
InetAddress inetAddress = InetAddress.getByName(context.getEnvironment().getProperty("url"));
if (!inetAddress.isReachable(5000))
{
// Stop the application or do other things
}
}
#Override
public void finished(ConfigurableApplicationContext context, Throwable exception)
{
// 4th opportunity
InetAddress inetAddress = InetAddress.getByName(context.getEnvironment().getProperty("url"));
if (!inetAddress.isReachable(5000))
{
// Stop the application or do other things
}
}
#Component
#ConfigurationProperties
public static class AppConfig {
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
}
then create META-INF\spring.factories and add
org.springframework.boot.SpringApplicationRunListener=com.foobar.MyApplication

Change main endpoint in Spring Data Rest (usind Spring Boot)

Im building a small application using Spring (Boot, Data, Data Rest).
I have some JpaRepositories that aumotatically are exported as Rest endpoints.
What i want to do is to change the base path from / to /api.
Now to list all people for example i do a GET to http://localhost:8080/people and i want the url to be http://localhost:8080/api/people.
I tried adding this config class but nothing happened (it seems that Spring Boot overrides this config):
public class SpringWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
#Override
protected Class<?>[] getRootConfigClasses()
{
return new Class<?>[] { Application.class};
}
#Override
protected Class<?>[] getServletConfigClasses()
{
return new Class<?>[] { RestExporterRestConfig.class, RepositoryRestMvcConfiguration.class };
}
#Override
protected String[] getServletMappings()
{
return new String[] { "/api/*" };
}
}
My Application.java:
#Configuration
#ComponentScan
#Import(RestExporterRestConfig.class)
#EnableJpaRepositories
#EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
and RestExporterRestConfig:
#Configuration
public class RestExporterRestConfig extends RepositoryRestMvcConfiguration {
#Bean
public Validator validator() {
return new LocalValidatorFactoryBean();
}
#Override
protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener v) {
v.addValidator("beforeCreate", validator());
}
#Bean
#Qualifier
public DefaultFormattingConversionService defaultConversionService() {
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
conversionService.addConverter(StringToDate.INSTANCE);
return conversionService;
}
#Bean
public DomainClassConverter<?> domainClassConverter() {
return new DomainClassConverter<DefaultFormattingConversionService>(defaultConversionService());
}
}
Well i figured it out. SpringWebAppInitializer is not necesary in this case. I just added this code to Application.java:
#Bean
public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet) {
ServletRegistrationBean reg = new ServletRegistrationBean(dispatcherServlet);
reg.addUrlMappings("/api/*");
return reg;
}
I think this is the correct way to modify (add, change mappings, etc) servlets using Spring Boot.

Resources