Magnolia - Instantiate fail with a module class - java

When I need starting a command with scheduler I have the next error in console:
I'm going to line 66 that log said me and i can see this:
This class WsProuser has a Null pointer Exception when i try get the instance. This class is a default class of module where i saved some configurations. This is a part of META-INF xml where i reference this class:
And this is the implementation of this class:
For finish, this is the config where i save the values that i need in the command:
¿Why i have this NullPointer Exception when magnolia should instanciate automating this class?

I don't have any information about your package structure, but I think the <class /> element from module descriptor should be:
<class>es.vass.magnolia.module.wsprouser.WsProuser</class>
It looks like you are repeating the class name.
Update: After reading the log, I saw that the NPE is thrown when the module ui-admincentral is started. At that time, your custom module ws-prouser-prosegur-intra-module is not started yet, so the static instance is still null. In order to work this way you should add a dependency to your module in ui-admincentral, but given that this is a magnolia module, you can't do that. What I would recommend is to inject a Provider<WsProuser> in your CommandGenerator and use that instead of WsProuser.getInstance(). Then use this provider where you actually need it, not in constructor.

Related

SpiRawSqlService not found setting up EBean in a Spigot plugin

Overview
I set up a github repo for this question to provide as much of the boiled down environment as possible.
My goal is to set up ebean ORM for database manangement from a Paper Minecraft plugin. I'm able to shade in the ebean dependencies, but creating a query using "io.ebean:ebean-querybean:" throws an error saying that it cannot find an implementation of SpiRawSqlService.
Environment
Paper Minecraft: paper-1.19.3-367.jar
Java 18
Ebean enhancement plugin for IntelliJ(I checked that I have it enabled for this project)
io.ebean gradle plugin version 13.10.0
shadowJar gradle plugin version 7.1.2
The Stacktrace
Everything is fine setting up the database, and saving to the Database. Queries without using a querybean work fine as well. The error is thrown when initializing any class containing a reference to a generated querybean.
The error outputted is printed the latest.log
Caused by: java.lang.IllegalStateException: No service implementation found for interface org.example.ebean.io.ebean.service.SpiRawSqlService
The stacktrace tells us that it couldn't find org.example.ebean.io.ebean.service.SpiRawSqlService.
Looking at the decompiled shadowJar after package relocation, the implementation for this class is found at org.example.ebean.io.ebeaninternal.server.rawsql.DRawSql;
Printing out the ClassLoader#getDefinedPackages on the instance supplied when creating the ebean Database connection results in this:
org.example.ebean
org.example.ebean.database
org.example.ebean.io.ebean
org.example.ebean.io.ebean.annotation
org.example.ebean.io.ebean.config
org.example.ebean.io.ebean.config.dbplatform
org.example.ebean.io.ebean.datasource
org.example.ebean.io.ebean.meta
As you can see, the org.example.ebean.io.ebeaninternal package and subpackages are not outputted in this list.
Underlying issue
How/where is the package "ebeaninternal" being loaded if at all? How can I get the enhanced querybean to find this package so it can load the implementation (DRawSql) of SpiRawSqlService?
Reasoning
Bukkit's #EventHandler utilizes a different contextClassLoader than the ClassLoader that loads the ebean classes/services (contained in the ShadowJar).
The error states No service implementation found because the thread that is initializing the querybean does not have access to that class.
Explained Solution
The solution here is to use Thread#setContextClassLoader() to use the same ClassLoader used when calling DatabaseFactory.createWithContextClassLoader(). Set the ClassLoader, initialize every Class that uses a QueryBean, revert the ClassLoader to what it originally was.
EBean might be able to solve this problem. But for now, a fix is to just call an empty init method on every class that becomes an Enhanced-QueryBean from a thread that is using the proper ContextClassLoader
Full Example
I pushed the full example containing the fix to the original github repo
Basic Example
DatabaseSetup.java
public static void load() {
DataSourceConfig dataSourceConfig = configureDataSource();
DatabaseConfig dbConfig = configureDatabase(dataSourceConfig);
// We should use the classloader that loaded this plugin
// because this plugin has our ebean dependencies
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
ClassLoader pluginClassLoader = BukkitEBeanPlugin.class.getClassLoader();
// create the DatabaseFactory with the classloader containing ebean dependencies
DatabaseFactory.createWithContextClassLoader(dbConfig, pluginClassLoader);
// Set the current thread's contextClassLoader to the classLoader with the ebean dependencies
// This allows the class to initialize itself with access to the required class dependencies
Thread.currentThread().setContextClassLoader(pluginClassLoader);
// invoke the static initialization of every class that contains a querybean.
// Note that any method in the class will initialize the class.
FindByQueryBean.init();
// Restore the contextClassLoader to what it was originally
Thread.currentThread().setContextClassLoader(originalClassLoader);
BukkitEBeanPlugin.get().getLogger().info("Successfully created database");
}
...
}
FindByQueryBean.java
public static void init() {
// intentionally empty
}

java.lang.NoClassDefFoundError only in particular conditions

My problem is that when class B tries to use A.check() my execution stops due to a java.lang.NoClassDefFoundError.
So here is my class configuration. NB: the classes are in the same packages and I have already checked that the A.class file is placed where it should be.
public class A{
// vars
// declare some public method
public synchronized static boolean check(){
//do stuff, log some info and return boolean
}
}
public class B implements Runnable{
public void run() {
A.check();
}
}
And here is my stacktrace:
java.lang.NoClassDefFoundError:
org/mypackage/A
at org/mypackage.B.run()
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException:
org/mypackage.B
at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:50)
The project is really big and class A is used lots of times before this call without any problem, so i don't think that is something relative to the classpath. Note that this is part of the last call of the software that should close up everything.
Moreover, I have two maven goals: the first one execute the questioned code without any problem, instead the second rise this error every time.
So I have solved my problem and I post here the solution so maybe can be useful for someone else.
First of all the error: java.lang.NoClassDefFoundError
This error is really different from ClassNotFoundException and this is where I'have lost a lot of time.
NoClassDefFoundError in Java is raised when JVM is not able to locate a particular class at runtime which was available at compile time. For example, if we have a method call from a class accessing any member of a Class and that class is not available during runtime then JVM will throw NoClassDefFoundError. It’s important to understand that this is different than ClassNotFoundException which comes while trying to load a class at run-time only and the name was provided during runtime, not on compile time. Many Java developer mingles this two Error and gets confused. Here I quote a really useful blog that I uesd.
So in a shorter way NoClassDefFoundError comes if a class was present during compile time but not available in java classpath during runtime.
But even with those information the problem was still there until I found the mystery: one of the reason that can place the class in a state that can be compiled but not located at runtime is that if you have static initialization that fail (e.g. in my class I had as field a static variable instantiated badly).
So remember to check for you initialization phase if you have static variables in your class this could be the reason of your java.lang.NoClassDefFoundError.
By the way I don't get why this kind of error is not raising some more meaninful errors for example java.lang.ExceptionInInitializerError or something like that.
Try to debug maven execution by running: mvn -X <your_goals>
It would be useful to see your POM file.
If you are working with spring mvc and if you made bean entry in dispatche-servlet.xml for Controller class.
Example :
<bean id="MyClass" class="com.aaps.myfolder.MyClass">
<property name="methodNameResolver">
<ref bean="methodNameResolver" />
</property>
</bean>
And if MyClass.java is not compiled & if no class file is generated in classes folder of your project folder then it wil show java.lang.NoClassDefFoundError.
So check whether the MyClass.class is created or not in classes folder if you are working with spring mvc.
Does Class A have anything that is done in a static block. You can get this exception even if a class is being loaded and static blocks fails for any reason reason. try to put in logging to see if something like this is happening.

gwt - cannot create unit test for class that uses HTMLPanel

I have util class with one method:
public static void setStyleForWidgetLayout(HTMLPanel panel, int rowQuantity) {
Which for each Widget in HTMLPannel assign widgth depends on number of widgets and rows.
It is very simple switch.
I want to test this method but when i create test with normal JUnit test case i recieve error on creating HTMLPanel.
Caused by: java.lang.UnsupportedOperationException: ERROR: GWT.create() is only usable in client code! It cannot be called, for example, from server code. If you are running a unit test, check that your test case extends GWTTestCase and that GWT.create() is not called from within an initializer or constructor.
Next I tried to extend GWTTestCase but it requires to implement getModuleName() but i dont have any particular module because the class I test is just util class
Ok, I thought, lets mock it. I used mockito, but the errror occured, same as from previous code section.
Than I found class GwtTestWithMockito and tried to run this and again I recieved error.
com.googlecode.gwt.test.exceptions.GwtTestConfigurationException: No declared module. Did you forget to add your own META-INF/gwt-test-utils.properties file with a 'gwt-module' property in the test classpath?
I added #GWTModule and this META-INF/gwt-test-util.properties. And experimented with different configurations. I tried existing module names and not existing ones but still i recieve error above.
Thanks in advance
I'm afraid you have to use GWTTestCase. Your module name is the name of your module XML file.
Sometimes you have to add your Panel to the root panel, I generally do this just to be on the safe side.

NoClassDefFoundError exception in my thread

I get this error:
Exception in thread "http-server" java.lang.NoClassDefFoundError: org/w3c/jigmonitor/ReplyServer
but I don't undestand why. Could someone explain why does this happen?
This is the class that causes the problem:
public class ReplyServer implements Serializable
{
public ReplyServer()
{
super();
}
}
It looks like the class you're defining isn't being found by something that's trying to load it. In my experience this is caused by one of three problems:
Your package declaration for the class is not correct. In this case something on the http-sever thread is expecting your class to be declared in the package org.w3c.jigmonitor.
Your source file is not located in the correct directory. In this case, your source file should be located in a directory structure like "org/w3c/jigmonitor/", providing that's the package you actually want.
The path of the compiled class for ReplyServer is not in the classpath of your JVM. You can check this by looking at the classpath used to start your JVM and seeing if the class is actually there or not. In most generic setups servlet setups there will be a "WEB-INF/classes" folder for you to go poke around in.
Good luck!
(The link David posted gives a ton of information on this type of issue and the possible causes. I would recommend tucking that away for later)

NoClassDefFoundError messages differ with context

NoClassDefFoundError gives me different kinds of messages in different contexts
By contexts, I mean,
Context 1:
If I remove the sapjco3.jar, the message is
java.lang.NoClassDefFoundError: com/xxx/xxx/AbapException
Context 2:
If I add the jar file in the webapp lib, the message is
java.lang.NoClassDefFoundError: com.xxx.xxx.CpicDriver
I understand java.lang.NoClassDefFoundError is thrown when a class is not found during runtime.
but why there is a difference in representing the class in the message, ie with a slash (path) and dot (package)?
If you look at javadoc for NoClassDefFoundError exception, you'll see it has two constructor, one of which is accepting a message as parameter.
So formatting of the name for the class not found is depending on the code throwing the exception .
I don't know sapjco, but maybe the two classes are loaded by differents class loaders...
Seems like java.lang.NoClassDefFoundError: com/xxx/xxx/AbapException is missing. This is not in sapjco3.jar.
Suppose a.class and b.class are required and order of loading is a,b. if a and b are not in classpath you will first get a is missing. if a is added in the class path you will get b is missing. Hope that is clear.

Categories