How do we use a custom CqlSession on a Spring Webflux application combined with Spring starter reactive Cassandra please?
I am currently doing the following, which is working perfectly:
public class BaseCassandraConfiguration extends AbstractReactiveCassandraConfiguration {
#Bean
#NonNull
#Override
public CqlSessionFactoryBean cassandraSession() {
final CqlSessionFactoryBean cqlSessionFactoryBean = new CqlSessionFactoryBean();
cqlSessionFactoryBean.setContactPoints(contactPoints);
cqlSessionFactoryBean.setKeyspaceName(keyspace);
cqlSessionFactoryBean.setLocalDatacenter(datacenter);
cqlSessionFactoryBean.setPort(port);
cqlSessionFactoryBean.setUsername(username);
cqlSessionFactoryBean.setPassword(passPhrase);
return cqlSessionFactoryBean;
}
However, I would like to use a custom session, something like:
CqlSession session = CqlSession.builder().build();
How do we tell this configuration to use it?
Thank you
Option 1:
If you are looking to completely override the auto configured CqlSession bean, you can do so by providing your own CqlSesson bean ie.
#Bean
public CqlSession cassandraSession() {
return CqlSession.builder().withClientId(MyClientId).build();
}
The downside of override the entire bean is that you will lose the ability to configure this session via application properties and you will lose the defaults spring boot ships with.
Option 2:
If you want to leave the default values provided by spring boot and have the ability to configure the session via application properties you can use CqlSessionBuilderCustomizer to provide specific custom configurations to the CqlSession. This can be achieved by defining a bean of that type ie:
#Bean
public CqlSessionBuilderCustomizer myCustomiser() {
return cqlSessionBuilder -> cqlSessionBuilder.withClientId(MyClientId);;
}
My personal preference is option 2 as it maintains the functionality provided by spring boot which in my opinion results in an easier to maintain application over time.
Related
scenario:
we store some encrypted data in db as blob. When reading/saving it, we need to decrypt/encrypt it using an external service.
because it is actually a spring bean using an external service, we cannot use the code generator like dealing with enums.
I don't want to use dslContext.select(field1, field2.convertFrom).from(TABLE_NAME) because you need to specify every fields of the table.
It is convenient to use dslContext.selectFrom(TABLE_NAME). wonder if any way we can register the converter bean in such query to perform encrypt and decrypt on the fly.
Thanks
Edit: I ended up using a service to encrypt/decrypt the value when it is actually used. Calling an external service is relatively expensive. Sometimes the value isn't used in the request. It may not make sense to always decrypt the value when reading from db using the converter.
because it is actually a spring bean using an external service, we cannot use the code generator like dealing with enums.
Why not? Just because Spring favours dependency injection, and you currently (as of jOOQ 3.15) cannot inject anything into jOOQ Converter and Binding instances, doesn't mean you can't use other means of looking up such a service. Depending on what you have available, you could use some JNDI lookup, or other means to discover that service when needed, from within your Converter.
Another option would be to use a ConverterProvider and register your logic inside of that. That wouldn't produce your custom type inside of jOOQ records, but whenver you convert your blob to your custom data type, e.g. using reflection.
How to access Spring Beans without Dependency Injection?
If you need to access your Spring Beans you don't need Dependency Injection. Simply create the following class and you can get beans from the static method getBean():
#Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static <T> T getBean(Class<T> type) {
return applicationContext.getBean(type);
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextHolder.applicationContext = applicationContext;
}
}
I followed Alexander Duemont's blog, trying to implement a Java Spring Boot application that consumes Cloud Foundry Destination. The Destination has a custom OData V2 behind it, coming from an On-Premise ERP system. For local dev, when I perform the Maven build, the Integration-Tests module registers failure due to dependency injection
This is part of my Controller
#RestController
#RequestMapping("/resources")
public class ClassificationsController {
private static final Logger logger = CloudLoggerFactory.getLogger(ClassificationsController.class);
private final ClassificationService service;
public ClassificationsController(#Nonnull final ClassificationService service) {
this.service = service;
}
…..
}
The #Nonnull final ClassificationService Service causes org.springframework.beans.factory.UnsatisfiedDependencyException
I cannot use Spring stereotype annotations on generated Service classes (Fluent) to create Beans!
This question is more likely related to Spring Boot configuration.
I'm assuming ClassificationService is an interface and the implementing class exists in the same package.
Please make sure...
... to add the implementing class of ClassificationService to your component scan / test runtime. Feel free to share the integration test code to setup the test environment. Maybe the additional class reference is missing.
... to correctly annotate the respective Application class of your Spring Boot project. For example, assuming your ClassificationService resides in org.example.services.classification, while the rest of your application uses org.example.app. Your basic Application class would look like this, when following the Cloud SDK guide:
#SpringBootApplication
#ComponentScan({"com.sap.cloud.sdk", "org.example.services.classification", "org.example.app"})
#ServletComponentScan({"com.sap.cloud.sdk", "org.example.app"})
public class Application extends SpringBootServletInitializer
{
#Override
protected SpringApplicationBuilder configure( final SpringApplicationBuilder application )
{
return application.sources(Application.class);
}
public static void main( final String[] args )
{
SpringApplication.run(Application.class, args);
}
}
... to annotate the implementing class of ClassificationService with javax.inject.Named. In case you have multiple implementations of the same interface, make sure to give the not-used class a custom (unique) value for the #Named annotation.
... to look for exceptions (Class not found) in the application log during startup.
I am new to JSF/Facelets and I am creating an application that does the usual CRUD operations over a (No SQL) database. The database has an API that allows the creation of a pool of connections, and then from this object my operations can take and release connections. I suppose this pool has to be created only once for the whole application when it is deployed, be shared (as static?) and closed once the application is destroyed. Is my approach correct? What is the best practice to do this? I have no idea of where I should place my code and how I should call it.
With my old SQL database I used to configure a "testOnBorrow" and a "validationQuery" in the context.xml Resource so I didn't have to create an explicit pool programmatically.
I found two great tutorials (here and here) but I can't figure out from them where to put the code that creates the pool.
Note: I know this might be only a Servlet problem, but I am tagging it as JSF since I don't know if there is a way to do this in JSF (like an application scoped bean). Thanks.
EDIT
Looking at the fact that I cannot find a JAR with a DataSource for the database to be loaded via context.xml, perhaps my question should be more specific: where can I run code once, when a JSF application is deployed and where can I run code when a JSF application is destroyed?
You can implement a weblistner( i.e ServletContextListener). and can use contextInitialized , contextDestroyed method of that to create and destroy your connection pool
Sample :
#WebListener
public class ContextWebListner implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
// initialize connection pool.
}
#Override
public void contextDestroyed(ServletContextEvent event) {
// Destroy connection pool.
}
}
For my SFTP client project, I am using spring integration. We have different clients and have to connect to different SFTP servers, but, all of the logic is same, so I have abstracted them out into AbstractSFTPEndPoint. Each client-specific class implements getClientId(), which is used by AbstractSFTPEndPoint to get client-specific details like SFTP credentials.
However, the entire logic is same for all the clients, but I am still having to implement specific classes for each client. This is mainly because we need separate "MessageSource" for each client.
How can I get rid of this duplication?
public class SFTPEndPointForClientAAAA extends AbstractSFTPEndPoint {
public String getClientId(){
return "clientAAAA";
}
#Bean(name = "channelForClientAAAA")
public QueueChannel inputFileChannel() {
return super.inputFileChannel();
}
#ServiceActivator(inputChannel = "channelForClientAAAA", poller = #Poller(fixedDelay = "500"))
public void serviceActivator(Message message) {
super.serviceActivator(message);
}
#Bean(name = "messageSourceForClientAAAA")
#InboundChannelAdapter(value = "channelForClientAAAA",
poller = #Poller(fixedDelay = "50", maxMessagesPerPoll = "2"))
public MessageSource messageSource() {
return super.messageSource();
}
}
Basically I have a bunch of SFTP hosts to connect to and apply same logic. I want that to be done automatically without having to implement class for each SFTP host.
See the dynamic ftp sample. It uses XML but the same techniques apply to Java configuration. It uses outbound adapters; inbound are a little more complicated because you might need to hook them into a common context. There are links in the readme for how to do that.
However, I recently answered a similar question for multiple IMAP mail adapters using Java configuration and then a follow-up question.
You should be able to use the technique used there.
I have a simple application that injects another component
#ComponentScan
#EnableAutoConfiguration
#Configuration
class Application {
static void main(String[] args) {
SpringApplication.run(Application, args)
}
#Bean
AuthorizationServerTokenServices tokenServices() {
return MY THING HERE
}
}
I'd like a quick/minimal way to new this up and grab the item springboot wires up (for tokenServices in this example). I'm trying to get at this to verify some configuration/settings/etc using TestNG
I should also say that I"m not using any xml to configure this (using gradle/groovy/springboot)
You can easily introduce conditional bean with the help of Spring profiles.
In your case the code would look like:
#Configuration
#Profile("tokenService")
public TestTokenServiceConfig {
#Primary
#Bean
AuthorizationServerTokenServices tokenServices() {
//implementation
}
}
The custom implementation you supply in this class will only be used by Spring in case the profile tokenService is active. The use of #Primary is needed in order to make Spring use the specified bean instead of any others present in the application context.
Also note that since you are going to be using the custom service in a test environment, you could easily mock the implementation using Mockito (or whatever other mocking framework you prefer)
And the actual integration test would be something like:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#ActiveProfiles("tokenService")
class YourIntegrationTest {
#Autowired
AuthorizationServerTokenServices tokenServices;
//test
}