Skip to content

Commit

Permalink
feat: Improve Spring To Spring Beans definition compatibility - MEED-…
Browse files Browse the repository at this point in the history
…7576 - Meeds-io/meeds#2469

This change will enhance Spring contexts Beans sharing by allowing to reference Bean Interface rather than implementation between Spring contexts and without having to define the Interface As Service with Primary annotation in Implementation.
  • Loading branch information
boubaker committed Oct 9, 2024
1 parent 02a7f11 commit a1f5428
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 91 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
*/
package io.meeds.spring.kernel;

import static io.meeds.spring.kernel.KernelContainerLifecyclePlugin.addSpringContext;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
Expand All @@ -25,7 +28,6 @@
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;

import org.exoplatform.container.PortalContainer;
import org.exoplatform.container.RootContainer.PortalContainerPostInitTask;

import jakarta.servlet.ServletContext;

Expand All @@ -48,20 +50,13 @@ public PortalApplicationContext(ServletContext servletContext, DefaultListableBe

@Override
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
BeanDefinitionRegistry beanRegistry = (BeanDefinitionRegistry) beanFactory;
// Declare spring Context for integration on Kernel when it will start
// ( Kernel container is always started after all Spring contexts are
// started, see "PortalContainersCreator" in Meeds-io/meeds project )
KernelContainerLifecyclePlugin.addSpringContext(servletContext.getServletContextName(), this, beanRegistry);

// Delay Spring context finishing startup until the Kernel container is
// fully started
PortalContainer.addInitTask(servletContext, new PortalContainerPostInitTask() {
@Override
public void execute(ServletContext context, PortalContainer portalContainer) {
finishSpringContextStartup(beanFactory);
}
}, "portal");
addSpringContext(servletContext.getServletContextName(),
this,
(BeanDefinitionRegistry) beanFactory,
() -> finishSpringContextStartup(beanFactory));
}

@Override
Expand All @@ -72,11 +67,18 @@ protected void finishRefresh() {
private void finishSpringContextStartup(ConfigurableListableBeanFactory beanFactory) {
long start = System.currentTimeMillis();
LOG.info("Continue Spring context '{}' initialization", servletContext.getServletContextName());
PortalApplicationContext.super.finishBeanFactoryInitialization(beanFactory);
PortalApplicationContext.super.finishRefresh();
LOG.info("Spring context '{}' initialized in {}ms",
servletContext.getServletContextName(),
System.currentTimeMillis() - start);
try {
PortalApplicationContext.super.finishBeanFactoryInitialization(beanFactory);
PortalApplicationContext.super.finishRefresh();
LOG.info("Spring context '{}' initialized in {}ms",
servletContext.getServletContextName(),
System.currentTimeMillis() - start);
} catch (Exception e) {
throw new IllegalStateException(String.format("Error While finishing Beans Initialization in context '%s' with Bean names [%s] (May be related to issue Meeds-io/meeds#2469)",
servletContext.getServletContextName(),
StringUtils.join(beanFactory.getBeanDefinitionNames(), " , ")),
e);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;

/**
* A super class used to define {@link PortalApplicationContext} as the Spring
* Application Builder to use
*/
public abstract class PortalApplicationContextInitializer extends SpringBootServletInitializer {

private DefaultListableBeanFactory beanFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
LOG.info("Integrating Spring Context with Container. Application name = '{}' using Kernel configuration class '{}'",
applicationContext.getApplicationName(),
getTestClass());
addSpringContext("test", applicationContext, (BeanDefinitionRegistry) beanFactory);
addSpringContext("test", applicationContext, (BeanDefinitionRegistry) beanFactory, null);
bootContainer(getTestClass());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* This file is part of the Meeds project (https://meeds.io/).
*
* Copyright (C) 2020 - 2023 Meeds Association [email protected]
* Copyright (C) 2020 - 2024 Meeds Association [email protected]
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand All @@ -18,33 +18,10 @@
*/
package io.meeds.spring.module.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import org.exoplatform.commons.api.settings.SettingService;

import io.meeds.spring.module.model.TestModel;
import io.meeds.spring.module.storage.TestStorage;

@Service
public class TestService {

// Fake injection from Kernel for Testing Purpose
@Autowired
private SettingService settingService;

@Autowired
private TestStorage storage;
public interface TestService {

public TestModel save(TestModel model) {
if (model == null) {
throw new IllegalArgumentException("TestModel is mandatory");
}
if (settingService == null) {
// Fake exception
throw new IllegalStateException("SettingService is null");
}
return storage.save(model);
}
TestModel save(TestModel testModel);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* This file is part of the Meeds project (https://meeds.io/).
*
* Copyright (C) 2020 - 2024 Meeds Association [email protected]
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package io.meeds.spring.module.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import org.exoplatform.commons.api.settings.SettingService;

import io.meeds.spring.module.model.TestModel;
import io.meeds.spring.module.storage.TestStorage;

@Service
public class TestServiceImpl implements TestService {

// Fake injection from Kernel for Testing Purpose
@Autowired
private SettingService settingService;

@Autowired
private TestStorage storage;

@Override
public TestModel save(TestModel model) {
if (model == null) {
throw new IllegalArgumentException("TestModel is mandatory");
}
if (settingService == null) {
// Fake exception
throw new IllegalStateException("SettingService is null");
}
return storage.save(model);
}

}

0 comments on commit a1f5428

Please sign in to comment.