Wicket Decorator to Listener when upgrade from 1.5.x to 6.x - wicket-1.5

I have been requested to upgrade the wicket version from 1.5.9 to 6.14.0 in a web-app.
I have found upgrading the (behavior) decorators to listeners very problematic.
https://cwiki.apache.org/confluence/display/WICKET/Wicket+Ajax#WicketAjax-o.a.w.ajax.IAjaxCallDecoratorisreplacedwitho.a.w.ajax.attributes.IAjaxCallListener
o.a.w.ajax.IAjaxCallDecorator is replaced with o.a.w.ajax.attributes.IAjaxCallListener.
I have succeeded in creating a POC where I upgrade the needed parts almost correctly.
In 1.5.9 the element script can be decorated like this (at low level, there is also other changes involved, but it ends to this)
public class MyBehavior extends AjaxFormComponentUpdatingBehavior {
#Override
// (removed in upgrade to 6.14.0)
protected IAjaxCallDecorator getAjaxCallDecorator() {
return new SmallDecorator();
}
private class SmallDecorator extends AjaxCallDecorator {
public SmallDecorator() {}
#Override
public CharSequence decorateScript(Component component, CharSequence script) {
return "alert('decorated onblur');" + script;
}
}
}
In 6.14.0 the same is done like this (as far as I have understood it correctly)
public class OnBlurBehavior extends AjaxFormComponentUpdatingBehavior {
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.getAjaxCallListeners().add(new
GenericListenerImpl("alert('Listener onblur')"));
}
private class GenericListenerImpl extends AjaxCallListener {
private String decoratorScript = null;
public GenericListenerImpl(String decoratorScript) {
this.decoratorScript = decoratorScript;
}
#Override
public CharSequence getPrecondition(Component component) {
return this.decoratorScript;
}
}
}
Now this works in basic, but when I want to edit or wrap the "script" like in the 1.5.9 version is done, how can I accomplish that in the 6.14.0 version?
This has proved to me extremely problematic as I haven't used Wicket for a (very) long time and kind of being a noob is specially what comes to the latest version. :)

I was in impression that the "script" part in 1.5.9 contains a single String of element attributes (or something like that) UI developer had added for the element in html. But checking that in detail reveals that the "script" content actually looks something like this:
var wcall=wicketAjaxPost('./?0-1.IBehaviorListener.0-input', wicketSerialize(Wicket.$('input')),function() { }.bind(this),function() { }.bind(this), function() {return Wicket.$('input') != null;}.bind(this));
So the "script" is something generated by the wicket and actually there is no content that could had been set by the (UI) developer and could require modification on the java side.
In general I consider such behavior bad (as in 1.5.9) when given the generated script to be modified and omitting this option alltogether in upgrade to 6.14.0 seems justified... Even that this causes gray hair and extra work to fix the functionality getting broken with the upgrade.
The code examples given above are correct, you just need to figure out what behavior to add (override) in GenericListenerImpl to gain the same functionality as with decorating the script with SmallDecorator.
The API for AjaxCallDecorator appears to be bad as it does not explaing the parameters with the 'decorateScript', thus I was mislead with the issue...
http://wicket.apache.org/apidocs/1.5/org/apache/wicket/ajax/calldecorator/AjaxCallDecorator.html#decorateScript%28org.apache.wicket.Component,%20java.lang.CharSequence%29

Related

Why does Spring Boot ignore my CustomErrorController?

I have a custom ErrorController like this:
#Controller
public class CustomErrorController implements ErrorController {
#RequestMapping("/error42")
public String handleError(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
System.err.println(status);
if (Objects.isNull(status)) return "error";
int statusCode = Integer.parseInt(status.toString());
String view = switch (statusCode) {
case 403 -> "errors/403";
case 404 -> "errors/404";
case 500 -> "errors/500";
default -> "error";
};
return view;
}
}
And then I've set the server.error.path property like this:
server.error.path=/error42
So far, so good. Everything works fine. All the errors go through my CustomErrorController.
But when I set the error path to server.error.path=/error - and of course I change the request mapping annotation to #RequestMapping("/error") - this won't work anymore.
Spring Boot now completely ignores my CustomErrorController. I know, I've set the path to the one Spring Boot usually defines as standard, but is there no way to override this?
Many thanks for any information clearing up this weird behavior.
I found the error, and it was solely my own fault. Since especially at the beginning of a Spring Boot career, the setting options quickly become overhelming, and one can lose sight of one or the other adjustment made, I would still like to leave this question and answer it myself.
The culprit was a self-configured view that i did weeks ago and completely lost track of:
#Configuration
#EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
/* FYI: will map URIs to views without the need of a Controller */
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login")
.setViewName("/login");
registry.addViewController("/error") // <--- Take this out !!!
.setViewName("/error");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}
May this help others facing the same mystery, why once again nothing runs quite as desired...

Interceptor on a class method belonging to External Dependency

We have an Aspect in our code that had been PointCut on Hibernate class.
Our Aspect class looks something like this:
#PointCut("(execution(* *.getQueryString(..))" + "|| execution(* *.getQuery(..)))" + "&& (target(org.hibernate.engine.NamedSQLQueryDefinition))")
public void aroundNamedSQLQueryDefinitionGetQuery() {
}
#Around("aroundNamedSQLQueryDefinitionGetQuery")
public String addExtraFilter(ProceedingJoinPoint pjp) throws Exception {
//Logic to add extra filter to the Query.
}
Now we are trying to migrate this code to Quarkus. We have replaced Aspects with Interceptors which were present on code belonging to our modules.
But how do we add Interceptors on Hibernate classes?
Is there an alternate way to achieve this?
A Quarkus extension would allow you to manipulate the Hibernate classes (or your own classes).
To scaffold a basic extension,
mvn io.quarkus.platform:quarkus-maven-plugin:2.10.1.Final:create-extension -N \
-DgroupId=org.you \
-DextensionId=aspectorama
Then, in the [whatever]Processor class that gets created, you could add an AnnotationTransformerBuildItem
#BuildStep
AnnotationsTransformerBuildItem transform() {
return new AnnotationsTransformerBuildItem(new AnnotationsTransformer() {
public boolean appliesTo(org.jboss.jandex.AnnotationTarget.Kind kind) {
return kind == org.jboss.jandex.AnnotationTarget.Kind.METHOD;
}
public void transform(TransformationContext context) {
if ("org.hibernate.engine.NamedSQLQueryDefinition".equals(context.getTarget().asMethod().declaringClass().name()) && ("getQueryString").equals(context.getTarget().asMethod().name()) {
context.transform().add(YourAnnotation.class).done();
}
}
});
}
(I haven't tested that, and I may not have quite the method names you intended. I only did getQueryString not getQuery... but it shows the idea.)
You may also need to tell Quarkus about your interceptor if it's not in the main application codebase:
/**
* Makes the interceptor as a bean so we can access it.
*/
#BuildStep
void beans(BuildProducer<AdditionalBeanBuildItem> producer) {
producer.produce(AdditionalBeanBuildItem.unremovableOf(YourInterceptor.class));
producer.produce(AdditionalBeanBuildItem.unremovableOf(OtherExtraBean.class));
}
It may be that the annotation route isn't the best for your use case, and you could make the changes you needed more directly. It's worth browsing all the Quarkus build items, which are kind of like a library of built-in extension capabilities. For example, you can use #Record to create bytecode.

What is the use case of skipping method execution in around advice?

I understood what #Around Advice does, and when we need to share Before and after state then we can use it, and we call also skip method execution. My question is why Spring given us this power to skip method execution and what is the use case of skipping method?
Side effects as NĂ¡ndor said are one thing. Maybe you even want to replace the return value altogether, possibly because there is a bug in a class you do not have the source code of or for other reasons:
Buggy Java class:
package de.scrum_master.app;
public class Earth {
public String getShape() {
return "disc";
}
}
Driver application:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
System.out.println("The Earth is a " + new Earth().getShape() + ".");
}
}
Console log:
The Earth is a disc.
Bugfix aspect:
package de.scrum_master.aspect;
import de.scrum_master.app.Earth;
public aspect BugfixAspect {
String around() : execution(* Earth.getShape()) {
return "sphere";
}
}
Console log with aspect applied:
The Earth is a sphere.
Method calls usually have side effects. Whenever you decide in your aspect that those side effects are undesirable for whatever reason, it's a valid use case to skip executing the original execution. This includes use cases for caching for example, when the side effects are not in terms of data, but execution time.

Spring Cache Abstraction: How to Deal With java.util.Optional<T>

We have a lot of code in our code base that's similar to the following interface:
public interface SomethingService {
#Cacheable(value = "singleSomething")
Optional<Something> fetchSingle(int somethingId);
// more methods...
}
This works fine as long we're only using local caches. But as soon as we're using a distributed cache like Hazelcast, things start to break because java.util.Optional<T> is not serializable and thus cannot be cached.
With what I've come up so far to solve this problem:
Removing java.util.Optional<T> from the method definitions and instead checking for the trusty null.
Unwrapping java.util.Optional<T> before caching the actual value.
I want to avoid (1) because it would involve a lot of refactoring. And I have no idea how to accomplish (2) without implementing my own org.springframework.cache.Cache.
What other options do I have? I would prefer a generic (Spring) solution that would work with most distributed caches (Hazelcast, Infinispan, ...) but I would accept a Hazelcast-only option too.
A potential solution would be to register a serializer for the Optional type. Hazelcast has a flexibile serialization API and you can register a serializer for any type.
For more information see the following example:
https://github.com/hazelcast/hazelcast-code-samples/tree/master/serialization/stream-serializer
So something like this:
public class OptionalSerializer implements StreamSerializer<Optional> {
#Override
public void write(ObjectDataOutput out, Optional object) throws IOException {
if(object.isPresent()){
out.writeObject(object.get());
}else{
out.writeObject(null);
}
}
#Override
public Optional read(ObjectDataInput in) throws IOException {
Object result = in.readObject();
return result == null?Optional.empty():Optional.of(result);
}
#Override
public int getTypeId() {
return 0;//todo:
}
#Override
public void destroy() {
}
}
However the solution isn't perfect because this Optional thing will be part of the actual storage. So internally the Optional wrapper is also stored and this can lead to problems with e.g. queries.

ninject 3 render out object context instances

Entity Framework 4, Ninject 3, MVC3
Currently in my web app i have been using a rather rudimentary approach to per request instantiation of an Object Context. So I am experimenting with Ninject, and some old sample code, but I am unsure how to proceed with the following..
Effectively I want to be able in the controller to do the equivalent of: DB_Entities.Current.Albums ... Should i be instantiating a StandardKernel every time?
The sample i was looking at was using the following: MvcApplication.Container.Get(); but in Ninject 3 with the App_Start hookup I dont have access to Container..
My attempt to replicate the above line, is failing at runtime.
using MusicStoreEntities;
using Ninject;
using TestMVC3WithIOC.App_Start;
using System.Data.Objects;
namespace TestMVC3WithIOC.Models
{
public partial class MusicStoreEntities
{
public static MusicStoreEntities Current
{
get
{
using (IKernel kernel = new StandardKernel())
{
return (MusicStoreEntities)kernel.Get<ObjectContext>();
}
}
}
}
}
Also, note, that in App_Start\NinjectWebCommon.cs I have the following modification:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ILogger>().To<NLogger>();
kernel.Bind<ObjectContext>().To<MusicStoreEntities>().InRequestScope();
}
Although a workable solution, it seems ill-advised to pass the entire Kernel into a class, because it tends to obscure the classes actual, specific dependencies. A better approach is to pass a factory dependency into your controller's constructor.
public partial class MusicStoreEntities
{
private readonly IEntitiesFactory _factory;
public MusicStoreEntities(IEntitiesFactory factory)
{
_factory = factory;
}
}
IEntitiesFactory has a simple implementation with a single method GetObjectContext().
(I believe also the "Unit of Work" pattern is popular at the moment, but I can't really speak to that as I haven't used it. Maybe worth looking into.)

Resources