ArrayStoreException when updating a bundle - osgi

Using Apache Felix I'm getting an ArrayStoreException when updating a bundle. It occurs in a different bundle to the one updated. The affected bundle has a service listener which reacts to a new service being registered by the updated bundle. The listener performs some code which ends in the ArrayStoreException. Here's the stack trace:
ERROR: Bundle com.elsten.bliss.platform [47] EventDispatcher: Error during dispatch. (java.lang.ArrayStoreException: com.elsten.bliss.music.policy.tag.tagtype.TagTypePolicy)
java.lang.ArrayStoreException: com.elsten.bliss.music.policy.tag.tagtype.TagTypePolicy
at com.elsten.bliss.main.Main.getPolicies(Main.java:473)
at com.elsten.bliss.main.Main.<init>(Main.java:150)
at com.elsten.bliss.main.Main.startup(Main.java:143)
at com.elsten.bliss.main.Activator$VersionServiceTracker.addingService(Activator.java:58)
at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:980)
at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:906)
at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:262)
at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:234)
at org.osgi.util.tracker.ServiceTracker$Tracked.serviceChanged(ServiceTracker.java:941)
at org.apache.felix.framework.util.EventDispatcher.invokeServiceListenerCallback(EventDispatcher.java:932)
at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:793)
at org.apache.felix.framework.util.EventDispatcher.fireServiceEvent(EventDispatcher.java:543)
at org.apache.felix.framework.Felix.fireServiceEvent(Felix.java:4260)
at org.apache.felix.framework.Felix.registerService(Felix.java:3275)
at org.apache.felix.framework.BundleContextImpl.registerService(BundleContextImpl.java:346)
at org.apache.felix.framework.BundleContextImpl.registerService(BundleContextImpl.java:352)
at com.elsten.osgi.Activator.start(Activator.java:28)
at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:641)
at org.apache.felix.framework.Felix.activateBundle(Felix.java:1977)
at org.apache.felix.framework.Felix.startBundle(Felix.java:1895)
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:944)
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:931)
at org.apache.felix.bundlerepository.impl.ResolverImpl.deploy(ResolverImpl.java:647)
at com.elsten.bliss.updater.OnlineUpdater$2.run(OnlineUpdater.java:100)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:679)
The code in getPolicies (which is a static method) accessess a static final variable:
private static final MusicPolicy tagTypePolicy = new TagTypePolicy();
private static MusicPolicy[] policies;
private static MusicPolicy[] getPolicies(Version version) {
if(policies==null) {
final HttpClientConfiguration httpClientConfig = HttpClientConfigurations.userAgentAndAcceptGzip(version);
policies = new MusicPolicy[] {
tagTypePolicy
};
}
return policies;
}
My guess is that this is related to classloading; the MusicPolicy or TagTypePolicy classes do not match after the update. I'm a little confused why this would be the case; given these are private static variables I though my code could do what it liked. It's only when the statics are exported to other bundles, I thought, that trouble could happen.

Related

Equalsverifier fails when run with quarkus:dev

When running equalsverfier in quarkus dev mode, equalsverfier tests fail.
I tried to test a class with equalsverifier. This works in my IDE.
I tried to use it in quarkus dev mode (by running ./mvnw quarkus:dev), but then it fails with the following exception:
ERROR [io.qua.test] (Test runner thread) Test DingetjeTest#implementsEquals() failed
: java.lang.AssertionError: EqualsVerifier found a problem in class a.Dingetje.
-> Can not set final java.lang.String field a.Dingetje.text to a.Dingetje
For more information, go to: http://www.jqno.nl/equalsverifier/errormessages
at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verify(SingleTypeEqualsVerifierApi.java:308)
at a.DingetjeTest.implementsEquals(DingetjeTest.java:11)
Caused by: java.lang.IllegalArgumentException: Can not set final java.lang.String field a.Dingetje.text to a.Dingetje
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at java.base/jdk.internal.reflect.UnsafeQualifiedObjectFieldAccessorImpl.get(UnsafeQualifiedObjectFieldAccessorImpl.java:38)
at java.base/java.lang.reflect.Field.get(Field.java:418)
at nl.jqno.equalsverifier.internal.reflection.FieldModifier.lambda$copyTo$1(FieldModifier.java:79)
at nl.jqno.equalsverifier.internal.reflection.FieldModifier.lambda$change$3(FieldModifier.java:113)
at nl.jqno.equalsverifier.internal.util.Rethrow.lambda$rethrow$0(Rethrow.java:47)
at nl.jqno.equalsverifier.internal.util.Rethrow.rethrow(Rethrow.java:30)
at nl.jqno.equalsverifier.internal.util.Rethrow.rethrow(Rethrow.java:45)
at nl.jqno.equalsverifier.internal.util.Rethrow.rethrow(Rethrow.java:55)
at nl.jqno.equalsverifier.internal.reflection.FieldModifier.change(FieldModifier.java:113)
at nl.jqno.equalsverifier.internal.reflection.FieldModifier.copyTo(FieldModifier.java:79)
at nl.jqno.equalsverifier.internal.reflection.InPlaceObjectAccessor.copyInto(InPlaceObjectAccessor.java:43)
at nl.jqno.equalsverifier.internal.reflection.InPlaceObjectAccessor.copy(InPlaceObjectAccessor.java:24)
at nl.jqno.equalsverifier.internal.checkers.ExamplesChecker.checkSingle(ExamplesChecker.java:84)
at nl.jqno.equalsverifier.internal.checkers.ExamplesChecker.check(ExamplesChecker.java:47)
at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verifyWithExamples(SingleTypeEqualsVerifierApi.java:413)
at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.performVerification(SingleTypeEqualsVerifierApi.java:369)
at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verify(SingleTypeEqualsVerifierApi.java:304)
... 1 more
Here's the class under test:
package a;
import java.util.Objects;
public class Dingetje {
private final String text;
public Dingetje(String text) {
this.text = text;
}
#Override
public final boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Dingetje)) {
return false;
}
Dingetje other = (Dingetje) o;
return text.equals(other.text);
}
#Override
public final int hashCode() {
return Objects.hash(text);
}
}
And the test:
package a;
import nl.jqno.equalsverifier.EqualsVerifier;
import org.junit.jupiter.api.Test;
class DingetjeTest {
#Test
void implementsEquals() {
EqualsVerifier.forClass(Dingetje.class)
.withNonnullFields("text")
.verify();
}
}
What am I missing here?
EqualsVerifier uses Objenesis to create instances of classes, and it keeps the same reference of the objenesis object around for performance reasons. It caches all the objects it has created before, so that makes things quicker when you want to create the same object over and over again, which EqualsVerifier tends to do.
However, EqualsVerifier keeps a static reference to objenesis, which means that it lives as long as the JVM does. It turns out that the Quarkus test runner can re-run the same tests again and again, and it creates a new class loader each time. But part of the equality of java.lang.Class is that the classloader that created the class, must also be the same. So it couldn't retrieve these objects from its cache anymore and returnd instances with classloaders that are now different from the other objects created in the test, and this caused the exceptions that you saw.
In version 3.8 of EqualsVerifier (created as a result of this StackOverflow post), this issue can be avoided by adding #withResetCaches() like this:
EqualsVerifier.forClass(Dingetje.class)
.withResetCaches()
.withNonnullFields("text")
.verify();
That fixes the problem.

Hazelcast ClassNotFound using Near Cache in Client

I try to use Hazelcast (3.9.2, 3.11 no difference) in the following way:
I got Hazelcast servers (members). I run them dedicated, not embedded.
I do not want to teach the Hazelcast members the classes I want to store within them. I used the bundled hazelcast.xml file and did the following addon (3.9.2)
<replicatedmap name="default">
<in-memory-format>BINARY</in-memory-format>
<statistics-enabled>true</statistics-enabled>
</replicatedmap>
I also activated TCP, not Multicast (true/false)
That is all changes I did. I started with one Member listening to 127.0.0.1:5701
Then I try to attach Hazelcast clients to the member for storing and retrieving Maps (Primarily ReplicatedMaps, but Maps also do not work in my scenario)
My Client Code looks like this (Cache is just a Serializable Class with no attributes):
public class Main {
public static final String HAZELCAST_INSTANCE_NAME = "HAZI";
public static final String REPLICATEDMAP_NAME = "REP_MAP";
public static final String MAP_NAME = "NORMAL_MAP";
public static void main(String[] args) {
init();
HazelcastInstance instance = HazelcastClient.getHazelcastClientByName(HAZELCAST_INSTANCE_NAME);
Map<String, Object> repMap = instance.getReplicatedMap(REPLICATEDMAP_NAME);
repMap.put("MyKey", new Cache());
System.err.println("Retrieve " + repMap.get("MyKey"));
Map<String, Object> normalMap = instance.getReplicatedMap(MAP_NAME);
normalMap.put("MyKey", new Cache());
System.err.println("Retrieve " + normalMap.get("MyKey"));
System.exit(1);
}
private static void init() {
ClientConfig cfg = new ClientConfig();
cfg.setInstanceName(HAZELCAST_INSTANCE_NAME);
cfg.addNearCacheConfig(defineNearCache(REPLICATEDMAP_NAME));
cfg.addNearCacheConfig(defineNearCache(MAP_NAME));
// for analysis in the hazelcast management console
cfg.getProperties().put("hazelcast.client.statistics.enabled", "true");
cfg.getProperties().put("hazelcast.client.statistics.period.seconds", "60");
cfg.getNetworkConfig().addAddress("127.0.0.1:5701");
if (HazelcastClient.newHazelcastClient(cfg) == null) {
System.err.println(" !!! ERROR in Cache Config !!!");
}
}
private static NearCacheConfig defineNearCache(String mapName) {
EvictionConfig evictionConfig = new EvictionConfig()
.setMaximumSizePolicy(EvictionConfig.MaxSizePolicy.ENTRY_COUNT)
.setSize(200);
return new NearCacheConfig()
.setName(mapName)
.setInMemoryFormat(InMemoryFormat.BINARY)
.setInvalidateOnChange(true)
.setEvictionConfig(evictionConfig);
}
}
My problem now is:
Using this code I get a ClassNotFoundError trying put put things to the replicated map or regular map, but in the dedicated Hazelcast server (member), not on the client side.
SCHWERWIEGEND: [127.0.0.1]:5701 [dev] [3.9.2] hz._hzInstance_1_dev.event-3 caught an exception while processing task:com.hazelcast.spi.impl.eventservice.impl.LocalEventDispatcher#eeed098
com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassNotFoundException: de.empic.hazelwar.model.Cache
at com.hazelcast.internal.serialization.impl.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:224)
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:48)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:185)
at com.hazelcast.map.impl.DataAwareEntryEvent.getValue(DataAwareEntryEvent.java:90)
at com.hazelcast.client.impl.protocol.task.replicatedmap.AbstractReplicatedMapAddEntryListenerMessageTask.handleEvent(AbstractReplicatedMapAddEntryListenerMessageTask.java:92)
at com.hazelcast.client.impl.protocol.task.replicatedmap.AbstractReplicatedMapAddEntryListenerMessageTask.entryAdded(AbstractReplicatedMapAddEntryListenerMessageTask.java:132)
at com.hazelcast.replicatedmap.impl.ReplicatedMapEventPublishingService.dispatchEvent(ReplicatedMapEventPublishingService.java:82)
at com.hazelcast.replicatedmap.impl.ReplicatedMapService.dispatchEvent(ReplicatedMapService.java:247)
at com.hazelcast.spi.impl.eventservice.impl.LocalEventDispatcher.run(LocalEventDispatcher.java:64)
at com.hazelcast.util.executor.StripedExecutor$Worker.process(StripedExecutor.java:225)
at com.hazelcast.util.executor.StripedExecutor$Worker.run(StripedExecutor.java:208)
Caused by: java.lang.ClassNotFoundException: de.empic.hazelwar.model.Cache
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at com.hazelcast.nio.ClassLoaderUtil.tryLoadClass(ClassLoaderUtil.java:173)
at com.hazelcast.nio.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:147)
at com.hazelcast.nio.IOUtil$ClassLoaderAwareObjectInputStream.resolveClass(IOUtil.java:591)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1868)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at com.hazelcast.internal.serialization.impl.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:219)
... 10 more
Whenever I remove the near cache config from the client config, all works pretty perfect, except I do not have a near cache of course.
What do I miss here ?
#magicroomy, I run the same on both 3.9.2 & 3.11. I can confirm that:
If you change Replicated Map to Map, it works with or without Near Cache.
When using Replicated Map, if Near Cache defined, the exception thrown on the server side.
Without Near Cache, ReplicatedMap also works.
I created a github issue as well: https://github.com/hazelcast/hazelcast/issues/14210
My problem is solved using the 3.11.1 version of hazelcast.

Refresh Package Bundles

I've stumbled upon a problem, that can be summarized as follows:
I have an application which is embedded with OSGI. In this OSGI container, I have installed a bundle A of version v1 which registers that service object. This service object is used by the host application. while the service object is in use, I uninstalled the bundle A and installed a new version(v2) of the bundle A. Here are my findings.
Old service object works fine even if we uninstall the bundle A(v1).
The new service object gives the new functionality of bundle A(v2).
My question here is when we refresh the bundle packages by using
List<Bundle> refreshbundles = new ArrayList<Bundle>();
Bundle local; // points to the bundle
refreshbundles.add(local);
m_felix.adapt(FrameworkWiring.class).refreshBundles(refreshbundles)
and when we try to get the service object registered by the new version of the bundle A, it is returning null. I tried looking at the source code but it didn't help. can you please help me with this?
EDIT:
HostApplication
public Felix m_felix = null;
m_felix = new Felix(config); //sending some config to felix.
m_felix.start();
//installing bundle
Bundle bundle = m_felix.getBundleContext().installBundle("file:/bundleA-1.0.jar")
bundle.start()
//getting the service object registered by bundle A.
ServiceReference sr = m_felix.getBundleContext()
.getServiceReference(SampleInterface.class.getName()))
(SampleInterface) m_felix.getBundleContext(sr).getService().sayHI();
//now uninstalling the bundle installing the new version of it say version 1.1
bundle.uninstall()
bundle = m_felix.getBundleContext().installBundle("file:/bundleA-1.1.jar")
bundle.start()
//getting the service object registered by bundleA1.1
ServiceReference sr = m_felix.getBundleContext()
.getServiceReference(SampleInterface.class.getName()))
(SampleInterface) m_felix.getBundleContext(sr).getService().sayHI();
//the above line is working fine but after refreshing the packages, Service object is returned as null
List<Bundle> refreshbundles = new ArrayList<Bundle>();
Bundle bundle; // points to the bundle
refreshbundles.add(bundle);
m_felix.adapt(FrameworkWiring.class).refreshBundles(refreshbundles)
//refresh done
ServiceReference sr = m_felix.getBundleContext()
.getServiceReference(SampleInterface.class.getName()))
(SampleInterface) m_felix.getBundleContext(sr).getService().sayHI();
//throwing null pointer exception because getService() is returning null.
what exactly is happening when we refresh the bundles?
BundleA_Activator.java
public class BundleA_Activator extends BundleActivator{
public class BundleActivatorInterfaces implements BundleActivator{
ServiceRegistration SR;
#Override
public void start(BundleContext bundleContext) {
SR = bundleContext.registerService(SampleInterface.class.getName(), new ExposedClass(), null);
}
#Override
public void stop(BundleContext bundleContext) {
SR.unregister();
}
}

Karaf PaxExam getting java.lang.IllegalStateException: Invalid BundleContext

Hi i am loading some features and bundles in runtime using FeaturesService and BundleContext. All these things are loaded successfully. After that if i do an operation on bundlecontext object i am getting
java.lang.IllegalStateException: Invalid BundleContext.
#Inject
FeaturesService service;
#Before
public void init() throws Exception{
service.installFeature("hibernate");
service.installFeature("hibernate-validator");
service.installFeature("transaction");
service.installFeature("jpa");
service.installFeature("hibernate-envers");
service.installFeature("hibernate-envers");
bc.installBundle("wrap:mvn:com.oracle/ojdbc6/11.2.0").start();
service.installFeature("DBHandler");
bc.getBundle(); // Fails
}
After a lot of browsing i understood you need to refresh the bundles. How to do it programatically and get a refeshed bundleContext object
You have this exception when you are using a bundle which is not valid : it has been stopped, or refreshed (a refresh stop the bundle and start a new instance)
When you install a feature, by default, Karaf try to define a list of bundles to refresh because of the new capabilities. For example, if a bundle have an optional dependency on a package, and the new feature add this package, then this bundle will be refreshed, in order to update his wires. This is transitive : all dependent bundles are refreshed too.
Moreover, when you use the "wrap" protocol, it create a bundle from a jar by importing all used packaged with a resolution 'optional'
In your case, I suppose the feature 'DBHandler' add a package which is used by your bundle.
You can :
After installing the features, look up your bundle by SymbolicName, with the BundleContext.getBundles() : You will have an instance of a valid bundle
Use the option NoAutoRefreshBundles to disable the refresh when installing a feature (featureService.installFeature("..", EnumSet.of(FeatureService.NoAutoRefreshBundles))). But it's not a good idea as some bundle will not see the new package
This code fixed my problem
public void refreshBundles() {
Bundle currentBundle = FrameworkUtil.getBundle(MyTest.class);
if (currentBundle == null) {
return;
}
BundleContext bundleContext = currentBundle.getBundleContext();
if (bundleContext == null) {
return;
}
Bundle systemBundle = bundleContext.getBundle(0);
if (systemBundle == null) {
return;
}
FrameworkWiring frameworkWiring = systemBundle.adapt(FrameworkWiring.class);
frameworkWiring.refreshBundles(null);
bc = frameworkWiring.getBundle().getBundleContext();
}

GWT violation check on server side throws SerializationException

I followed the gwt 2.4 validation sample and implemented the whole stuff into my own App. The client side works great.
private void verifyRegistrationData(final RegistrationTO registration) throws ConstraintViolationException {
final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
final Set<ConstraintViolation<RegistrationTO>> violations = validator.validate(registration);
if (violations.size() > 0) {
final Set<ConstraintViolation<?>> temp = new HashSet<ConstraintViolation<?>>(violations);
throw new ConstraintViolationException(temp);
...
but if I do the same on the server side:
public void update(final RegistrationTO registration) throws IllegalArgumentException, ConstraintViolationException, TestException {
final Set<ConstraintViolation<RegistrationTO>> violations = validator.validate(registration);
if (!violations.isEmpty()) {
final Set<ConstraintViolation<?>> temp = new HashSet<ConstraintViolation<?>>(violations);
throw new ConstraintViolationException(temp);
}
...
the whole thing crashes with the following exception:
javax.servlet.ServletContext log: Exception while dispatching incoming RPC call
com.google.gwt.user.client.rpc.SerializationException: Type 'org.hibernate.validator.engine.PathImpl' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.
That's how PathImpl looks like hibernate-validator-4.1.0.Final-sources.jar
public class PathImpl implements Path, Serializable {
private static final long serialVersionUID = 7564511574909882392L;
...
looks OK (at least to me)
I am using GWT 2.4, validation-api-1.0.0.GA, hibernate-validator-4.1.0.Final, gwt-servlet-deps ...
Thanks in advance!
Is there an explicitly defined a default constructor? i.e.,
public PathImpl() { } ? This is required by GWT's serialization mechanism; if it isn't in the source, serializing an RPC response will fail.
A custom serializer does exist for PathImpl, it's just that unless that class is explicitly referenced in your service API, it's not going to be added to the serialization policy.
The current work around is to add a dummy PathImpl field somewhere in your service API. The ValidationSupport class exists to group this and other such classes together to make this a bit easier.
I change the whole thing to RequestFactory as Thomas Broyer recommended. It was by far not so easy as GWT-RPC. This was the reason for me to collect all kind of informations and to build a sample program. For those who are interested - here you can find a sample with documentation and source. (Single line client logger is also implemented) (Documentation is in German but logging-output aso. is in English...)

Resources