How can I use an externally created singleton to satisfly a dependency in Spring? - spring

Let's say I have a configuration like this:
#Configuration
open class AppConfig {
#Bean
open fun mainWindow(stage: Stage): MainWindow {
return MainWindow(stage)
}
}
I also have a class where my app gets initialized. I'm using JavaFX, so I can't create the stage myself, instead it gets passed in to a function.
class MyApplication : Application()
{
override fun start(stage: Stage)
{
// I can't create the stage myself.
val ctx = AnnotationConfigApplicationContext(AppConfig::class.java)
ctx.beanFactory.registerSingleton("stage", stage)
stage.run {
scene = Scene(mainWindow, 800.0, 600.0)
show()
}
}
}
I get an error in the configuration class that "Could not autowire. No beans of 'Stage' type found"
What can I do so that the stage I registered could be used to satisfy Stage dependencies?

Related

Quarkus #CacheResult is not working properly

I am trying to use quarkus-cache by following the appropriate quarkus doc. I have the below code setup
#ApplicationScoped
class MyClass {
public result doSomething() {
String remoteData = getRemoteData(url);
}
#CacheResult(cacheName = "myCacheName")
public String getRemoteData(String url) {
return remoteCall(url);
}
}
Usage
// Grpc impl class
// call to Myclass.doSomething()
Execution is not proceeding further when getRemoteData() is called the first time. Also, not getting any error.
Am I missing something?

axon 4 snapshot in demand

I work with spring boot and axon example, i implement the snapshot feature, with the below code is working fine, after 3 events i found the data in the table snapshot_event_entry in the database
#Configuration
#AutoConfigureAfter(value = { AxonAutoConfiguration.class })
public class AxonConfig {
#Bean
public SnapshotTriggerDefinition catalogSnapshotTrigger(Snapshotter snapshotter) {
return new EventCountSnapshotTriggerDefinition(snapshotter, 3);
}
}
#Aggregate(snapshotTriggerDefinition = "catalogSnapshotTrigger")
public class CatalogAggregate { }
My question, is there a method to do a snapshot in demand? That means i want to implement an api to do the snapshot, not automatically after 3 events
there is nothing already in place.
One way to implement what you need is to create a dedicated Command, eg PerformShapshotCmd, that will carry the aggregateId information, and a #CommandHandler into your Aggregate. You could then let Spring autowire the Snapshotter instance bean, and call for the scheduleSnapshot(Class<?> aggregateType, String aggregateIdentifier) method.
Below some code snippet that could guide you.
data class PerformShapshotCmd(#TargetAggregateIdentifier val id: String)
#CommandHandler
public void handle(PerformShapshotCmd cmd, Snapshotter snapshotter) {
logger.debug("handling {}", cmd);
snapshotter.scheduleSnapshot(this.getClass(), cmd.getId());
}
You should also define one Bean of type Snapshotter into your config
#Bean
public SpringAggregateSnapshotterFactoryBean snapshotter() {
SpringAggregateSnapshotterFactoryBean springAggregateSnapshotterFactoryBean = new SpringAggregateSnapshotterFactoryBean();
//Setting async executors
springAggregateSnapshotterFactoryBean.setExecutor(Executors.newSingleThreadExecutor());
return springAggregateSnapshotterFactoryBean;
}
Please note that the first argument of your commandHandler needs to be the command, otherwise the framework will complain with an exception at startup time.

#PostConstruct method runs before flyway

I know this kind of question has been asked before.
I have a method which is annotated with #PostConstruct.
The methods assumes that all Flyway scripts have been executed before invocation.
It seems that Flyway also uses #PostConstruct annotated methods and that these methods are called after my method.
I tried to annotate my method with #DependOn and different flyway beennames.
Unfortunately without success. Can anybody help me.
Solution:
I would set a dependency on the FlywayMigrationInitializer in the constructor. When the Initializer is created and set up, the migrations are run.
Or you can depend on the flywayInitializer bean (#DependsOn("flywayInitializer")). The bean is named flywayInitializer, of the class FlywayMigrationInitializer and it is created in FlywayAutoConfiguration.java.
FlywayMigrationInitializer implements InitializingBean and calls the migrate method in the afterPropertiesSet method.
Example:
#Component
// #DependsOn("flywayInitializer")
#Slf4j
public class TestPostConstruct {
public TestPostConstruct(FlywayMigrationInitializer flywayForceInitialization) {
}
#PostConstruct
public void testPostConstruct() {
log.info("----> in testPostConstruct");
}
}
The Spring Boot log:
INFO 4760 --- [main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.130s)
INFO 4760 --- [main] c.example.flywayinit.TestPostConstruct : ----> in testPostConstruct
For new Flyway this work (use Flyway callbacks)
#Configuration
class FlywayConfig(env: Environment) {
private val env: Environment
init {
this.env = env
}
#Bean(initMethod = "migrate")
fun flyway(dbLoadService: DbLoadService): Flyway {
return Flyway(
Flyway.configure()
.baselineOnMigrate(true)
.dataSource(
env.getRequiredProperty("spring.datasource.url"),
env.getRequiredProperty("spring.datasource.username"),
env.getRequiredProperty("spring.datasource.password")
)
//запуск загрузки из базы после окончания миграции
.callbacks(FlywayMigrationsCompleteCallback {
dbLoadService.loadAllCertificateInformation()
})
)
}
class FlywayMigrationsCompleteCallback(private val callback: () -> Unit) : Callback {
override fun supports(event: Event?, context: Context?): Boolean {
return event == Event.AFTER_MIGRATE
}
override fun canHandleInTransaction(event: Event?, context: Context?): Boolean {
return true
}
override fun handle(event: Event?, context: Context?) {
callback()
}
override fun getCallbackName(): String {
return FlywayMigrationsCompleteCallback::class.simpleName!!
}
}
#Component
class DbLoadService(private val certificateRepository:CertificateRepository) {
#Volatile var certificate: List<Certificate>?=null
fun loadAllCertificateInformation(){
val findAll = certificateRepository.findAll()
runBlocking {
certificate = findAll.toList()
}
}
}

Weblogic,EJB, $Proxy99 class cast exception

Following are the modules in my project,
1. EJB module (version 3): We prepare ejb jar of this module and deploy on Weblogic11g server. It deals with database operation. It has #local, #Remote interface and #stateless classes implementing #local,#Remote interfaces.
2. Web Application : This web application takes inputs (user uploads file) from users, validates file and inserts data into database. It uses RMI.
Problem: On production (weblogic 11g server ) sometimes we observe exception saying $Proxy99 cannot be cast to "Remote interface name" (for different different classes) e.g com.xyz.fileProcessSetting.FileProcessSttgFacadeRemote.
But after some time when we again upload file, it gets uploaded successfully without any error.
Now, I do not understand how come these remote objects becomes temporarily unavailable? Never faced this issue on development/UAT environment. Also no idea how to reproduce and fix it.
Please help. Thanks in advance.
#Remote
public interface FileProcessSttgFacadeRemote {
//methods
}
#Local
public interface FileProcessSttgFacadeLocal {
//methods
}
#Stateless
public class FileProcessSttgFacade implements FileProcessSttgFacadeLocal, FileProcessSttgFacadeRemote {
//methods
}
in weblogic-ejb-jar.xml
<weblogic-enterprise-bean>
<ejb-name>FileProcessSttgFacade</ejb-name>
<stateless-session-descriptor>
<business-interface-jndi-name-map>
<business-remote>com.xyz.fileProcessSetting.FileProcessSttgFacadeRemote</business-remote>
<jndi-name>FileProcessSttgFacade</jndi-name>
</business-interface-jndi-name-map>
</stateless-session-descriptor>
</weblogic-enterprise-bean>
In web application also in ejb module whenever we want to call methods we use following lookup method to get remote object:
public class someclass extends EjbLocator {
public void someMethod(){
FileProcessSttgFacadeRemote fpfr = (FileProcessSttgFacadeRemote) getService("FileProcessSttgFacade");
//other code
}
}
Following is the class used for JNDI lookup:
public class EjbLocator {
public Object getService(final String jndiName) throws Exception {
try {
obj = getDefaultContext().lookup(jndiName);
} catch (final Exception exp) {
exp.printStackTrace();
}
return obj;
}
protected Context getDefaultContext() {
try {
final Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL,"weblogic");
env.put(Context.SECURITY_CREDENTIALS, "password");
env.put(Context.PROVIDER_URL, "t3://<ip>:<port>");
defaultContext = new InitialContext(env);
return defaultContext;
} catch (final NamingException nExp) {
nExp.printStackTrace();
}
return null;
}
}

What could cause a class implementing "ApplicationListener<ContextRefreshedEvent>" not to be notified of a "ContextRefreshedEvent"

I have a Spring application listener implementing ApplicationListener<ContextRefreshedEvent> as follows:
#Profile({ Profiles.DEFAULT, Profiles.CLOUD, Profiles.TEST, Profiles.DEV })
#Component
public class BootstrapLoaderListener implements ApplicationListener<ContextRefreshedEvent>, ResourceLoaderAware, Ordered {
private static final Logger log = Logger.getLogger(BootstrapLoaderListener.class);
#Override
public int getOrder() {
return HIGHEST_PRECEDENCE;
}
#Autowired
private DayToTimeSlotRepository dayToTimeSlotRepository;
#Autowired
private LanguageRepository languageRepository;
private ResourceLoader resourceLoader;
#Override
#Transactional
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
initApplication();
}
private void initApplication() {
if (dayToTimeSlotRepository.count() == 0) {
initDayToTimeSlots();
}
if (languageRepository.count() == 0) {
initLanguages();
}
}
private void initDayToTimeSlots() {
for (Day day : Day.values()) {
for (TimeSlot timeSlot : TimeSlot.values()) {
DayToTimeSlot dayToTimeSlot = new DayToTimeSlot();
dayToTimeSlot.setDay(day);
dayToTimeSlot.setTimeSlot(timeSlot);
dayToTimeSlot.setDisabled(isDayToTimeSlotDisabled(timeSlot, day));
dayToTimeSlotRepository.save(dayToTimeSlot);
}
}
}
...
I rely on this listener class to insert reference data that is not updated nor deleted and I have a number of Spring integration tests that use this class, one of which fails because the listener is not notified (initDayToTimeSlots is not invoked).
I am trying to pinpoint where the problem comes from by debugging the tests and I noticed that when I run the problematic test class on its own, the tests contained in the class pass (indicating that the listener is notified) but when I run all of my application test classes together, the listener is not notified causing the test to fail (indicating that some other test changes/dirties the context).
Here is the problematic test class:
#ActiveProfiles({ Profiles.TEST })
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { FullIntegrationTestConfiguration.class, BaseTestConfiguration.class })
public class RegularDayToTimeSlotsTest {
private static int NUMBER_OF_REGULAR_DAY_TO_TIME_SLOTS_IN_WEEK = 25;
#Before
public void setup() {
//org.hsqldb.util.DatabaseManagerSwing.main(new String[] { "--url", "jdbc:hsqldb:mem:bignibou", "--noexit" });
}
#Autowired
private AdvertisementService advertisementService;
#Test
public void shouldNotContainSaturdayNorSunday() {
Set<DayToTimeSlot> regularDayToTimeSlots = advertisementService.retrieveRegularDayToTimeSlots();
assertThat(regularDayToTimeSlots).onProperty("day").excludes(Day.SATURDAY, Day.SUNDAY);
assertThat(regularDayToTimeSlots).onProperty("day").contains(Day.MONDAY, Day.THUESDAY);
}
#Test
public void shouldNotContainEveningNorNighttime() {
Set<DayToTimeSlot> regularDayToTimeSlots = advertisementService.retrieveRegularDayToTimeSlots();
assertThat(regularDayToTimeSlots).onProperty("timeSlot").excludes(TimeSlot.EVENING, TimeSlot.NIGHTTIME);
assertThat(regularDayToTimeSlots).onProperty("timeSlot").contains(TimeSlot.MORNING, TimeSlot.LUNCHTIME);
}
#Test
public void shouldContainCorrectNumberOfDayToTimeSlots() {
Set<DayToTimeSlot> regularDayToTimeSlots = advertisementService.retrieveRegularDayToTimeSlots();
assertThat(regularDayToTimeSlots).hasSize(NUMBER_OF_REGULAR_DAY_TO_TIME_SLOTS_IN_WEEK);
}
}
I am puzzled to see that both the prepareRefresh() and finishRefresh() methods within AbstractApplicationContext.refresh method are indeed called but that my listener is not notified...
Has anyone got any clue?
P.S. I know I could use #DirtiesContext in order to get a fresh context and I also know it would be preferable not to rely on an application listener for my tests but I am very anxious to understand what is going wrong here. Hence this post.
edit 1: When I debug the problematic test class in isolation, I notice that the event source is of type GenericApplicationContext and as explained above the test passes OK because the listener is notified. However when all test classes are run together, the event source is, oddly enough, of type GenericWebApplicationContext and no listener is found here in SimpleApplicationEventMulticaster:
#Override
public void multicastEvent(final ApplicationEvent event) {
for (final ApplicationListener<?> listener : getApplicationListeners(event)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
#Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
edit 2: my comments in edit 1 make me asks myself what is responsible for determining the uniqueness of context configuration...
For instance, I have only two test classes with the following context configuration:
#ContextConfiguration(classes = { FullIntegrationTestConfiguration.class, BaseTestConfiguration.class })
I guess they both will use the same cached context, won't they? Now can a third class use the same cached context even though it does not have exactly the same context configuration?
Why does my test get a GenericWebApplicationContext above?
my comments in edit 1 make me asks myself what is responsible for
determining the uniqueness of context configuration...
The elements that make up the context cache key are described in the Context caching section of the "Testing" chapter in the reference manual.
For instance, I have only two test classes with the following context
configuration:
#ContextConfiguration(classes = {
FullIntegrationTestConfiguration.class, BaseTestConfiguration.class })
I guess they both will use the same cached context, won't they?
If they declare only those two configuration classes in that exact order, then yes.
Now can a third class use the same cached context even though it does not
have exactly the same context configuration?
No.
Why does my test get a GenericWebApplicationContext above?
A GenericWebApplicationContext is only loaded if your test class (or one of its superclasses) is annotated with #WebAppConfiguration.
If you are experiencing behavior that contradicts this, then you have discovered a bug in which case we would appreciate it if you could produce a scaled down test project in the issue repository and create a corresponding JIRA issue against the "Spring Framework" and its "Test" component.
Thanks,
Sam (author of the Spring TestContext Framework)

Resources