ClassCastException Error while using SupportsContextSwitching with ThreadLoacal - java

After upgrading to
<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>8.3.0</version>
</dependency>
I had to update code as shown below.
public class AppDriver extends TestListener_Error {
private static final ThreadLocal<AppiumDriver> driverThread = new ThreadLocal<>();
private static final Logger log = LogManager.getLogger();
public static String getCurrentContext() {
log.info("Entering");
return ((SupportsContextSwitching) driverThread).getContext();
}
public static Set getAllContexts() {
log.info("Entering");
return ((SupportsContextSwitching) driverThread).getContextHandles();
}
}
The following error is generated when getCurrentContext() is called. The error occurs for iOS only. When the same code is executed on an Android device, the ClassCastException error is not thrown. What could be the reason? How do I resolve this issue?
java.lang.ClassCastException: class java.lang.ThreadLocal cannot be
cast to class io.appium.java_client.remote.SupportsContextSwitching
(java.lang.ThreadLocal is in module java.base of loader 'bootstrap';
io.appium.java_client.remote.SupportsContextSwitching is in unnamed
module of loader 'app')

Related

Bytebuddy: How to inject class that can be read by java.net.http.HttpClient#sendAsync

I'm trying to time time it takes for the CompletableFuture that is being returned by java.net.http.HttpClient#sendAsync
// premain
public static void premain(String arguments, Instrumentation instrumentation) {
// ...inject helper class to bootloader
new AgentBuilder.Default()
.ignore(ElementMatchers.none())
.with(Listener.StreamWriting.toSystemOut().withErrorsOnly())
.type(hasSuperType(named("java.net.http.HttpClient")))
.transform((builder, typeDescription, classLoader,
module, protectionDomain) -> {
return builder
.visit(Advice.to(SendAsyncAdvice.class)
.on(hasMethodName("async")));
})
.asTerminalTransformation()
.installOn(instrumentation);
}
class SendAsyncAdvice {
#Advice.OnMethodExit()
public static void exit(
#Advice.Return(readOnly = false) CompletableFuture<HttpResponse<?>> future) {
future = future.whenComplete(new ResponseConsumer());
}
}
class ReponseConsumer implements BiConsumer<HttpResponse<?>, Throwable> {
#Override
public void accept(HttpResponse<?> arg0, Throwable arg1) {
System.out.println("HELLO");
}
}
I injected the ReponseConsumer to the bootloader and I'm getting this error
Exception in thread "main" java.lang.IllegalAccessError:
failed to access class io.hello.agent.SendAsyncAdvice
from class jdk.internal.net.http.HttpClientImpl
(io.hello.agent.SendAsyncAdvice is in unnamed module of loader
'bootstrap'; jdk.internal.net.http.HttpClientImpl
is in module java.net.http of loader 'platform')
Just wondering how do i make the ReponseConsumer class available in java.net.http module
You are hitting the module system's boundaries and you have to add a read edge from your http client's module to the injected class. You can do so by adding a step in your code: assureReadEdgeTo where you reference the target class or module.

Arquillian: Getting WFLYEE0117: Field field cannot be set, on Singleton.START

I am trying to run an arquillian test, the test use a bean mapped with #Singleton and #Startup annotations, inside the singleton there are some cache Types from infinispan that are injected using #Resource(lookup = "JNDI"), the error only tells of the filds can't be set
I am sure that I missing something in my Test class, This is the code from the class and the bean.
#RunWith(Arquillian.class)
public class EJBsBeanTest {
private static SimpleDateFormat SDF_YYYYMMDD = new SimpleDateFormat("yyyy-MM-dd");
private Libreta lib;
private Documento documento;
private Documento documentoAdmin;
private Documento documentoRol;
#Deployment
public static Archive<?> createTestArchive() {
File[] files = Maven.resolver().loadPomFromFile("pom.xml")
.importRuntimeDependencies().resolve().withTransitivity().asFile();
WebArchive myArchive = ShrinkWrap.create(WebArchive.class, "test.war")
.addClasses(ConfigurationBean.class,... )
.addAsLibraries(files)
.addAsWebInfResource("jboss-deployment-structure.xml", ArchivePaths.create("jboss-deployment-structure.xml"))
.addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("META-INF/beans.xml"));
return myArchive;
}
}
............
#Startup
#Singleton
public class ConfigurationBean {
private static final Logger logger = Logger.getLogger(ConfigurationBean.class.getName());
private static Properties props;
private static IOException ioerror;
public static final String CACHE_RUA_CEIP = "evaluacionRuaCeip";
#Resource(lookup = "java:jboss/datagrid-infinispan/container/backend-manager/cache/externos-cache")
private Cache<String, Object> cacheExternos;
#Resource(lookup = "java:jboss/datagrid-infinispan/container/shiro-container")
private CacheContainer basicCacheContainer;
#Resource(lookup = "java:jboss/datagrid-infinispan/container/backend-manager/cache/permisosapp-cache")
private Cache<String, Object> cachePermisosApp;
#PostConstruct
public void init() {
try {
props = new Properties();
props.load(ConfigurationBean.class.getClassLoader().getResourceAsStream("ftp.properties"));
cachePermisosApp.clear();
cacheExternos.clear();
} catch (Exception ex) {
logger.log(Level.SEVERE, null, ex);
throw new RuntimeException(ex);
}
}
public Cache<String, Object> getCacheExternos() {
return cacheExternos;
}
public Properties getProps() {
return props;
}
public CacheContainer getBasicCacheContainer() {
return basicCacheContainer;
}
public Cache<String, Object> getCachePermisosApp() {
return cachePermisosApp;
}
}
And this is the error:
org.jboss.arquillian.container.spi.client.container.DeploymentException:
Cannot deploy test.war: {"WFLYCTL0062: Composite operation failed and was rolled back. Steps that failed:" => {"Operation step-1" => {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"test.war\".component.ConfigurationBean.START" => "java.lang.IllegalStateException: WFLYEE0042: Failed to construct component instance
Caused by: java.lang.IllegalStateException: WFLYEE0042: Failed to construct component instance
Caused by: javax.ejb.EJBException: java.lang.IllegalArgumentException: WFLYEE0117: Field cacheExternos cannot be set - object of class org.infinispan.cache.impl.EncoderCache loaded by ModuleClassLoader for Module \"org.infinispan.core:ispn-9.4\" version 9.4.3.Final from local module loader #7776ab (finder: local module finder #79179359 (roots: /jboss/modules,/jboss/modules/system/layers/base,/jboss/modules/system/add-ons/ispn)) is not assignable to interface org.infinispan.Cache loaded by ModuleClassLoader for Module \"deployment.test.war\" from Service Module Loader
Caused by: java.lang.IllegalArgumentException: WFLYEE0117: Field cacheExternos cannot be set - object of class org.infinispan.cache.impl.EncoderCache loaded by ModuleClassLoader for Module \"org.infinispan.core:ispn-9.4\" version 9.4.3.Final from local module loader #7776ab (finder: local module finder #79179359 (roots: /jboss/modules,/jboss/modules/system/layers/base,/jboss/modules/system/add-ons/ispn)) is not assignable to interface org.infinispan.Cache loaded by ModuleClassLoader for Module \"deployment.test.war\" from Service Module Loader"}}}}
Finally I found an answer, the application wasn't find the module org.infinispan.core:ispn-9.4 in the generated .war so I add the module to the jboss-deployment-structure.xml file to have access to the module.
Here is the src/test/resources/jboss-deployment-structure.xml
<jboss-deployment-structure>
<ear-subdeployments-isolated>false</ear-subdeployments-isolated>
<deployment>
<dependencies>
<module name="org.infinispan.core" slot="ispn-9.4"/>
</dependencies>
</deployment>
</jboss-deployment-structure>

Guice Constructor Injection withOUT Annotations?

Can someone help with an implementation of Guice withOUT annotations?
public interface IAnimal {
void makeNoise();
}
public interface IVehicle {
int getWheelCount();
}
import org.apache.commons.logging.Log;
public class Car implements IVehicle {
private Log Logger;
public Car(Log lgr) {
this.Logger = lgr;
}
public final int getWheelCount() {
this.Logger.info("getWheelCount is returning 4");
return 4;
}
}
import org.apache.commons.logging.Log;
public class Dog implements IAnimal {
private Log Logger;
public Dog(Log lgr) {
this.Logger = lgr;
}
public final void makeNoise() {
this.Logger.info("Bark Bark Bark");
}
}
pom.xml
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.2.0</version>
</dependency>
What I've tried:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.google.inject.*;
public class App {
public static void main(String[] args) {
Log localLogger =
LogFactory.getLog(App.class);
Injector injector = Guice.createInjector();
IVehicle veh = injector.getInstance(Car.class);
int wc = veh.getWheelCount();
IAnimal amh = injector.getInstance(Dog.class);
amh.makeNoise();
}
}
The error I'm getting is:
Classes must have either one (and only one) constructor annotated with #Inject or a zero-argument constructor that is not private.
I understand the error.
But I'm hoping I can "point" Guice to the correct constructor......instead of using the annotation.
As you can see, using a default/empty constructor is not a good option, as this example is simple, but I want to stick with constructor based inject.
APPEND:
Based on the "hint" I got from Hemant Singh in the comments, I think I got closer.
I created a ProductionInjectModule, that uses
bind(MyInterface.class).toConstructor(MyConcrete.class.getConstructor(org.apache.commons.logging.Log.class));
But even though I am "forcing" the issue by pointing to a specific constructor (using "toConstructor").......I'm still getting:
Classes must have either one (and only one) constructor annotated with
#Inject or a zero-argument constructor that is not private.
Gaaaaaaaaaaaaaaaaaaaaa!
Full "module" code below:
public class App {
public static void main(String[] args) {
runGuice();
}
private static void runGuice() {
Log localLogger = LogFactory.getLog(App.class);
ProductionInjectModule pm = new ProductionInjectModule(localLogger);
Injector injector = Guice.createInjector(pm);
////Injector injector = Guice.createInjector();
//// injector.injectMembers(localLogger);
IVehicle veh = injector.getInstance(Car.class);
int wc = veh.getWheelCount();
IAnimal amh = injector.getInstance(Dog.class);
amh.makeNoise();
}
}
import com.google.inject.AbstractModule;
import com.google.inject.Module;
public class ProductionInjectModule extends AbstractModule implements Module {
// public void configure(Binder binder) {
// binder.bind(IVehicle.class).to(Car.class);
//// binder.bind(InterfaceB.class).to(ConcreteB.class);
//// binder.bind(InterfaceC.class).to(ConcreteC.class);
// }
private final org.apache.commons.logging.Log Logger;
public ProductionInjectModule(org.apache.commons.logging.Log concreteLogger) {
this.Logger = concreteLogger;
}
#Override
protected void configure() {
try {
bind(org.apache.commons.logging.Log.class).toInstance(this.Logger);
bind(IVehicle.class).toConstructor(Car.class.getConstructor(org.apache.commons.logging.Log.class));
bind(IAnimal.class).toConstructor(Dog.class.getConstructor(org.apache.commons.logging.Log.class));
} catch (NoSuchMethodException e) {
addError(e);
}
}
}
And following the same hint, I found some documentation to support:
from : http://www.baeldung.com/guice
You can also inject a dependency that doesn’t have a default no-arg
constructor using constructor binding:
> public class BasicModule extends AbstractModule {
>
> #Override
> protected void configure() {
> bind(Boolean.class).toInstance(true);
> bind(Communication.class).toConstructor(
> Communication.class.getConstructor(Boolean.TYPE)); }
The snippet above will inject an instance of Communication using the
constructor that takes a boolean argument. We supply the true argument
to the constructor by defining an untargeted binding of the Boolean
class.
This untargeted binding will be eagerly supplied to any constructor in
the binding that accepts a boolean parameter. With this approach, all
dependencies of Communication are injected.
Another approach to constructor-specific binding is the instance
binding, where we provide an instance directly in the binding:
> public class BasicModule extends AbstractModule {
>
> #Override
> protected void configure() {
> bind(Communication.class)
> .toInstance(new Communication(true));
> } }
Summer 2019 APPEND:
It would be wiser to use "slf4j" instead of "org.apache.commons"
org.slf4j.Logger
and
org.slf4j.LoggerFactory.getLogger(MyClass.class);
and
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
Why?
https://www.slf4j.org/codes.html#multiple_bindings
Embedded components such as libraries or frameworks should not declare
a dependency on any SLF4J binding but only depend on slf4j-api. When a
library declares a compile-time dependency on a SLF4J binding, it
imposes that binding on the end-user, thus negating SLF4J's purpose.
When you come across an embedded component declaring a compile-time
dependency on any SLF4J binding, please take the time to contact the
authors of said component/library and kindly ask them to mend their
ways.
I got it! My "APPEND:" area in the original question was close! But now I see my small mistake.
My ProductionInjectModule above was correct.
My "ask to resolve" was wrong.
Notice in my getInstance, I still had the concrete.
I needed to have this: (emphasis on the argument of the getInstance)
IVehicle veh = injector.getInstance(IVehicle.class);
int wc = veh.getWheelCount();
IAnimal amh = injector.getInstance(IAnimal.class);
amh.makeNoise();
Full working code: (with the interfaces and concretes from above)
public class App {
public static void main(String[] args) {
runGuice();
}
private static void runGuice() {
Log localLogger = LogFactory.getLog(App.class);
ProductionInjectModule pm = new ProductionInjectModule(localLogger);
Injector injector = Guice.createInjector(pm);
IVehicle veh = injector.getInstance(IVehicle.class);
int wc = veh.getWheelCount();
IAnimal amh = injector.getInstance(IAnimal.class);
amh.makeNoise();
}
}
import com.google.inject.AbstractModule;
import com.google.inject.Module;
public class ProductionInjectModule extends AbstractModule implements Module {
private final org.apache.commons.logging.Log Logger;
public ProductionInjectModule(org.apache.commons.logging.Log concreteLogger) {
this.Logger = concreteLogger;
}
#Override
protected void configure() {
try {
bind(org.apache.commons.logging.Log.class).toInstance(this.Logger);
bind(IVehicle.class).toConstructor(Car.class.getConstructor(org.apache.commons.logging.Log.class));
bind(IAnimal.class).toConstructor(Dog.class.getConstructor(org.apache.commons.logging.Log.class));
} catch (NoSuchMethodException e) {
addError(e);
}
}
}
Summer 2019 APPEND:
It would be wiser to use "slf4j" instead of "org.apache.commons"
org.slf4j.Logger
and
org.slf4j.LoggerFactory.getLogger(MyClass.class);
and
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
Of course, check for more recent update:
https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.slf4j%22%20AND%20a%3A%22slf4j-api%22
Why?
https://www.slf4j.org/codes.html#multiple_bindings
Embedded components such as libraries or frameworks should not declare
a dependency on any SLF4J binding but only depend on slf4j-api. When a
library declares a compile-time dependency on a SLF4J binding, it
imposes that binding on the end-user, thus negating SLF4J's purpose.
When you come across an embedded component declaring a compile-time
dependency on any SLF4J binding, please take the time to contact the
authors of said component/library and kindly ask them to mend their
ways.

java.lang.ClassCastException: android.app.Application cannot be cast to com.google.android.apps.common.inject.InjectedApplication

I'm trying t use Robolectric
#RunWith(RobolectricTestRunner.class)
#Config(
manifest = "...mypath.../AndroidManifest.xml",
qualifiers = "fr-normal-port-hdpi",
sdk = 21,
application = Application.class)
public class SetPaymentActivityTest {
#Before
public void setUp() throws Exception {
}
#Test
public void sendWrongPaymentDetails() throws Exception {
SetPaymentActivity activity = Robolectric.buildActivity(SetPaymentActivity.class)
// .attach()
.create()
// .starst()
// .resume()
// .visible()
.get();
activity = Robolectric.setupActivity(SetPaymentActivity.class);
// Shadows.shadowOf(SetPaymentActivity.class);
String url = activity.getUrl();
assertThat(url, equalTo(""));
}
}
PROD code:
public class SetPaymentActivity extends FragmentActivity implements DaggerActivity {
but I get this error:
Time: 109.712
There was 1 failure:
1) sendWrongPaymentDetails(com.google.android.apps.ridematch.payments.SetPaymentActivityTest)
java.lang.ClassCastException: android.app.Application cannot be cast to com.google.android.apps.common.inject.InjectedApplication
at com.google.android.apps.common.inject.ActivityInjectHelper.initGraph(ActivityInjectHelper.java:56)
what am i doing wrong?
Maybe you need your SetPaymentActivityTestto extends InjectedApplication
like this:
public class SetPaymentActivityTest extends InjectedApplication {
It is easy to fix.
Change your test code to next:
#RunWith(RobolectricGradleTestRunner.class)
#Config(
constants = BuildConfig.class,
qualifiers = "fr-normal-port-hdpi",
sdk = 21)
The problem is that Robolectric trying to use Application as you specified in config and at some point you casting it to your class
I have created a dummy TestApplication class:
public TestApplication extends InjectedApplication
and configured:
#Config(
manifest = "...mypath.../AndroidManifest.xml",
qualifiers = "fr-normal-port-hdpi",
sdk = 21,
application = TestApplication.class)

java.lang.NoSuchFieldError: INSTANCE

When trying to submit my topology through StormSubmitter, I am getting -
Caused by: java.lang.NoSuchFieldError: INSTANCE
at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:52)
I am using Spring.
I am not initializing HttpClient in Spout/Bolt Constructor. Instead its initialized in constructor of a class that is being fetched from Spring Context in prepare() method of bolt
Code is structured as follows -
SomeBolt.java
#Component
public class SomeBolt extends BaseRichBolt {
private OutputCollector _collector;
private SomeClient someClient;
#Override
public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
_collector = collector;
someClient = AppContext.getBean(SomeClient.class);
}
}
SomeClient.java
#Component
public class SomeClient {
private final CloseableHttpClient httpClient;
public SomeClient() {
this.httpClient = (httpClient == null ? HttpClients.createDefault() : httpClient);
}
}
AppContext.java
#Component
public class AppContext implements ApplicationContextAware {
private static ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
AppContext.applicationContext = applicationContext;
}
public static <T> T getBean(Class<T> c) {
return applicationContext.getBean(c);
}
}
This is probably a dependency issue.
It's a very unclear error message but I found something similar here:
Hibernate NoSuchFieldError INSTANCE but only with Struts 1?
I faced similar issue like this, In my class path there was two jar contains same class, httpcore-4.3 and apache-httpcomponents-httpcore, I have removed apache-httpcomponents-httpcore from class path solved the issue.
Harsh is right its in the storm class path.
So what I did to make this work was remove the httpclient and httpcore that comes with storm and replaced them with newer version 4.3.3 and 4.3.2 respectively. This changes the classpath the works/nimbus/supervisor uses to start. You can run storm classpath and it print the class path out.
[nimbus ~]$ storm classpath
...../storm-0.8.2/lib/httpclient-4.3.3.jar:..../storm-0.8.2/lib/httpcore-4.3.2.jar.....
I am not sure this is a very good work around, I am not sure what part of storm uses this jar.
if you look at the python storm code you see that it will put all jars in the storm root and storm/lib
def get_classpath(extrajars):
ret = get_jars_full(STORM_DIR)
ret.extend(get_jars_full(STORM_DIR + "/lib"))
ret.extend(extrajars)
return normclasspath(":".join(ret))
I had the below jar files in the path inside the plugin folder:
./var/lib/jenkins/plugins/build-pipeline-plugin/WEB-INF/lib/httpcore-4.2.1.jar
./var/lib/jenkins/plugins/git-client/WEB-INF/lib/httpcore-4.3.2.jar
./var/lib/jenkins/plugins/maven-plugin/WEB-INF/lib/httpcore-4.2.4.jar
After, I removed the below file, it worked for me
/var/lib/jenkins/plugins/build-pipeline-plugin/WEB-INF/lib/httpcore-4.2.1.jar

Categories