JavaFX IllegalAccessException during FXML load() - javafx-2

I have a dialog window that is invoked by the following code (DialogController is a helper class for using modal dialog windows; it mainly bundles together a controller reference with its window):
void handleServicesEdit(ActionEvent event) throws IOException {
DCServRecEditor sre = DialogController.<DCServRecEditor>loadFXML(
CensusAssistant.RES_FXML_DIALOG_SERVEDIT,
CensusAssistant.RES_STRING_SERVEDIT,
this.getDialog());
sre.setDialogMode(DB.DBEDIT_MODE_EDIT,
tbvService.getItems(),
tbvService.getSelectionModel().getSelectedIndex(),
m_encCal);
sre.showAndWait();
sre.release();
this.updateGUI();
}
I have confirmed that I get an exception during the FXMLLoader.load() method. I have also determined that the error occurs before any code in my initialize() method has a chance to run. Some of the stack trace that I get from load() is here:
java.lang.IllegalAccessException: Class sun.reflect.misc.ReflectUtil
can not access a member of class org.kls.md.censusassistant.DCServRecEditor
with modifiers ""
file:/D:/Documents/NetBeansProjects/CensusAssistant/dist/run1284250063/CensusAssistant.jar!/org/kls/md/censusassistant/fxml/GUIServRecEditor.fxml:13
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:738)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:775)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:180)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:563)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2314)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2131)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2028)
at org.kls.md.censusassistant.DialogController.loadFXML(DialogController.java:63)
at org.kls.md.censusassistant.DCMainEditor.handleServicesEdit(DCMainEditor.java:330)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
Caused by: java.lang.IllegalAccessException: Class sun.reflect.misc.ReflectUtil
can not access a member of class org.kls.md.censusassistant.DCServRecEditor
with modifiers ""
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:95)
at java.lang.Class.newInstance0(Class.java:368)
at java.lang.Class.newInstance(Class.java:327)
at sun.reflect.misc.ReflectUtil.newInstance(ReflectUtil.java:46)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:731)
... 66 more
My class DCServRecEditor is a subclass of DialogController. It is a pretty normal looking FXML controller class:
class DCServRecEditor extends DialogController {
private int m_dialogMode = DB.DBEDIT_MODE_ADD;
private int m_selServ = -1;
private GregorianCalendar m_cal = null;
#FXML // ResourceBundle that was given to the FXMLLoader
private ResourceBundle resources;
#FXML // URL location of the FXML file that was given to the FXMLLoader
private URL location;
#FXML // fx:id="ancMatchSelector"
private AnchorPane ancMatchSelector; // Value injected by FXMLLoader
#FXML // fx:id="ancServEditor"
private AnchorPane ancServEditor; // Value injected by FXMLLoader
#FXML // fx:id="ancServRecEditor"
private AnchorPane ancServRecEditor; // Value injected by FXMLLoader
...
}
I have double and triple checked to make sure that there wasn't a named control in the FXML that didn't also have an instance field in the controller class.
All the instance fields are tagged with #FXML.
The name of the controller class in the FXML is the same as my java file and is properly qualified.
The error occurs before initialize() is called, so I don't think it's anything with initialize(), although I have checked to make sure it is also tagged with #FXML.
The skeleton for my controller class was copied and pasted from Scene Builder ... I've gone back and repasted blocks of stuff from Scene Builder to be sure that there wasn't a control I was missing in my java file.
The error message gives me no specifics about the member it is having its problem with, other than to say it has modifiers "".
I went back to my controller class and made all the members with default access public, and I still get the error.
I don't even know where in my class the problem is coming from.
Anyone have any ideas about what is going wrong here?

Yet another embarrassingly simple problem.
I'm surprised someone didn't jump on this by now.
The problem was in my class DCServRecEditor. Note that the class was declared with default access permission.
JavaFX requires that controller classes be made public.
To be fair to myself, Java's error reporting in this situation is abominable and misleading. The stack trace clearly shows that Java is complaining about being unable to access a member of my class, hence my focus on my instance fields and methods. Java really should have complained that it was the class itself that it could not access and not its members.

Had the same issue. In my case controller was at folder that named with uppercase letter. cast to lowercase solve the problem.

I prefer to declare every method and filed public.

Related

How to use the strategy pattern with managed objects

I process messages from a queue. I use data from the incoming message to determine which class to use to process the message; for example origin and type. I would use the combination of origin and type to look up a FQCN and use reflection to instantiate an object to process the message. At the moment these processing objects are all simple POJOs that implement a common interface. Hence I am using a strategy pattern.
The problem I am having is that all my external resources (mostly databases accessed via JPA) are injected (#Inject) and when I create the processing object as described above all these injected objects are null. The only way I know to populate these injected resources is to make each implementation of the interface a managed bean by adding #stateless. This alone does not solve the problem because the injected members are only populated if the class implementing the interface is itself injected (i.e. container managed) as opposed to being created by me.
Here is a made up example (sensitive details changed)
public interface MessageProcessor
{
public void processMessage(String xml);
}
#Stateless
public VisaCreateClient implements MessageProcessor
{
#Inject private DAL db;
…
}
public MasterCardCreateClient implements MessageProcessor…
In the database there is an entry "visa.createclient" = "fqcn.VisaCreateClient", so if the message origin is "Visa" and the type is "Create Client" I can look up the appropriate processing class. If I use reflection to create VisaCreateClient the db variable is always null. Even if I add the #Stateless and use reflection the db variable remains null. It's only when I inject VisaCreateClient will the db variable get populated. Like so:
#Stateless
public QueueReader
{
#Inject VisaCreateClient visaCreateClient;
#Inject MasterCardCreateClient masterCardCreateClient;
#Inject … many more times
private Map<String, MessageProcessor> processors...
private void init()
{
processors.put("visa.createclient", visaCreateClient);
processors.put("mastercard.createclient", masterCardCreateClient);
… many more times
}
}
Now I have dozens of message processors and if I have to inject each implementation then register it in the map I'll end up with dozens of injections. Also, should I add more processors I have to modify the QueueReader class to add the new injections and restart the server; with my old code I merely had to add an entry into the database and deploy the new processor on the class path - didn't even have to restart the server!
I have thought of two ways to resolve this:
Add an init(DAL db, OtherResource or, ...) method to the interface that gets called right after the message processor is created with reflection and pass the required resource. The resource itself was injected into the QueueReader.
Add an argument to the processMessage(String xml, Context context) where Context is just a map of resources that were injected into the QueueReader.
But does this approach mean that I will be using the same instance of the DAL object for every message processor? I believe it would and as long as there is no state involved I believe it is OK - any and all transactions will be started outside of the DAL class.
So my question is will my approach work? What are the risks of doing it that way? Is there a better way to use a strategy pattern to dynamically select an implementation where the implementation needs access to container managed resources?
Thanks for your time.
In a similar problem statement I used an extension to the processor interface to decide which type of data object it can handle. Then you can inject all variants of the handler via instance and simply use a loop:
public interface MessageProcessor
{
public boolean canHandle(String xml);
public void processMessage(String xml);
}
And in your queueReader:
#Inject
private Instance<MessageProcessor> allProcessors;
public void handleMessage(String xml) {
MessageProcessor processor = StreamSupport.stream(allProcessors.spliterator(), false)
.filter(proc -> proc.canHandle(xml))
.findFirst()
.orElseThrow(...);
processor.processMessage(xml);
}
This does not work on a running server, but to add a new processor simply implement and deploy.

How to override protected methods of a class of MVCResourceCommand in liferay?

I want to override a protected method in the class ExportArticleMVCResourceCommand which extends theBaseMVCResourceCommand class.
I want to convert journal article's to pdf in liferay 7 . I have written this functionality in its own method and wish to call that method in the doServeResource(...) method. But as doServeResource() is protected, I am not able to call it on a button submit. Therefore, I want to ask how to override this doServeResource() method in liferay 7.
Dissecting the problem
Liferay 7 is an open source Java platform an as such the best way to troubleshoot (absent any documentation) is to first at the code. You will notice that theExportArticleMVCResourceCommand class extends BaseMVCResourceCommand. In the ExportArticleMVCResourceCommand class you can see that the doServeResource method overrides it's parent's doServeResource method. In BaseMVCResourceCommand there are several things to note.
It is an abstract class
There is protected abstract void doServeResource method with no implementation.
The serveResource method simply calls the doServeResource
Piecing it together
So you want to override the doServeResource method in the ExportArticleMVCResourceCommandclass because that method does not work when the "targeted extension" is of type PDF (purportedly). You cannot override the doServeResource by extending or implementing any *MVCResourceCommand class or interface because it's either protected (and your OSGi component override is bundled separately) or in the case of MVCResourceCommand interface it doesn't exist.
Solution
Remember the doServeResource method is simply called by the serveResource method in ExportArticleMVCResourceCommand, and the serveResource method is public in both the MVCResourceCommand interface and BaseMVCResourceCommand class. Therefore to override the doServeResource method you simply need to create your own OSGi component with that appropriate annotations, have it override the serveResource method, and do not the referened serveResource method at the end of your own.
#Component(
property = {
"javax.portlet.name=" + JournalPortletKeys.JOURNAL,
"mvc.command.name=exportArticle"
},
service = MVCResourceCommand.class
public class CustomExportArticleMVCResourceCommand implements MVCResourceCommand {
#Override
public boolean serveResource
(ResourceRequest resourceRequest, ResourceResponse resourceResponse) {
// Call your custom method here
// ExportArticleUtil.sendFile("pdf", resourceRequest, resourceResponse);
}
#Reference(target = "(component.name=com.liferay.journal.web.internal.portlet.action.ExportArticleMVCResourceCommand)")
protected MVCResourceCommand mvcResourceCommand;
}

Mule Issue : More than one JAXBContext

We are facing one issue in our Mule Adapter related to JAXB context, needed some opinion on the same
We are using xpath to evaluate some expressions in the choice blocks in our adapter like below for instance,
<choice doc:name="Choice">
<when expression="//env:abc/env:Body/ref:dataelement/ref:/ref:element" evaluator="xpath">
......
</when>
Now, this works perfectly fine in our application but the problem arises when one of other team uses this Adapter as a jar in their application.
When they try to use this adapter, they are getting below error,
Message : More than one object of type class javax.xml.bind.JAXBContext registered but only one expected.
Type : org.mule.api.registry.RegistrationException
Code : MULE_ERROR--2
JavaDoc : http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/registry /RegistrationException.html.
After debugging with the help of loggers etc, we narrowed down to the choice block used above which is causing this particular issue. Also, googled a bit and found one of the posts pointing out the same issue.
Also, to confirm we commented out the choice block having xpath expression and the flow went ahead but broke again where was xpath used in some other way.
https://www.mulesoft.org/jira/browse/MULE-5926
Can anyone please suggest any suitable workaround to resolve this issue?
I agree with you. It is an unresolved issue in Mule.
One solution we have implemented is not define the jaxb context in the config you are providing in the jar file.
Along with the jar file, give instructions to the end application using it, to include the JAXB packages in their JAXB Context object definition.
This way there will be only one JAXB context and it will work smoothly.
Hope this helps.
This is a bit late however the solution that worked was
<mulexml:jaxb-context name=“JAXB_Context“ packageNames=“org.example.test1:org.example.test2“ doc:name=“JAXB Context1“ />
Please note that there must be no space between package names.
Thanks to: http://dominikbial.de/quicktipp-working-with-more-than-one-package-name-in-a-jaxb-context-config-in-mule-esb/
As of now we cannot add more than one JAXBContext in mule. As an alternative you can write your custom transformer.
I implemented something like
public interface MyAppJaxbObj2XmlComponent<I,O> extends
MyAppComponent<I,O>,Callable {
public O marshal(I input) throws Exception;
}
Abstart transformer
public abstract class AbstractMyAppJaxbObj2XmlComponent<I,O> implements
MyAppJaxbObj2XmlComponent<I,O>{
private Class<I> inputType;
public AbstractMyAppJaxbObj2XmlComponent(){
this.inputType = (Class<I>) new TypeToken<I>(getClass())
{}.getRawType();
}
public AbstractMyAppJaxbObj2XmlComponent(Class<I> type){
this.inputType = type;
}
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
I input = eventContext.getMessage().getPayload(inputType);
O output = marshal(input);
return output;
}
}
Your flow transformer this will load your needed jaxb during startup.
#Component
public class MyFlowJaxbObj2XmlComponent extends
AbstractMyAppJaxbObj2XmlComponent<RequestPayloadType,String> {
#PostConstruct
public void init() {
//Load your schema during startup
}
}
You can also implement a fluid interface as an alternative for this.

Bootstrap Javafx 2.0 with Weld

I am trying to bootstrap a small javafx application using Weld-SE. I was able to run the application if I remove the #Inject annotation on the Menubar and instantiate it manually.
But the moment I add #Inject, the application throws exception. Listed below are the injection point and the Producer method. This is all the configuration I did, am I missing something ?
Injection Point
#Inject MenuBar menuBar
Class with producer method
public class ComponentProducer {
#Produces
public MenuBar createMenuBar(){
return new MenuBar();
}
}
Exception
491 [JavaFX Application Thread] INFO org.jboss.weld.Bootstrap - WELD-000101 Transactional services not available. Injection of #Inject UserTransaction not available. Transactional observers will be invoked synchronously.
8868 [JavaFX Application Thread] WARN org.jboss.interceptor.model.InterceptionTypeRegistry - Class 'javax.ejb.PostActivate' not found, interception based on it is not enabled
8868 [JavaFX Application Thread] WARN org.jboss.interceptor.model.InterceptionTypeRegistry - Class 'javax.ejb.PrePassivate' not found, interception based on it is not enabled
Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:399)
at com.sun.javafx.application.LauncherImpl.access$000(LauncherImpl.java:47)
at com.sun.javafx.application.LauncherImpl$1.run(LauncherImpl.java:115)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.NullPointerException
at net.sourceforge.squirrel_sql.client.MainScene.<init>(MainScene.java:26)
at net.sourceforge.squirrel_sql.client.FXApplication.startup(FXApplication.java:176)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:304)
at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:54)
at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:163)
at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:298)
at org.jboss.weld.introspector.jlr.WeldMethodImpl.invokeOnInstance(WeldMethodImpl.java:200)
at org.jboss.weld.introspector.ForwardingWeldMethod.invokeOnInstance(ForwardingWeldMethod.java:59)
at org.jboss.weld.injection.MethodInjectionPoint.invokeOnInstanceWithSpecialValue(MethodInjectionPoint.java:194)
at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:241)
at org.jboss.weld.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:216)
at org.jboss.weld.manager.BeanManagerImpl.notifyObservers(BeanManagerImpl.java:654)
at org.jboss.weld.manager.BeanManagerImpl.fireEvent(BeanManagerImpl.java:647)
at org.jboss.weld.manager.BeanManagerImpl.fireEvent(BeanManagerImpl.java:641)
at org.jboss.weld.event.EventImpl.fire(EventImpl.java:93)
at net.sourceforge.squirrel_sql.client.Main.start(Main.java:180)
at com.sun.javafx.application.LauncherImpl$5.run(LauncherImpl.java:315)
at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:174)
at com.sun.javafx.application.PlatformImpl$3.run(PlatformImpl.java:141)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication$2$1.run(GtkApplication.java:79)
... 1 more
ShaggyInjun, you refer to the Initializable interface which indicates you were trying to integrate with the FXMLLoader. All of the information below assumes you are using FXML for your interface definition and only discusses issues around injecting values into FXML controllers.
The FXMLLoader has the concept of a controller factory, which you should use to integrate the controller instantiation with your dependency injection system. There is a brief discussion of controller factories in Oracle's Mastering FXML Tutorial. Andy demonstrates definition of such a factory for Guice in his blog and there is a comprehensive integration of Guice in FXML on github.
For Weld you will need to implement a similar controller factory callback mechanism to realize the dependency injection functionality which Weld provides. The article by Matthieu Brouillard that you linked in a comment FXML & JavaFX—Fueled by CDI & JBoss Weld would seem to provide all of the information you need to both initialize Weld and interface Weld into the FXMLLoader controller factory mechanism. Specifically, the following code is the Weld equivalent of Andy Till's FXML based injection mechanism:
public class FXMLLoaderProducer {
#Inject Instance<Object> instance;
#Produces public FXMLLoader createLoader() {
FXMLLoader loader = new FXMLLoader();
loader.setControllerFactory(new Callback<Class<?>, Object>() {
#Override public Object call(Class<?> param) {
return instance.select(param).get();
}
});
return loader;
}
}
Even when an FXMLoader controller factory is used, I believe it is the FXMLLoader that is instantiating the controller. So in those cases, you should not make of annotations like #PostConstruct because they only apply when the dependency injection system is maintaining the lifecycle of the object - and that is not the case if the FXMLLoader creates the controller.
There is one other alternative, and that it is to explicitly set the controller to be used by the FXMLLoader using setController. This would allow you to have your dependency injection system instantiate (and inject into) controllers using whatever means it wishes and then you could subsequently pass the instantiated controller to your FXMLLoader. In such cases anotations like #PostConstruct should work as the dependency injection system is now maintaining the objects lifecycle (and #PostConstruct would be invoked by the dependency injection system after the Controller has been created and before you pass the Controller through to the FXMLLoader).
I'll post Andy's Guice based solution here as it is a small and simple example of how similar injection is accomplished in Guice (in case his blog goes offline):
class GuiceControllerFactory implements Callback<Class<?>, Object> {
private final Injector injector;
public GuiceControllerFactory(Injector anInjector) {
injector = anInjector;
}
#Override public Object call(Class<?> aClass) {
return injector.getInstance(aClass);
}
}
Is it because you are trying to use menuBar in the constructor or initialiser block?
If so, try using Initializable and using them in initialize.
EJB documentation states that the method annotated with #PostConstruct will be called after the injections are done, and that this is the method to expect variable injections.
#PostConstruct
The PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization.
Expecting the variable to be initialized inside the initialize does seem to work however.
According to the Initializable documentation, initialize is Called to initialize a controller after its root element has been completely processed.
Initializable
Order of call for initialize and #PostConstruct
I think it is safe to understand that the calling of initialize does not have anything to do with object construction. Instead, initialize is called when the root of the current node graph has been completely processed, so one can process things like event handlers etc. Something on the lines of document.onload or jQuery(document).ready(). If you were to try to attach event handlers before object graph is ready, there is a pretty good chance to see a null pointer because the node is not the object graph yet making it impossible to attach an event handler.
So, you'd instantiate an object (either directly or via injecting) before you load it to the scene-graph. Therefore #PostConstruct gets called before the initialize. But, if you instantiate the object directly then the responsibility to call the method annotated #PostConstruct falls on you, otherwise that post processing will not happen.
Conclusion:
It is safe to assume that initialize is always called after the method annotated with #PostConstruct.
EDIT
#Jewelsea has pointed out a few assumptions that I have not listed above. So here it goes, the circumstances where the above worked for me.
Using FXML files for views.
Controller name specified inside the fxml file.

Monotouch - global variables

How can I store/access global variables within a monotouch application? I am retrieving the GPS Location (using Monotouch.CoreLocation.CLLocationManager) during the FinishedLaunching method of the AppDelegate. How do I then access that information from a property on that appdelegate (from a view, for example)? Or is there another preferred method for global data?
UPDATE:
I just want to grab the location once, at startup, then have access to that location from all my views. Here's my AppDelegate - I'd like to access the locationManager field from a view. I can certainly add a property to do so, but I guess my question is "How do I access that property from a view (or can I even, considering it's a delegate)"?
// The name AppDelegate is referenced in the MainWindow.xib file.
public partial class AppDelegate : UIApplicationDelegate
{
private CLLocationManager locationManager = new CLLocationManager();
// This method is invoked when the application has loaded its UI and its ready to run
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
locationManager.Delegate = new GpsLocationManagerDelegate();
locationManager.StartUpdatingLocation();
window.AddSubview (navController.View);
window.MakeKeyAndVisible ();
return true;
}
// This method is required in iPhoneOS 3.0
public override void OnActivated (UIApplication application)
{
}
}
Generally, most people will tell you to avoid global variables and instead pass what you need into the delegate. (I would agree with that sentiment).
However, you can use a singleton class, a service locator, or a static class with static fields/properties to get global variable-like behavior in C# (or any other Dotnet/Mono compatible language).
In your case, I presume you wrote the class GpsLocationManagerDelegate yourself. If so, you can change the constructor to take parameters for the necessary information (the view, a reference to the app delegate, and/or a reference to the location manager) and store it in your GpsLocationManagerDelegate instance. If you didn't write GpsLocationManagerDelegate yourself and it's not declared sealed, subclass it and create an appropriate constructor.
This example seems close to what you're after: http://www.conceptdevelopment.net/iPhone/MapKit01/Main.cs.htm
You should make locationManager a public property, then you can access it from most places in the app like so:
CLLocationManager LocationManager {get;set;}
AppDelegate delegateReference =
(AppDelegate)UIApplication.SharedApplication.Delegate;
then access the locationmanager anywhere in code via:
delegateReference.LocationManager
Generally, you should setup such things as singletons, setup within the AppDelegate.

Resources