Upgrading Wicket 9.0.0 to 9.3.0: runtime error when try to access database - ejb

I am attempting to upgrade from Wicket 9.0.0 to Wicket 9.3.0. When I change the version in a quick-start application, everything is fine.
The problem occurs in my real application, where we were originally using Jakarta Enterprise Beans 8.0.0. At runtime, when a database access was attempted, we got an exception with the following message:
Last cause: net.sf.cglib.proxy.MethodInterceptor not found by org.objectweb.asm [23]
Trying to use Jakarta EE 9.1 instead
I changed my pom.xml as follows:
<jakartaee>9.1.0</jakartaee>
<wicket.version>9.3.0</wicket.version>
I downloaded the jar for Jakarta EE 9.1, changed "javax" to "jakarta" throughout my application, rebuilt it and tried to run again.
The result was still not perfect, but significantly better than before: a plain old null pointer exception instead of any weird errors about cglib.
Here's the section of code that now causes the trouble:
#EJB(name = "AdminNotesFacade")
private AdminNotesFacade adminNotesFacade;
public AdminNotesFacade getAdminNotesFacade() {
return adminNotesFacade; //ACTUALLY RETURNS NULL
}
So now the big question is: what do I need to do/change to make the #EJB work instead of returning null?
Checking the Payara log, I get this error:
java.lang.RuntimeException: Unable to load the EJB module. DeploymentContext does not contain any EJB. Check the archive to ensure correct packaging for D:\Dev\icase2\target\icase2.
If you use EJB component annotations to define the EJB, and an ejb or web deployment descriptor is also used, please make sure that the deployment descriptor references a Java EE 5 or higher version schema, and that the metadata-complete attribute is not set to true, so the component annotations can be processed as expected
at org.glassfish.ejb.startup.EjbDeployer.prepare(EjbDeployer.java:189)
Adding further details, 2022-05-06
I wonder if we were going off on the wrong track when we thought that we could fix this by upgrading our jakartaee version. From Wicket 9.0 to 9.3 is only a change of minor version and you wouldn't expect to have to make such fundamental changes to get a minor upgrade working.
I've tried using Wicket 9.9.1 instead, in case this problem has been fixed in more recent versions, but it's exactly the same.
Anyway, I have created a very small "quick-start" application, based on Wicket's own templates, to reproduce the problem. I have stuck with the original "javax" version, and added just one EJB - a JavaMail bean. I think it's probably interesting to know that it's not a specifically database-related issue. We just can't seem to load any EJBs at all.
In the Wicket 9.0.0 version, a simple form is displayed on the home page, allowing the user to enter their email address. When they submit the form, a test message is sent to that address. It works fine.
Then if I change the Wicket version to 9.3.0 but make no other changes at all, it doesn't even get to the stage of displaying the home page, it immediately crashes with the message "Last cause: net.sf.cglib.proxy.MethodInterceptor not found by org.objectweb.asm [23]"
For what it's worth, here's the code that triggers the error.
public class HomePage extends WebPage {
#EJB(name = "EmailerFacade")
private EmailerFacade emailerFacade;
private static final long serialVersionUID = 1L;
private String sendTo = "";
public HomePage(final PageParameters parameters) {
super(parameters);
add(new Label("version", getApplication()
.getFrameworkSettings().getVersion()));
FeedbackPanel feedback = new FeedbackPanel("feedback");
add(feedback);
final Form emailForm = new Form("emailForm") {
#Override
protected void onSubmit() {
emailerFacade.sendMessage(sendTo, "Test message from quick-start",
"Version is " + getApplication().getFrameworkSettings()
.getVersion());
info("Tried to send message to " + sendTo);
}
};
add(emailForm);
final TextField<String> emailAddress = new TextField<>("emailAddress",
new PropertyModel<>(this, "sendTo"));
emailAddress.setLabel(Model.of("Email address"));
emailAddress.setRequired(true);
emailForm.add(emailAddress);
}
}

Wicket 9.x is based on javax.servlet APIs. To deploy it on jakarta.servlet supporting web container you will need to migrate the bytecode with a tool like https://github.com/apache/tomcat-jakartaee-migration.
I am not sure whether Payara does something smart at runtime to support both javax.** and jakarta.** classes.
Tomcat 10.x supports migration of the classes at application start time by deploying your app in the special $CATALINA_HOME/webapps-javaee folder.

This answer was actually provided by Sven Meier. He commented:
Use the new system property to switch to ByteBuddy in Wicket 9.x:
-Dwicket.ioc.useByteBuddy=true
To expand a bit on this, I found I needed to do three things:
Set the system property "wicket.ioc.useByteBuddy" to true as specified by Sven
Add a dependency on byte buddy
Upgrade to a higher version than I was initially attempting to do: 9.3.0 was not good enough. I see in a comment above by Sven, he says that the migration to byte buddy was actually done in 9.5. So in fact I upgraded to the latest version, which is currently 9.9.1.
Here is the dependency on byte buddy that I added:
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.12.10</version>
</dependency>

Related

SQLite no longer seems to work on xamarin android

We have a Xamarin.Forms project that needed to use the sqlite local db to store date. EF Core's sqlite library was used to set this up and by different developers from different PCs (vs 2019). Initially, it was used with the Database.EnsureCreated() function and later with ef core's migrations. All went smooth for more than a month.
Last week all of a sudden the android app wouldn't start on any one's PC due to some error with sqlite. It showed the following error:
Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)
I spent a while trying all kinds of fixes and rollbacks thinking it was an issue with the code. This included the following:
Deleted obj and bin folders, cleaned and rebuilt for all below steps.
Downgraded the version of ef to 2.2.3 (the version we started with)
Rolled back to git commits up to a week back
Upgraded the versions of dependencies of ef core
Removed the past few migrations
Downgraded xamarin forms to 3.6.x
After trying the above and several other fixes, finally upgrading the versions of java and android SDK worked last Friday (on all PCs). Once this fix worked everything went smooth that day. On Tuesday once again the issue was back (no library updates or code changes). A deeper look at EF Cores logging shows that it crashes the moment it attempts to connect to a db.
The issue can be replicated on the android devices but not the emulators. I am not sure if there is some new permission in android we need to request for.
I finally created a new xamarin forms project with sqlite setup. I used the pcl library and ef core. I still found the same error.
Here is the git hub that replicates the issue https://github.com/neville-nazerane/xamarin-site
Update
Just something i noticed. eariler my database file was named "main.db". Now no matter what i change this file name to or no matter what variables i change. it always shows database name as "main" in logs. Not sure if changing the db name would fix the issue. However, never found a way to change this db name. I tried different connection strings, it just said "database" and "db" were unknown keys
Update
Steps to replicate:
using (var db = new AppDbContext())
{
db.Add(new Person {
Age = 55,
Name = "Neville"
});
db.SaveChanges();
Person[] alldata = db.People.ToArray();
}
The definitions of Person and AppDbContext are quite obvious. So, with the spirit of not making the question too long, I am not posting it here. However, if required I can post them too.
This is a bug with the Xamarin.Forms and Mono.
It was detected since a couple of months ago, it was fixed but then there was some regression (with VS 2019 v16.1).
Even with the latest release (v16.1.2) the bug still happens, so we need to wait for a fix.
Sources:
https://github.com/mono/mono/issues/14170
https://github.com/xamarin/xamarin-android/issues/3112
https://github.com/xamarin/xamarin-android/issues/2920
Due to slight differences of the particular file systems on the native side, I would suggest creating an interface to handle the actual database file handling on the native application level.
So here is how I implemented SQLite using the nuget package SQLite.Net-PCL:
In the shared project, create a new interface, for instance FileHandler.cs
public interface IFileHandler
{
SQLite.SQLiteConnection GetDbConnection();
}
You may want to extend that with more methods to save or retrieve various files, but for now we will just have the GetDbConnection Method to retrieve a working SQLite Connection.
Now in your Android implementation, we add the native implementation to that interface:
Create a new class called FileHandler.cs in your android project:
[assembly: Dependency(typeof(FileHandler))]
namespace YourProjectName.Droid
{
public class FileHandler : IFileHandler
{
public SQLite.SQLiteConnection GetDbConnection()
{
string sqliteFilename = "YourDbName.db3";
string path = Path.Combine(GetPersonalPath(), sqliteFilename);
SQLiteConnectionString connStr = new SQLiteConnectionString(path, true);
SQLiteConnectionWithLock connection = new SQLiteConnectionWithLock(connStr, SQLiteOpenFlags.Create | SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.NoMutex);
return connection;
}
private string GetPersonalPath()
{
return Environment.GetFolderPath(Environment.SpecialFolder.Personal);
}
}
}
Now back again in your shared code you can access that connection with the following code:
using (SQLiteConnection connection = DependencyService.Get<IFileHandler>().GetDbConnection())
{
// Do whatever you want to do with the database connection
}
Alright mate, I don't understand what issue you are facing. It might be an issue with your machine, I'd suggest using another computer/laptop.
I took the exact code that you shared on the Github. I was able to build it on my Mac computer in VS 2019 and installed the application in debug mode on my phone. I was able to add a date successfully, as you can see in the picture, and I placed an Exception Catchpoint and faced no exceptions.
I then proceeded to add another entry with the same details and it errored out with the message that you can see here
I would also suggest using Xamarin Profiler or any other Android logger to see the Stack Trace that you aren't able to see in your application output. It will give you details of the error, that you can share here for us to understand better.

Wicket tester not searching WebApplicationPath

In my first Wicket project (developed in Wicket 6.20 using Eclipse mars and Glassfish 4.1) based on the Quickstart Maven archetype, I am using
getResourceSettings().getResourceFinders().add(new WebApplicationPath(getServletContext(), "html")); to separate markup from code.
My homepage works well, but the WicketTester throws an exception org.apache.wicket.markup.MarkupNotFoundException: Can not determine Markup. Component is not yet connected to a parent. [Page class = ...MyProject.HomePage, id = 0, render count = 1]
This problem does not seem to be addressed anywhere in the literature.
After many hours of searching, a thorough debugging session lead me to the JavaDoc for MockServletContext which explains that it is necessary to supply an absolute path to the root of the application on disk if non-default resource locations are used.
Furthermore, I found that this path can be supplied as a second argument to the constructor of WicketTester.
So, my test Setup() method finishes with :
return new WicketTester(new WicketApplication(),"<path to Eclipse workspace>/MyProject/src/main/webapp");

Caliburn.Micro IEventAggregator Publish method missing an overload

I'm working through some tutorials online learning Caliburn.Micro for the first time. Some of the tutorials are using the older 1.3.0 version, I'm using the newer 2.0.0.6 version which was the latest Nuget package which is likely the source of this discrepancy:
When trying to publish the following message:
public void Red()
{
_events.Publish(new ColorEvent(new SolidColorBrush(Colors.Red)));
}
The compiler throws an error saying that the overload wasn't found. The only overload for Publish that is available has the following signature:
void Publish(object message, Action marshal)
I got this to work by using the background worker thread method shown below but in my case it seems like overkill. Was the single parameter overload really removed from Caliburn.Micro?
Also, the documentation is here:
https://caliburnmicro.codeplex.com/wikipage?title=The%20Event%20Aggregator
still show examples using the more basic, single parameter example where you simply pass a message. Is the documentation at this link the latest that correctly describes 2.0.0.6?
public void Red()
{
_events.Publish(new ColorEvent(new SolidColorBrush(Colors.Red)),
action => Task.Factory.StartNew(action));
}
Finally, for bonus points:
What is this 2nd parameter good for other than publishing the message on a background thread? Can someone give some other example(s) of what this overload can be used for?
In Caliburn Micro version 2.0, the EventAggregator.Publish method also takes an action to marshal the event. To maintain the pre-2.0 behavior, you should switch to the EventAggregator.PublishOnUIThread method instead. See the migration instructions here for information on incompatibilities between 1.5 and 2.0.
In general, I believe that the Codeplex documentation is a little bit outdated. Please refer to the new dedicated web site for most up-to-date documentation.

MvvmCross - how do I access SQLite in a windows store background task?

I have a store app that uses the mvvmcross sqlite plugin (community edition). This app has a periodic background task that accesses the database to get data to be shown in a live tile. I can't see how I can get access to this database from the background task. I would like to use the mvvmcross sqlite plugin in the background task, but I don't see how to initialize the mvvmcross environment properly.
If you want to initialize the full MvvmCross framework including all of your app, then you'll need to run your Setup class.
In WinRT, this could be as simple as calling:
var setup = new Setup(null /*rootFrame*/);
setup.Initialize();
although it may require you to do a little work to:
Make sure your presenter does not use the null rootFrame
Provide some other means to create a UI thread dispatcher - currently MvxStoreViewDispatcher relies on .Dispatcher access - see https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.WindowsStore/Views/MvxStoreViewDispatcher.cs - to do this, you could override InitializeViewDispatcher with something like:
protected override void InitializeViewDispatcher()
{
if (_rootFrame != null)
{
base.InitializeViewDispatcher(); return;
}
var dispatcher = new NonMainThreadDispatcher();
Mvx.RegisterSingleton<IMvxMainThreadDispatcher>(dispatcher);
}
public class NonMainThreadDispatcher : MvxMainThreadDispatcher
{
public bool RequestMainThreadAction(Action action)
{
action();
}
}
If you want to initialize less functionality than the entire framework (e.g. for memory reasons) then you can also consider creating special Setup and App classes just for your background task.
Aside> This is similar to questions like these in Android - Using MvvmCross from content providers and activities and MvvmCross initialization
I was able to solve the problem in a straightforward way. Since the background task only needed the SQLite data service from the PCL core project, I did the following:
Included a reference to the Core project.
Added the nuget packages for MvvmCross and the SQLite community plugin.
Deleted all of the files and folders added when doing the mvvmcross install: Bootstrap/, Todo-Mvvmcross/, Views/, DebugTrace.cs, and Setup.cs.
There is a current limitation in the nuget installer that requires some additional edits to the project file to handle multiple store platforms (x86, ARM, and x64), see 'Cirrius.Mvvmcross.Community.Plugins.SQLite.WindowsStore needs platform-specific dlls for X86 and ARM' on Stack Overflow for details. Make sure you put the Choose statement after the default SQLite.WindowsStore reference and you need to leave the default reference in the project file. You will also need to adjust the HintPath based on the location/names of your references.
Initialized the SQLite data service by explicitly calling the factory and creating a new instance of the data service:
var factory = new MvxStoreSQLiteConnectionFactory();
IMyDataService repository = new MyDataService(factory);
I then have access to the data service with no other overhead associated with mvvmcross.

Error when using DependencyResolver for Controller instantiation with MVC 3

I'm using MVC 3 and using the following code when the application starts...
UnityContainer container = new UnityContainer();
new UnityMappings(container);
DependencyResolver.SetResolver(new UnityServiceLocator(container));
Now when the app runs I'm getting the following error (but only sometimes)...
Activation error occured while trying to get instance of type
IControllerFactory, key ""
Interestingly, if I continue with the web request, the website works normally.
Any ideas? I can't see what I'm doing differently from before when this worked fine.
Cheers, Ian.
MVC3 requests a lot more than just controllers from the DependencyResolver. For most of them MVC3 falls back to the default implementation in case the DependencyResolver does not return an instance.
In your case it requests the IControllerFactory which is unknown to your IoC container and it throws an exception which is caught by the UnityServiceLocator implementation and null is returned. MVC then falls back to the default controller factory.
Unlike other IoC containers Unity does not provide an optional TryResolve and therefore does not support a proper exceptionless implementation of the DependencyResolver.
I would suggest first looking through the config and make sure everything is correct there, then I would make sure I had all the assemblies needed for Unity referenced in the project. That error message may (in my experience) point to an error in config or a missing DLL, perhaps an assembly you want to load in the container or another DLL needed by a DLL loaded by Unity?
Hope this helps.

Resources