"No such network" error when trying to re-use Testcontainers rules with network from abstract class - testcontainers

Suppose I have an abstract class called AbstractTestWithNetwork:
#RunWith(JUnit4.class)
public abstract class AbstractTestWithNetwork {
#ClassRule
public static Network network = Network.newNetwork();
#ClassRule
public static GenericContainer etcd = new GenericContainer<>("alpine:3.6")
.withNetwork(network);
}
I would like to simply re-use it to have the same container in several classes by extending it:
public class FirstTestClass extends AbstractTestWithNetwork {
#Test
public void emptyMethod() throws Exception {
System.out.println("An empty test method");
}
}
There is also a SecondTestClass with the same content.
I can run each class separately from IDE and they will pass. But when I run gradle test or choose the whole package with test classes from IDE, only the 1st test class passes. For the second I get:
org.testcontainers.containers.ContainerLaunchException: Container startup failed
Caused by:
org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
Caused by:
org.testcontainers.containers.ContainerLaunchException: Could not create/start container
Caused by:
java.lang.reflect.UndeclaredThrowableException
Caused by:
java.lang.reflect.InvocationTargetException
Caused by:com.github.dockerjava.api.exception.NotFoundException: {"message":"No such network: a48cf082ab42a55c843e9963c3938f44dd93cceae09e1724d4fefd5b45f235f1"}

I checked the implementation and spotted a bug in Networks' implementation.
In TestContainers <= 1.4.2, an instance of Network is not reusable, i.e. can't be used with #ClassRule.
But I have good news for you - there is a simple workaround until it's fixed: just remove #ClassRule from "network" field.

Related

Quarkus extension using a repository based on PanacheMongoRepository

I'm currently working on a Quarkus extension which is basically a filter that is using a PanacheMongoRepository. Here is a code snippet (this is in the runtime part of the extension) :
#Provider
#Priority(Priorities.AUTHORIZATION)
#AuthorizationSecured
public class AuthorizationFilter implements ContainerRequestFilter {
// Some injection here
#Inject
UserRepository userRepository;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Some business logic here...
UserEntity userEntity = userRepository.findByName(name);
// Some business logic here...
}
}
The repository :
#ApplicationScoped
public class UserRepository implements PanacheMongoRepository<UserEntity> {
public UserEntity findByName(String name) {
return find("some query...", name).firstResult();
}
}
When the repository is called, I get the following exception:
org.jboss.resteasy.spi.UnhandledException: java.lang.IllegalStateException: This method is normally automatically overridden in subclasses...
java.lang.IllegalStateException: This method is normally automatically overridden in subclasses\n\tat io.quarkus.mongodb.panache.common.runtime.MongoOperations.implementationInjectionMissing(MongoOperations.java:765)\n\tat io.quarkus.mongodb.panache.PanacheMongoRepositoryBase.find(PanacheMongoRepositoryBase.java:119)
The processor
class AuthorizeProcessor {
private static final String FEATURE = "authorize";
#BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(FEATURE);
}
#BuildStep(onlyIf = IsAuthorizeEnabled.class)
void registerAuthorizeFilter(
BuildProducer<AdditionalBeanBuildItem> additionalBeanProducer,
BuildProducer<ResteasyJaxrsProviderBuildItem> resteasyJaxrsProviderProducer
) {
additionalBeanProducer.produce(new AdditionalBeanBuildItem(UserRepository.class));
additionalBeanProducer.produce(new AdditionalBeanBuildItem(AuthorizationFilter.class));
resteasyJaxrsProviderProducer.produce(new ResteasyJaxrsProviderBuildItem(AuthorizationFilter.class.getName()));
}
}
Any idea ?
Thanks for your help :)
MongoDB with Panache (and the same for Hibernate with Panache) uses bytecode enhancement at build time. When this enhancement didn't occurs it leads to the exception you mentionned at runtime: java.lang.IllegalStateException: This method is normally automatically overridden in subclasses
It can occurs only when the repository or entity is not in the Jandex index. Jandex is used to index all the code of your application to avoid using reflection and classpath scanning to discover classes. If your entity / repository is not in the index this means it's not part of your application as we automatically index the classes of your application, so it must be inside an external JAR.
Usually, this is solved by adding the Jandex plugin to index the code of the external JAR (in fact there is multiple way to do this, see How to Generate a Jandex Index).
An extension suffer from the same issue as extensions are not indexed by default. But from an extension you can index the needed classes via a build step wich is more easy and avoid polluting the index with classes that are not needed.
This can be done by generating a new AdditionalIndexedClassesBuildItem(UserRepository.class.getName()) inside a build step.

SpringBoot scanBasePackages not working in multi module project

I have the following maven project structure:
eu.arrowhead
common
repository
-AJpaRepository.class
orchestrator
controller
-AController.class
OrchestratorApplication
other_modules...
Where two of the modules are common, and orchestrator. Common is a dependency for the Orchestrator module. The JpaRepositoryClass is annotated with #Repository.
In the controller class I use the constructor autowiring to get a copy of the repository:
private final AJpaRepository serviceRepo;
#Autowired
public AController(AJpaRepository serviceRepo){
this.serviceRepo = serviceRepo;
}
And finally, in the Application class, I use scanBasePackages, to pick up the components from the common module:
#SpringBootApplication(scanBasePackages = "eu.arrowhead")
public class OrchestratorApplication {
public static void main(String[] args) {
SpringApplication.run(OrchestratorApplication.class, args);
}
}
When I start the application, I get:
Description:
Parameter 0 of constructor in eu.arrowhead.orchestrator.controller.ArrowheadServiceController required a bean of type 'eu.arrowhead.common.repository.ArrowheadServiceRepo' that could not be found.
Action:
Consider defining a bean of type 'eu.arrowhead.common.repository.ArrowheadServiceRepo' in your configuration.
If I use scanBasePackages = {"eu.arrowhead.common"} then the application starts without an error, but I can not reach the endpoint in my controller class (getting the default 404 error). If I write scanBasePackages = {"eu.arrowhead.common", "eu.arrowhead.orchestrator"} it's the same as if only "eu.arrowhead" is there, I get the same error at startup.
Is this how this supposed to work? I highly doubt it.
Depencendies:
Common module: starter-data-jpa, starter-json, mysql-connector-java, hibernate-validator
Orch module: starter-web, the common module.
I also tried using #ComponentScan, but had the same result. What is the problem? Thanks.
You are missing #EnableJpaRepositories("eu.arrowhead") annotation to enable Spring Data JPA repository scanning.

Using Felix/Whiteboard to host a VaadinServlet

As the title states, I'm trying to use Whiteboard to host my VaadinServlet. After many failed attempts at using other embedded servlet containers such as Jetty and Grizzly, I came across this solution here, written by the Bndtools man himself, Peter. I've tried implementing this myself, but I'm getting an error I cannot solve myself:
[test.client.ui.ClientUI$ClientServlet(4)] Error during instantiation of the implementation object
java.lang.InstantiationException: test.client.ui.ClientUI$ClientServlet: test.client.ui.ClientUI$ClientServlet.<init>()
Caused by: org.apache.felix.log.LogException: java.lang.InstantiationException: test.client.ui.ClientUI$ClientServlet
at java.lang.Class.newInstance(Class.java:427)
at org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:253)
at org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:127)
at org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:871)
at org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:838)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:850)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:419)
at org.apache.felix.scr.impl.config.ConfigurableComponentHolder.enableComponents(ConfigurableComponentHolder.java:376)
at org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:172)
at org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:120)
at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:258)
at org.apache.felix.scr.impl.Activator.access$000(Activator.java:45)
at org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:185)
at org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:259)
at org.apache.felix.utils.extender.AbstractExtender.modifiedBundle(AbstractExtender.java:232)
... 17 more
Caused by: java.lang.NoSuchMethodException: test.client.ui.ClientUI$ClientServlet.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
at org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:253)
at org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:127)
at org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:871)
at org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:838)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:850)
at org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:419)
at org.apache.felix.scr.impl.config.ConfigurableComponentHolder.enableComponents(ConfigurableComponentHolder.java:376)
at org.apache.felix.scr.impl.BundleComponentActivator.initialize(BundleComponentActivator.java:172)
at org.apache.felix.scr.impl.BundleComponentActivator.<init>(BundleComponentActivator.java:120)
at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:258)
at org.apache.felix.scr.impl.Activator.access$000(Activator.java:45)
at org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:185)
at org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:259)
... 18 more
I added empty constructors just for the hell of it to see if they changed anything but nope.
ClientUI and ClientServlet classes:
public class ClientUI extends UI
{
public ClientUI()
{
//Empty constructor.
}
#Override
public void init(VaadinRequest request)
{
//Typical UI initialization.
}
}
#VaadinServletConfiguration(productionMode = false, ui = ClientUI.class)
#Component(provide = Servlet.class, properties = {"alias=/test"}, immediate = true)
public class ClientServlet extends VaadinServlet
{
// Empty class. This class uses the annotations for servlet configuration instead of a web.xml.
public ClientServlet()
{
// Empty constructor.
}
}
Any idea on how to stop this error and get the servlet up and running?
Edit: New error! Steffen, who commented below, pointed out I may have needed to move the servlet class to a top-level class, in which I most likely did need to, but now I get this:
org.osgi.framework.ServiceException: Service cannot be cast: javax.servlet.Servlet
Caused by: org.apache.felix.log.LogException: org.osgi.framework.ServiceException: Service cannot be cast: javax.servlet.Servlet
at org.apache.felix.framework.ServiceRegistrationImpl.getFactoryUnchecked(ServiceRegistrationImpl.java:344)
at org.apache.felix.framework.ServiceRegistrationImpl.getService(ServiceRegistrationImpl.java:231)
at org.apache.felix.framework.ServiceRegistry.getService(ServiceRegistry.java:327)
at org.apache.felix.framework.Felix.getService(Felix.java:3574)
at org.apache.felix.framework.BundleContextImpl.getService(BundleContextImpl.java:468)
at org.osgi.util.tracker.ServiceTracker.addingService(ServiceTracker.java:411)
at org.apache.felix.http.whiteboard.internal.tracker.AbstractTracker.addingService(AbstractTracker.java:35)
at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:932)
at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:864)
at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:256)
at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:229)
at org.osgi.util.tracker.ServiceTracker$Tracked.serviceChanged(ServiceTracker.java:894)
at org.apache.felix.framework.util.EventDispatcher.invokeServiceListenerCallback(EventDispatcher.java:943)
at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:794)
at org.apache.felix.framework.util.EventDispatcher.fireServiceEvent(EventDispatcher.java:544)
... 12 more
Also, this question may eventually be deleted. I'm looking at this Vaadin/OSGi EnRoute example that does what I need and I have confirmed that it works. I may just use the example provider and API for an application or create something similar. I will leave this question up for now just to provide to the knowledge of the internet and see if anyone can answer!

Using ViewAccessControl in Spring and Vaadin

I am currently trying to use the ViewAccessControl Interface of vaadin.spring as explained in the last paragraph of this tutorial.
But when implementing the isAccessGranted Method I get the following error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'frontPageView': Scope 'vaadin-view' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No active view
The declaration of the FrontPageView class (The only thing I do in the enter method, is to add some vaadin ui elements):
#SpringView(name = FrontPageView.NAME)
public class FrontPageView extends DashboardDesign implements View, ViewAccessControl {
#Override
public void enter(ViewChangeEvent event) {
}
}
And my implementation of the isAccessGranted Method:
#Override
public boolean isAccessGranted(UI ui, String beanName) {
return SecurityContextHolder.getContext().getAuthentication().isAuthenticated();
}
P.S. Its basically the same problem this guy had a year ago: How to create a secure view with Vaadin and SpringViewProvider
Ok I figured it out now. If anyone else ever finds this problem, the solution is to use the ViewInstanceAccessControl interface instead of the ViewAccessControl iterface. Everything works fine this way.

Launching application from one class and using it in another class(Help me in Learning Selenium)

Launching Application from One Class and using it in another class.
Hi All,
I am new to selenium and Java. I just trying to work on selenium. I am
facing some problem. I wanted to create a class in which I just want
to launch application(say google.com), and the next other tasks like
executing test cases has to be done by other class. Can this be done,
Here I am pasting my code. Help me please in understanding this.
Here are my two classes
This class Launches Google on browser.
public class GoogleTest extends SeleneseTestCase
{
private static Selenium selenium;
#BeforeClass
public static void setUpBeforeClass() throws Exception
{
selenium = new DefaultSelenium("localhost", 4444, "*firefox", "http://www.google.com");
selenium.start();
selenium.windowMaximize();
}
#Test
public void testSearch() throws InterruptedException
{
selenium.open("http://www.google.com");
selenium.waitForPageToLoad("50000");
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
selenium.stop();
}
}
This class should type in search field
public class FirstSeleniumTest extends GoogleTest
{ private static Selenium selenium;
#Test
public void testSearch()
{
selenium.type("q", "Selenium OpenQA");
selenium.waitForPageToLoad("50000");
}
}
When I run "GoogleTest" first class it runs perfectly, when I try to
run "FirstSeleniumTest" second class it gives error like this. FAILED:
testSearch on null(com.dev.rao.FirstSeleniumTest)
java.lang.NullPointerException at
com.dev.rao.FirstSeleniumTest.testSearch(FirstSeleniumTest.java:18)
Its normally difficult to do what you are trying to achieve. That's why new Selenium instance is better per test. and in the longer run easy to debug. But as per what you are trying I see two issues:
1.) selenium.stop() should be in the second script not the first. If you kill the instance how can it be extended in 2nd test.
2.) Declaring Selenium twice. (I think probably Selenium instance in 2nd test should also extend from first test.)

Resources