Spring Session with Hazelcast 4 - hazelcast

I'm trying to upgrade to Hazelcast 4.0 in our Spring Boot 2.2.1 application.
We use the #EnableHazelcastHttpSession annotation, which pulls in HazelcastHttpSessionConfiguration, which pulls in HazelcastIndexedSessionRepository from the spring-session-hazelcast jar.
However, this class won't compile because it imports Hazelcast's IMap which has moved to a different package in Hz 4.0.
Is there any way to fix this so that Spring Session works with Hazelcast 4?

I just copied the HazelcastIndexedSessionRepository into my own source code, changed the import from com.hazelcast.core.IMap to com.hazelcast.map.IMap, and swapped the sessionListenerId from String to UUID. If I keep it in the same package, then it loads my class instead of the one in the jar, and everything compiles and works fine.
Edit: We no longer get the SessionExpiredEvent, so something's not quite right, but manual testing shows us that our sessions do time out and force the user to log in again, even across multiple servers.

I found the cause of the error, you must look that the session repository is created by HazelcastHttpSessionConfiguration, in the class it checks wich version of hazelcast is in the classpath, when hazelcast4 is true then it instantiates Hazelcast4IndexedSessionRepository that doesn't use 'com.hazelcast.core.IMap' and you don't get the class not found exception.
Code of class HazelcastHttpSessionConfiguration
#Bean
public FindByIndexNameSessionRepository<?> sessionRepository() {
return (FindByIndexNameSessionRepository)(hazelcast4 ? this.createHazelcast4IndexedSessionRepository() : this.createHazelcastIndexedSessionRepository());
}
Remove the usage of HazelcastIndexedSessionRepository replace it with Hazelcast4IndexedSessionRepository or remove the code and let spring autoconfiguration do the job by HazelcastHttpSessionConfiguration

Related

Why is InvocationInterceptor active in dev-mode?

Today, while profiling a Quarkus app, I found out that io.quarkus.arc.runtime.devconsole.InvocationInterceptor seems to intercept (almost?) all bean classes when Quarkus is running in dev mode, even though the Interceptor has an InterceptorBinding that is not used anywhere in the application code.
#Inherited
#InterceptorBinding
#Target({ TYPE, METHOD })
#Retention(RUNTIME)
public #interface Monitored {
}
#Priority(Interceptor.Priority.LIBRARY_BEFORE)
#Monitored
#Interceptor
public class InvocationInterceptor {
//...
}
Can somebody explain to me why that is the case? I can't really tell if this is intended behaviour or a bug. Is the InterceptorBinding automatically sprinkled around my app during the build? I looked through the code, but could not find a place where that happened.
Why am I interested in that? The bookkeeping this interceptor does uses a CopyOnWriteArrayList (inside Invocation.Builder) which, in a hot loop will quickly generate tens of thousands of copies of that list. Today, that confused the heck out of me while I was profiling the app, because the memory requirements were so drastically different between prod and dev mode.
(If relevant: All of this happened with Quarkus 2.7.3.Final)
This is essentially #Ladicek's comment:
[The behaviour] is intentional, but there are discussions it should be off by default. In any case, there's a configuration property to switch it off.
I was also able to locate the BuildExtension that does the magic: It is located inside io.quarkus.arc.deployment.devconsole.ArcDevConsoleProcessor.

Mockito latest versions support to surpress static block

I am trying to add tests using latest (5.7.0) Mockito and using Mockito.mockStatic(...)
to mock class with static methods which works fine . However when I have class with static block it is unable to create mock and fais with java.lang.InternalError: class redefinition failed: invalid class .
Is this supported in latest mockito versions or still I have to live with other alternatives like powermock.
I did face the same error and couldn't find answer in the internet, so I see that it is 1 month old question but might help someone.
The problem was that mocked class (or classes that this static block used) was not in the classpath. Before you can mock the method all static blocks or fields initializators will be run, and it causes the problem.
You can verify what class is missing in your classpath by simply trying to use this static method before mocking it. You should get java.lang.NoClassDefFoundError with a class name.
When you resolve this problem, everything should work.
I had this issue, and for me it was due to an Error being thrown from instrumentation.retransformClasses called from org.mockito.internal.creation.bytebuddy.inlineBytecodeGenerator. Somewhere between there and findOrInsert in net.bytebuddy.TypeCache, the Throwable looses its context (for mockito-core 4.1.0 and bytebuddy 1.12.0)
In my case, the error being thrown was a NoClassDefFoundError for Jetty Servlet. This ultimately turned out to be a dodgy local build of a different maven module I had been working on, so clearing out my ~/.m2 and downloading a legit version fixed that right up.
You might be able to catch the Error being thrown in inlineBytecodeGenerator and taking a look at what's really going on, if this is in fact the same problem.

SearchDomainFactory.Instance is obsolete: 'Inject me!' ( Can't find out how to create instance)

I'm in the process of trying to migrate a R# extension project from R# 6 to R# 8. (I've taken over a project that someone wrote, and I'm new to writing extensions.)
In the existing v6 project there is a class that derives from RenameWorkflow, and the constructor used to look like this;
public class RenameStepWorkflow : RenameWorkflow
{
public RenameStepWorkflow(ISolution Solution, string ActionId)
: base(Solution, ActionId)
{
}
This used to work in R# SDK v 6, but now in V8, RenameWorkflow no longer has a constructor that takes Solution and actionId. The new constructor signature now looks like this;
public RenameWorkflow(
IShellLocks locks,
SearchDomainFactory searchDomainFactory,
RenameRefactoringService renameRefactoringService,
ISolution solution,
string actionId);
now heres my problem that I need help with (I think)
I've copied the constructor, and now the constructor of this class has to satisfy these new dependancies. Through some digging I've managed to find a way to satisfy all the dependencies, except for 'SearchDomainFactory'. The closest I can come to instantiating via the updated constructor is as follows;
new RenameStepWorkflow(Solution.Locks, JetBrains.ReSharper.Psi.Search.SearchDomainFactory.Instance, RenameRefactoringService.Instance, this.Solution, null)
All looks good, except that JetBrains.ReSharper.Psi.Search.SearchDomainFactory.Instance is marked as Obsolete, and gives me a compile error that I cannot work around, even using #pragma does not allow me to compile the code. The exact error message I get when I compile is Error 16 'JetBrains.ReSharper.Psi.Search.SearchDomainFactory.Instance' is obsolete: 'Inject me!'
Obvious next question..ok, how? How do I 'inject you'? I cannot find any documentation over this new breaking change, in fact, I cannot find any documentation (or sample projects) that even mentions DrivenRefactoringWorkflow or RenameWorkflow, (the classes that now require the new SearchDomainFactory), or any information on SearchDomainFactory.Instance suddenly now obsolete and how to satisfy the need to 'inject' it.
Any help would be most appreciated! Thank you,
regards
Alan
ReSharper has its own IoC container, which is responsible for creating instances of classes, and "injecting" dependencies as constructor parameters. Classes marked with attributes such as [ShellComponent] or [SolutionComponent] are handled by the container, created when the application starts or a solution is loaded, respectively.
Dependencies should be injected as constructor parameters, rather than using methods like GetComponent<TDependency> or static Instance properties, as this allows the container to control dependency lifetime, and ensure you're depending on appropriate components, and not creating leaks - a shell component cannot depend on a solution component for instance, it won't exist when the shell component is being created.
ReSharper introduced the IoC container a few releases ago, and a large proportion of the codebase has been updated to use it correctly, but there are a few hold-outs, where things are still done in a less than ideal manner - static Instance properties and calls to GetComponent. This is what you've encountered. You should be able to get an instance of SearchDomainFactory by putting it as a constructor parameter in your component.
You can find out more about the Component Model (the IoC container and related functionality) in the devguide: https://www.jetbrains.com/resharper/devguide/Platform/ComponentModel.html

Accessing methods from imported jars in managed beans

I'm sure I'm missing something, but I'm not seeing it at all.
I'm creating PDFs using iText, and I want to do this in a bean. I've created one, but it's been erroring out. It seems some of the ways I've usually worked in Java don't seem to work in this bean.
For example, this line:
com.itextpdf.text.Document document1 = new com.itextpdf.text.Document();
will throw the error java.lang.NoClassDefFoundError: com.itextpdf.text.Document, even though the jar is imported, in the build path and com.itextpdf.text.Document is imported in the bean.
if you change it to this:
com.itextpdf.text.Document document1;
or
com.itextpdf.text.Document document1 = null;
the error goes away. I don't understand why one way works and the other doesn't, but it's a fairly easy change to make.
Now I need to set the page size. This will work in Eclipse:
document1.setPageSize(PageSize.LETTER);
but this is the error I get:
java.lang.NoClassDefFoundError: com.itextpdf.text.PageSize
Which might be because I've set it to null to initialize it. But
document1 = new Document();
and
document1 = new com.itextpdf.text.Document();
both throw java.lang.NoClassDefFoundError: com.itextpdf.text.Document
Oddly, the import statement for (iText) Document warns me it is never used.
document1.open();
will give the error java.lang.NoClassDefFoundError: com.itextpdf.text.Document as well.
So, am I missing something in the syntax in beans? I've created Notes Java agents, XAgents, and straight up Java Eclipse projects that work, but I can't get the methods to work in a 8.5.3 Java Bean. I imported the iText jars into WebContent\WEB-INF\lib and then added those (via add jars, not add external jars) to the build path. I've gotten the latest jars and I'm using them, I've built and cleaned, the bean is in faces-config. But I'm doing something wrong, and I can't see it.
If someone could point me in the right direction, I would be very grateful.
Cheers,
Brian
EDIT:
The license isn't a problem, but I still can't get the class to load even using the classLoader:
Thread currentThread = Thread.currentThread();
ClassLoader clCurrent = currentThread.getContextClassLoader();
//ClassLoader clCurrent=com.ibm.domino.xsp.module.nsf.NotesContext.getCurrent().getModule().getModuleClassLoader();
try {
currentThread.setContextClassLoader(Activator.class.getClassLoader());
DebugToolbar.get().info("after setting up FileOutputStream");
com.itextpdf.text.Document document1 = new com.itextpdf.text.Document();
//com.itextpdf.text.Document document1;
//com.itextpdf.text.Document document1 = null;
//document1 = new com.itextpdf.text.Document();
//document1.open();
document1.setPageSize(PageSize.LETTER);
I still get java.lang.NoClassDefFoundError: com.itextpdf.text.Document
I've cut the beans out, cleaned, built, pasted back in, cleaned built, still the error.
I appreciate the assistance.
Brian
Most likely you have a classloader isssue. Unless your app is strictly for internal use, you might reconsider use of iText since it is GPL. Apache PDFBox is an Apache licensed alternative (I'm particularly fond of) or Apache FOP (I'll complete the ]2 missing articles](http://www.wissel.net/blog/htdocs/DominoXSLT), promise). Of course OpenNTF's POI4XPages might just be what you need.
I called Lotus/ICS support. It seems for 8.5.3, if you put the jars in ~Lotus\Notes\jvm\lib\ext they will load. I'm testing this on my local, but the same path should work on the server. I'll test that Monday. I had researched, and if that is mentioned I didn't find it. Jars will be a design element in 9, putting them in a directory like this should not be needed for that version, but it seems that adding them this way is more consistent now. The jars have loaded properly for some applications I've made, so this confused me a bit.
Stephan and Panu, thank you for responding.
Brian

Accessing global variable in multithreaded Tomcat server

Edit: I've figured out the constructor for the singleton is getting called multiple times so it appears the classes are getting loaded more than once by separate class loaders. How can I make a global singleton in Tomcat? I've been googling, but no luck so far.
I have a singleton object that I construct like thus:
private static volatile KeyMapper mapper = null;
public static KeyMapper getMapper()
{
if(mapper == null)
{
synchronized(Utils.class)
{
if(mapper == null)
{
mapper = new LocalMemoryMapper();
}
}
}
return mapper;
}
The class KeyMapper is basically a synchronized wrapper to HashMap with only two functions, one to add a mapping and one to remove a mapping. When running in Tomcat 6.24 on my 32bit Windows machine everything works fine. However when running on a 64 bit Linux machine (CentOS 5.4 with OpenJDK 1.6.0-b09) I add one mapping and print out the size of the HashMap used by KeyMapper to verify the mapping got added (i.e. verify size = 1). Then I try to retrieve the mapping with another request and I keep getting null and when I checked the size of the HashMap it was 0. I'm confident the mapping isn't accidentally being removed since I've commented out all calls to remove (and I don't use clear or any other mutators, just get and put).
The requests are going through Tomcat 6.24 (configured to use 200 threads with a minimum of 4 threads) and I passed -Xnoclassgc to the jvm to ensure the class isn't inadvertently getting garbage collected (jvm is also running in -server mode). I also added a finalize method to KeyMapper to print to stderr if it ever gets garbage collected to verify that it wasn't being garbage collected.
I'm at my wits end and I can't figure out why one minute the entry in HashMap is there and the next it isn't :(
Another wild guess: is it possible the two requests are being served by different copies of your web app? Each would be in its own ClassLoader and thus have a different copy of the singleton.
Have you tried removing the outer check
if(mapper == null)
{
Thereby always hitting the Synchronized point, it's subtle stuff but possibly you're hitting the double-checked locking idiom problem. Described here and in many other articles.
Must admit I've never seen the problem actually bite someone before, but this sure sounds like it.
With this solution, the JVM guarantees that it's only one mapper and that's it's initialized before use.
public enum KeyMapperFactory {
;
private static KeyMapper mapper = new LocalMemoryMapper();
public static KeyMapper getMapper() {
return mapper;
}
}
This may not be the cause of your problem but you are using the faulty double-checked locking. See this,
http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
I found a rather poor fix. I exported my code as a JAR and put it in $TOMCAT/lib and that worked. This is clearly a class loader issue.
Edit: Figured out the solution
Ok, I finally figured out the problem.
I had made my application the default application for the server by adding a to server.xml and setting the path to "". However, when I was accessing it through the URL http://localhost/somepage.jsp for somethings, but also the URL http://localhost/appname/anotherpage.jsp for other things.
Once I changed all the URLs to use http://localhost/ instead of http://localhost/appname the problem was fixed.

Resources