I would like to use fongo 2.0.x in my Spring boot application, but I getting errror
Error:(23, 44) java: cannot access com.mongodb.operation.OperationExecutor
class file for com.mongodb.operation.OperationExecutor not found
Here is my AbstractMongoConfiguration
#Configuration
#ComponentScan("com.foo")
public class MongoDbConfig extends AbstractMongoConfiguration {
#Override
protected String getDatabaseName() {
return "demo";
}
#Override
public Mongo mongo() throws Exception {
return new Fongo(getDatabaseName()).getMongo(); //this line throws the error
}
}
From the Fongo documentation:
It has a "provided" dependency on the mongo-java-driver and was tested with 2.13.0 and 3.0.1.
So Fongo wants mongo-java-driver on the classpath, and I'm guessing you don't have it (or at least not in the test scope).
So make sure the following is in your build script:
For Maven:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.4.1</version>
<scope>test</scope>
</dependency>
For Gradle:
testCompile 'org.mongodb:mongo-java-driver:3.4.1'
Related
I have IdentManagerApp with regular SpringBoot 2.6.8 and Kafka producers and consumers. Additionally I have custom Kafka configurations and failure scenarios handling with Retry/DLT topics. The respective factories creation need beans like :
ConcurrentKafkaListenerContainerFactory,
ConcurrentKafkaListenerContainerFactoryConfigurer configurer,
ConsumerFactory<Object, Object> kafkaConsumerFactoryOriginalToRetry,
KafkaTemplate<String, String> kafkaTemplate,
KafkaListenerEndpointRegistry registry,
etc
While all of that works smooth while running application, it doesnt go well while running Junits.
I keep getting errors like -
'org.springframework.boot.autoconfigure.kafka.ConcurrentKafkaListenerContainerFactoryConfigurer' that could not be found.
OR
Field registry in <package> required a bean of type 'org.springframework.kafka.config.KafkaListenerEndpointRegistry' that could not be found.
I fix one and other one pops up.
Is EmbeddedKafka compatible with exhaustive unit testing for springboot + Kafka ?
My simple test config looks like -
Main class :
#DirtiesContext
#EmbeddedKafka(partitions = 1, brokerProperties = { "listeners=PLAINTEXT://localhost:8888", "port=8888" })
#EnableKafkaCustomization
#SpringBootTest(classes = IdentManagerApp.class)
class OrchestratorAppTests {
#Test
void contextLoads() {
}
}
Ultra simple test class, doesnt even have Kafka related operations yet -
#ExtendWith(MockitoExtension.class)
#Import({
KafkaConfiguration.class
})
#ContextConfiguration
#WebMvcTest(controllers = IncomingRequestController.class)
public class IncomingRequestControllerTest { . . . . . }
Pom has below with Springboot's 2.6.8
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka-test</artifactId>
<scope>test</scope>
</dependency>
I'm trying to use an EJB on a Spring boot application. This application runs in 'undertow' and it can call an EJB on a JBoss EAP (Jboss EAP 7.0).
I tried to configure the application to use Oracle XA transactions without success.
What I need is that when the Spring boot app calls the EJB and, after the call, some failure occurs on this app that EJB does a rollback the previous work.
Follows some configurations of the spring boot app:
pom
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-ejb-client-bom</artifactId>
<version>17.0.0.Final</version>
<type>pom</type>
</dependency>
</dependencies>
properties
spring.datasource.url=jdbc:oracle:thin:#<host>:<port>:<data>
spring.datasource.username=user
spring.datasource.password=pass
spring.datasource.xa.data-source-class-name=bitronix.tm.resource.jdbc.lrc.LrcXADataSource
spring.datasource.xa.properties.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.jpa.properties.hibernate.hbm2ddl.schema_filter_provider=<class>
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.integration.envers.enabled=false
App Class
Configuration
#SpringBootApplication
#EnableTransactionManagement
#ComponentScan(basePackages={...,...})
#EntityScan(basePackages={...,...,...})
public class SpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootApplication .class, args);
}
EJB 'producer'
#Configuration
public class EJBConfiguration {
#Bean
public Context context() throws NamingException {
Properties jndiProps = new Properties();
jndiProps.put("java.naming.factory.initial", "org.jboss.naming.remote.client.InitialContextFactory");
jndiProps.put("jboss.naming.client.ejb.context", true);
jndiProps.put("java.naming.provider.url", "http-remoting://localhost:8081");
return new InitialContext(jndiProps);
}
#Bean
public EJBRemote(Context c) throws NamingException {
return (EJBRemote) c.lookup("full EJB remote name")
}
}
the call of EJB is made as follows:
stuff
Spring boot App controller
class AppControler {
#AutoWired
Service service
#PostMapping("/")
#Transactional
public ResponseEntity controllerMethod() {
return new ResponseEntity<>(this.service.doStuff(), HttpStatus.OK);
}
}
Spring boot app service
class Service {
#Autowired
private EJBRemote EJBRemote;
#Autowired
private DAOObject dao;
#TransactionAttribute(TransactionAttributeType.MANDATORY)
Public Object doStuff() {
dao.save();
EJBRemote.saveSomeThing(); // OK operation, needs to rolback if oerros occurs after
dao.saveOtherThing();// errors occurs
}
}
the EJB implementation class on JBoss EAP is like
class EJBRemoteImpl implements EJBRemote {
#Override
public void saveSomeThing() {
someDao.save();
}
}
So when a error occurs in 'dao.saveOtherThing();' the operation made in 'EJBRemove.saveSomeThing();' needs to rolback.
If I'm put '#TransactionAttribute(TransactionAttributeType.MANDATORY)' on EJB this error occurs:
javax.ejb.EJBTransactionRequiredException: WFLYEJB0062: A transaction is required to call org.jboss.invocation.InterceptorContext#493c9dbb
at org.jboss.as.ejb3.tx.CMTTxInterceptor.mandatory(CMTTxInterceptor.java:289) ~[na:na]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:233) ~[na:na]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) ~[na:na]
at org.jboss.as.ejb3.remote.EJBRemoteTransactionPropagatingInterceptor.processInvocation(EJBRemoteTransactionPropagatingInterceptor.java:79) ~[na:na]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) ~[na:na]
at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41) ~[na:na]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) ~[na:na]
at org.jboss.as.ejb3.component.invocationmetrics.WaitTimeInterceptor.processInvocation(WaitTimeInterceptor.java:43) ~[na:na]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340) ~[na:na]
.
.
.
If the annotation (#TransactionAttribute(TransactionAttributeType.MANDATORY)) is not present the calls to EJB occurs normally but the rollback not occurs.
You are trying create an EJB transaction in a Spring Service, if you want do it you need convert your service to an EJB, so automatically all operations will be TransactionAttribute.REQUIRED, if you want that this method work with a Spring transaction, you need to use #Transactional(propagation = Propagation.MANDATORY) from Spring (org.springframework.transaction.annotation.Transactional), but I don't know if an Spring transaction works in distributed context, but you can try. If not converting the Bean to EJB will work.
After adding cache2k to my project some #SpringBootTest's stopped working with an error:
java.lang.IllegalStateException: Cache already created: 'cache'
Below I provide the minimal example to reproduce:
Go to start.spring.io and create a simplest Maven project with Cache starter, then add cache2k dependencies:
<properties>
<java.version>1.8</java.version>
<cache2k-version>1.2.2.Final</cache2k-version>
</properties>
<dependencies>
<dependency>
<groupId>org.cache2k</groupId>
<artifactId>cache2k-api</artifactId>
<version>${cache2k-version}</version>
</dependency>
<dependency>
<groupId>org.cache2k</groupId>
<artifactId>cache2k-core</artifactId>
<version>${cache2k-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.cache2k</groupId>
<artifactId>cache2k-spring</artifactId>
<version>${cache2k-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Now configure the simplest cache:
#SpringBootApplication
#EnableCaching
public class CachingDemoApplication {
public static void main(String[] args) {
SpringApplication.run(CachingDemoApplication.class, args);
}
#Bean
public CacheManager springCacheManager() {
SpringCache2kCacheManager cacheManager = new SpringCache2kCacheManager();
cacheManager.addCaches(b -> b.name("cache"));
return cacheManager;
}
}
And add any service (which we will #MockBean in one of our tests:
#Service
public class SomeService {
public String getString() {
System.out.println("Executing service method");
return "foo";
}
}
Now two #SpringBootTest tests are required to reproduce the issue:
#SpringBootTest
#RunWith(SpringRunner.class)
public class SpringBootAppTest {
#Test
public void getString() {
System.out.println("Empty test");
}
}
#RunWith(SpringRunner.class)
#SpringBootTest
public class WithMockedBeanTest {
#MockBean
SomeService service;
#Test
public void contextLoads() {
}
}
Notice that the 2nd test has mocked #MockBean. This causes an error (stacktrace below).
Caused by: java.lang.IllegalStateException: Cache already created: 'cache'
at org.cache2k.core.CacheManagerImpl.newCache(CacheManagerImpl.java:174)
at org.cache2k.core.InternalCache2kBuilder.buildAsIs(InternalCache2kBuilder.java:239)
at org.cache2k.core.InternalCache2kBuilder.build(InternalCache2kBuilder.java:182)
at org.cache2k.core.Cache2kCoreProviderImpl.createCache(Cache2kCoreProviderImpl.java:215)
at org.cache2k.Cache2kBuilder.build(Cache2kBuilder.java:837)
at org.cache2k.extra.spring.SpringCache2kCacheManager.buildAndWrap(SpringCache2kCacheManager.java:205)
at org.cache2k.extra.spring.SpringCache2kCacheManager.lambda$addCache$2(SpringCache2kCacheManager.java:143)
at java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1853)
at org.cache2k.extra.spring.SpringCache2kCacheManager.addCache(SpringCache2kCacheManager.java:141)
at org.cache2k.extra.spring.SpringCache2kCacheManager.addCaches(SpringCache2kCacheManager.java:132)
at com.example.cachingdemo.CachingDemoApplication.springCacheManager(CachingDemoApplication.java:23)
at com.example.cachingdemo.CachingDemoApplication$$EnhancerBySpringCGLIB$$2dce99ca.CGLIB$springCacheManager$0(<generated>)
at com.example.cachingdemo.CachingDemoApplication$$EnhancerBySpringCGLIB$$2dce99ca$$FastClassBySpringCGLIB$$bbd240c0.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
at com.example.cachingdemo.CachingDemoApplication$$EnhancerBySpringCGLIB$$2dce99ca.springCacheManager(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 52 more
If you remove #MockBean, both tests will pass.
How can I avoid this error in my test suite?
Your second test represents a different ApplicationContext altogether so the test framework will initiate a dedicated one for it. If cache2k is stateful (for instance sharing the CacheManager for a given classloader if it already exists), the second context will attempt to create a new CacheManager while the first one is still active.
You either need to flag one of the test as dirty (see #DirtiesContext) which will close the context and shut down the CacheManager, or you can replace the cache infrastructure by an option that does not require all that, see #AutoConfigureCache.
If cache2k works in such a way that it requires you to dirty the context, I'd highly recommend to swap it using the later options.
Since I do not want any custom behavior in test, but just want to get rid of this error, the solution is to create CacheManager using unique name like this:
#Bean
public CacheManager springCacheManager() {
SpringCache2kCacheManager cacheManager = new SpringCache2kCacheManager("spring-" + hashCode());
cacheManager.addCaches(b -> b.name("cache"));
return cacheManager;
}
I encountered the same error when using cache2k with Spring Dev Tools, and ended up with the following code as the solution:
#Bean
public CacheManager cacheManager() {
SpringCache2kCacheManager cacheManager = new SpringCache2kCacheManager();
// To avoid the "Caused by: java.lang.IllegalStateException: Cache already created:"
// error when Spring DevTools is enabled and code reloaded
if (cacheManager.getCacheNames().stream()
.filter(name -> name.equals("cache"))
.count() == 0) {
cacheManager.addCaches(
b -> b.name("cache")
);
}
return cacheManager;
}
So I just upgraded my Spring Boot web app to 2.0.0, In my main Application class I have this method:
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext rootAppContext = createRootApplicationContext(servletContext);
if (rootAppContext != null) {
servletContext.addListener(new RequestContextListener());
}
else {
logger.debug("No ContextLoaderListener registered");
}
}
But now I am getting a compile error:
The method addListener(RequestContextListener) is undefined for the type ServletContext
What's weird is that the ServletContext is the problem, not Spring boot. It no longer has any add* methods. Did Spring5/Boot2 upgrade the servlet specs, and
What is the correct way to do this now?
It was a ServletContext issue. Spring boot 2 uses servlet specs 3.1.0, and apparently no longer support 2.5, which is what I had in my pom. So I replaced it with this:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
And it worked fine. Hope this helps someone.
I am having an strange behavior, using spring 4.1.1 I get this error.
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project newvalia-view: Compilation failure
[ERROR] /C:/Users/edu/IdeaProjects/newvalia/newvalia- view/src/main/java/com/newvalia/web/init/WebInitContext.java:[19,12] cannot access org.springframework.context.annotation.AnnotationConfigRegistry
[ERROR] class file for org.springframework.context.annotation.AnnotationConfigRegistry not found
while if I downgrade to spring 4.0.7 it compiles correctly.
I am using simple spring webmwc configuration :
#Configuration
#ComponentScan(value = "com.newvalia.web")
#EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
}
public class WebInitContext implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(WebMvcConfig.class);
ctx.setServletContext(container);
Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
}
is this a new expected behavior?
import org.springframework.context jar correctly in your pom file , and thats it .
Hope that Helps .
Add spring context dependency :
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>