JavaFX call default method in SceneBuilder (FXML) - javafx

How can I call a interface default method in the FXML - scenebuilder.
I have an Interface like:
public interface Startable
{
default void handleStart(){...}
}
and a controller like:
BlaController implements Startable {...}
but if I call the method "handleStart()" in the fxml, I get the following exception:
javafx.fxml.LoadException: Error resolving onMouseClicked='#handleStart', either the event handler is not in the Namespace or there is an error in the script.
Is there a possibility to call the method?

It is not possible to implement an interface default method and use it in FXML, apparently FXMLLoader uses reflection and doesn't find the method in the class implementation. You must override the method in the Controller class and then call the default method.
The interface remains the same.
public interface Startable {
default void handleStart(){...}
}
This is how you can call the super implementation
public class BlaController implements Startable {
#Override
#FXML
void handleStart(){
Startable.super.handleStart();
}
}
Hope it helps...

I have created a feature request. Maybe there will be a straight forward solution to this question in the future: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8259916

Related

How to use ResourceProcessorHandlerMethodReturnValueHandler in a spring-hateos project

When using spring-data-rest there is a post processing of Resource classes returned from Controllers (e.g. RepositoryRestControllers). The proper ResourceProcessor is called in the post processing.
The class responsible for this is ResourceProcessorHandlerMethodReturnValueHandler which is part of spring-hateoas.
I now have a project that only uses spring-hateoas and I wonder how to configure ResourceProcessorHandlerMethodReturnValueHandler in such a scenario. It looks like the auto configuration part of it still resides in spring-data-rest.
Any hints on how to enable ResourceProcessorHandlerMethodReturnValueHandler in a spring-hateoas context?
I've been looking at this recently too, and documentation on how to achieve this is non-existent. If you create a bean of type ResourceProcessorInvokingHandlerAdapter, you seem to lose the the auto-configured RequestMappingHandlerAdapter and all its features. As such, I wanted to avoid using this bean or losing the WebMvcAutoConfiguration, since all I really wanted was the ResourceProcessorHandlerMethodReturnValueHandler.
You can't just add a ResourceProcessorHandlerMethodReturnValueHandler via WebMvcConfigurer.addReturnValueHandlers, because what we need to do is actually override the entire list, as is what happens in ResourceProcessorInvokingHandlerAdapter.afterPropertiesSet:
#Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
// Retrieve actual handlers to use as delegate
HandlerMethodReturnValueHandlerComposite oldHandlers = getReturnValueHandlersComposite();
// Set up ResourceProcessingHandlerMethodResolver to delegate to originally configured ones
List<HandlerMethodReturnValueHandler> newHandlers = new ArrayList<HandlerMethodReturnValueHandler>();
newHandlers.add(new ResourceProcessorHandlerMethodReturnValueHandler(oldHandlers, invoker));
// Configure the new handler to be used
this.setReturnValueHandlers(newHandlers);
}
So, without a better solution available, I added a BeanPostProcessor to handle setting the List of handlers on an existing RequestMappingHandlerAdapter:
#Component
#RequiredArgsConstructor
#ConditionalOnBean(ResourceProcessor.class)
public class ResourceProcessorHandlerMethodReturnValueHandlerConfigurer implements BeanPostProcessor {
private final Collection<ResourceProcessor<?>> resourceProcessors;
#Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof RequestMappingHandlerAdapter) {
RequestMappingHandlerAdapter requestMappingHandlerAdapter = (RequestMappingHandlerAdapter) bean;
List<HandlerMethodReturnValueHandler> handlers =
requestMappingHandlerAdapter.getReturnValueHandlers();
HandlerMethodReturnValueHandlerComposite delegate =
handlers instanceof HandlerMethodReturnValueHandlerComposite ?
(HandlerMethodReturnValueHandlerComposite) handlers :
new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
requestMappingHandlerAdapter.setReturnValueHandlers(Arrays.asList(
new ResourceProcessorHandlerMethodReturnValueHandler(delegate,
new ResourceProcessorInvoker(resourceProcessors))));
return requestMappingHandlerAdapter;
}
else return bean;
}
}
This has seemed to work so far...

what is the equivalence of contextDestroyed() in ServletContainerInitializer?

I have to create a class that implements ServletContextListener to add an event during the initialization or the shutdown of Tomcat. However, the class has to be located in a jar file inside WEB-INF/lib. After doing some readings, I found out that this is not possible, and the alternative is to use ServletContainerInitializer. However, only onStartup() method is available.
Is there any other alternatives where I can also add an event during the shutdown or destruction of the web application?
I am using Tomcat 8 and Java 8 btw.
Let your ServletContainerInitializer programmatically add a ServletContextListener which in turn does the desired job in its contextDestroyed().
servletContext.addListener(YourServletContextListener.class);
Not sure how you tested your code. But this the ServletContextListener works fine for me on Tomcat 8.5.5. Just try this code, no need to put this to separate JAR file.
#WebListener
public class AppContextListener implements ServletContextListener{
Logger log = LoggerFactory.getLogger(AppContextListener.class);
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
log.info("### Context is destroyed ###");
}
}

OpenJDK #Override missing issue

Is there any case that in OpenJDK 1.7.0_45, the Derived class override the base class' method, but without #Override annotation, and in runtime, the instance of derived class will invoke the base class' method?
class Base {
public f() {
}
}
class Derived {
public f() {
}
}
the Derived class's method does not call the base class's method.
BTW, the same code run well on Oracle JDK1.7.
No, as you can see in the Javadocs, #Override has SOURCE retention and only works as a compile time safeguard. The bytecode will not be any different. See also How to identify override method in Java byte code?
I am not sure if I understand the question correctly, but the override-annotation does not control which method is invoked at runtime.
So sure you can invoke the baseclass-method. Just invoke super.f().

Using Spring AOP 3.1.0 to set service instance using method argument

Hi i am new to Annotation and Spring AOP. below is what i am trying to achieve
public interface Service {
public void process(String ServiceName, Bean bean);
}
public class ServiceImpl1 implements Service{
public void process(String ServiceName, Bean bean) {
/// do something here
}
}
public class ServiceImpl2 implements Service{
public void process(String ServiceName, Bean bean) {
/// do something here
}
}
from other class i would be calling something like
...
public void doSomething(String serviceName, Bean bean){
service.process("ServiceImpl1", bean);
}
...
I can achieve the same by using AroundAdvice and Before advice and intercepting my doSomething method and then instantiate the service object after reading the serviceName.
I there is a better approach for this?
I just need a direction and then i will figure this out.
Thanks
Well, I am guessing what you want to do is have a Before advice that takes the passed in service name, creates an object of appropriate class, then calls the appropriate method on that newly created object. It seems like, to me, you are really looking for more of a Factory pattern, but trying to use AOP to accomplish it.
If you took the Factory pattern, you would create a class called ServiceFactory, which takes some parameters and returns the correct Service implementation for those parameters. You calling code would simply use the Factory to get the right Service at runtime.
Another approach, if you want to stick with more of a DI pattern, might be to create a wrapper class that serves as the "conductor". This might have a Map of service names to Service implementation. You could then inject this wrapper into your code, and even inject the Map into the wrapper. Your calling code would call methods on the wrapper, which would locate the correct, singleton implementation and aggrigate the call to it.
I just feel that using AOP for this is asking for trouble.
You can inject the service impl class using the spring #Autowire annotation. Since u have 2 implementation classes, you can use qualifier to specify which impl needs to b injected.

#PostConstruct not working in JBoss 5

I have a servlet that I cannot change (com.sun.jersey.spi.container.servlet.ServletContainer of Jersey RS) . What I can do is create a subclass of it. However, I needed that when the servlet is initialized it runs one function of my subclass. I cannot override the init method because it has the Jersey code.
I tried to use the annotation #PostConstruct on a method to make it run after initialization but it does not work (but it does work under Tomcat 6).
In web.xml the class is set to run on startup.
You should be able to subclass ServletContainer, override init, invoke the superclass method then perform your own logic, i.e.
public class MyServletContainer extends ServletContainer {
public void init() throws ServletException {
super.init();
//... perform custom initialization logic here
}
}
Check if you have some of these jars "commons-annotation.jar, geronimo-annotation_1.1_spec, jboss-annotations-api_1.1_spec" in your webapp lib and remove.

Resources