Deserializing JavaFX properties with yWorks and Java Reflection API - javafx

I am implementing a process managing tool and I am using (for research purposes) the yWorks library "yFiles for JavaFX".
I am doing fine so far, but that one thing just sets a show stopper for me for 2 days now:
Since im using JavaFX beans and their properties to edit and display my data, I had to implement some kind of custom serializer:
graphMLIOHandler.addHandleSerializationListener(
(source, hsArgs) -> {
// Only serialize items that are of the specific type.
if (hsArgs.getItem() instanceof StringProperty) {
//serialize
} else if (hsArgs.getItem() instanceof IntegerProperty) {
//serialize
} else if (hsArgs.getItem() instanceof DoubleProperty) {
//serialize
} else if (hsArgs.getItem() instanceof SimpleListProperty) {
//serialize
}
});
But when loading the file i was writing I get a IllegalArgumentException. yFiles wants to invoke a setValue method and is throwing a DeserializationNotSupportedException. So I tried to implement a addHandleDeserializationListener. Didn't work. Then I implemented MarkupExtensions for my Project class. Nothing changed. Giving you guys the code for the latter implementation and hoping that somebody finds what i missed. Im kinda on my last resort here..
CustomGraphController:
public class CustomGraphController extends GraphControl{
private IGraph graph ;
private GraphMLIOHandler graphMLIOHandler;
public CustomGraphController(){
super();
graph = this.getGraph();
graph.setTag(new Project());
}
}
Project.class:
#GraphML(markupExtensionConverter = ProjectMEC.class)
public class Project {
SimpleListProperty<ParameterOccurrence> generalParameters;
public Project(){
generalParameters = new SimpleListProperty<>(FXCollections.observableArrayList());
}
public ObservableList<ParameterOccurrence> getGeneralParameters() {
return generalParameters;
}
public SimpleListProperty<ParameterOccurrence> generalParametersProperty() {
return generalParameters;
}
public void setGeneralParameters(ObservableList<ParameterOccurrence> generalParameters) {
this.generalParameters.set(generalParameters);
}
}
ProjectME.class
public class ProjectME extends MarkupExtension {
ArrayList<ParameterOccurrence> generalParameters;
public ProjectME() {
super();
}
public ArrayList<ParameterOccurrence> getGeneralParameters() {
return generalParameters;
}
public void setGeneralParameters(ArrayList<ParameterOccurrence> generalParameters) {
this.generalParameters = generalParameters;
}
#Override
public Object provideValue(ILookup iLookup) {
Project ret = new Project();
ret.getGeneralParameters().addAll(generalParameters);
return ret;
}
}
ProjectMEC.class:
public class ProjectMEC implements IMarkupExtensionConverter {
#Override
public boolean canConvert(IWriteContext iWriteContext, Object o) {
return o instanceof Project;
}
#Override
public MarkupExtension convert(IWriteContext iWriteContext, Object o) {
ProjectME extension = new ProjectME();
ObservableList<ParameterOccurrence> temp = FXCollections.observableArrayList(((Project)o).getGeneralParameters());
extension.getGeneralParameters().addAll(temp);
return extension;
}
}
Stacktrace:
Caused by: com.yworks.yfiles.graphml.DeserializationNotSupportedException: Error parsing property GeneralParameters: argument type mismatch
at com.yworks.yfiles.graphml.XamlReader.b(Unknown Source)
at com.yworks.yfiles.graphml.XamlReader.c(Unknown Source)
... 83 more
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.yworks.yfiles.graphml.PropertyInfo.setValue(Unknown Source)
at com.yworks.yfiles.graphml.Property.setValue(Unknown Source)
... 85 more
My guess was that the GeneralParameters property (even though I
tryed to implement a addHandleDeserializationListener for
SimpleListProperty) somehow need this MarkupExtension. But the
stacktrace stayed exactly the same and since the reflection API and
the closed source stuff I cant find, where exactly the Exception is
thrown...
ANY idea, whats happending?

Related

PowerMockito failing to create an instance of a class which has anonymous block

I just converted our application code into simple classes to express the problem concisely. Our use case contains a class which internally uses some helper classes with static methods which needs to be mocked. So, planned to use PowerMockito. No issues with this part, however we have one class where we have an anonymous block inside one of the methods. When we try to create an instance of this class, PowerMockito fails with a very vague error. Tried spending few hours to resolve the issue without any luck.
public abstract class AbstractClass {
public abstract void methodOne(String arg);
public void methodTwo()
{
System.out.println("In method two");
}
}
public class StaticMethod {
public static String someStaticMethod()
{
System.out.println("in static method");
return "static";
}
}
public class AbstractClassCaller {
public AbstractClassCaller()
{
StaticMethod.someStaticMethod();
// The following piece of code is the problematic block
AbstractClass abstractClassInstance = new AbstractClass(){
public void methodOne(String methodArg)
{
System.out.println("In Method One");
}
};
}
}
#Test
#PrepareForTest({AbstractClassCaller.class,StaticMethod.class})
public class AbstractClassCallerTest {
#Test
public void test() throws Exception
{
PowerMockito.mockStatic(StaticMethod.class);
PowerMockito.when(StaticMethod.someStaticMethod()).thenReturn(
"PowerStatic");
// This is the code which triggers the exception
AbstractClassCaller instance = new AbstractClassCaller();
}
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
}
The above junit class fails with the following exception:
org.powermock.reflect.exceptions.ConstructorNotFoundException: Failed to lookup constructor with parameter types [ com.oracle.oal.seaas.AbstractClassCaller ] in class com.oracle.oal.seaas.AbstractClassCaller$1.
at com.oracle.oal.seaas.AbstractClassCallerTest.test(AbstractClassCallerTest.java:21)
Caused by: java.lang.NoSuchMethodException: com.oracle.oal.seaas.AbstractClassCaller$1.<init>(com.oracle.oal.seaas.AbstractClassCaller)
at com.oracle.oal.seaas.AbstractClassCallerTest.test(AbstractClassCallerTest.java:21)
// the following anonymous block in AbstractClassCaller is causing the issue:
AbstractClass abstractClassInstance = new AbstractClass(){
public void methodOne(String methodArg)
{
System.out.println("In Method One");
}
};
Any ideas on how to fix this issue?

InvocationTargetException when binding to custom class run by JavaFX Concurrent Task

I'm getting InvocationTargetException and NullPointerException when attempting to bind to custom class run by Task. I have working examples of binding to library classes ObeservableList, Long, Integer etc but now need to bind to values of custom class. I created TaskOutput class that includes StringProperty for binding purposes as follows:
public class TaskOutput {
private final StringProperty textValue = new SimpleStringProperty();
public TaskOutput(String textValue) {
this.textValue.set(textValue);
}
public String getTextValue() {
return textValue.get();
}
public void setTextValue(String textValue) {
this.textValue.set(textValue);
}
public final StringProperty nameProperty() {
return this.textValue;
}
}
This was tested successfully as follows:
TaskOutput newTaskOutput = new TaskOutput("Text of TaskOutput");
value.textProperty().bind(newTaskOutput.nameProperty());
System.out.println(value.getText());
Now I'm attempting to run a Task that provides a TaskOutput as its Value Property. The class extending Task is as follows:
public class NameGeneratorTask extends Task<TaskOutput> {
private int counter;
TaskOutput taskOutput;
public NameGeneratorTask() {
this.counter = 10;
taskOutput = new TaskOutput("Test String from output");
}
#Override
protected TaskOutput call() {
this.updateTitle("Name Generator");
do {
if (this.isCancelled())
{
break;
}
updateValue(taskOutput);
counter--;
}
while (counter > 0);
return taskOutput;
}
}
The Application class instantiates a Task Object and then passes it to the WorkerState class as follows:
public class FxConcurrentBespokeObjectVersion2 extends Application
{
NameGeneratorTask task;
public static void main(String[] args)
{
Application.launch(args);
}
#Override
public void start(final Stage stage)
{
task = new NameGeneratorTask();
WorkerState pane = new WorkerState(task);
}
}
The WorkerState class attempts to bind to the nameProperty of the TaskOutput being run by the Task as follows:
public class WorkerState
{
private final TextArea value = new TextArea("");
public WorkerState(Worker<TaskOutput> worker)
{
value.textProperty().bind(worker.valueProperty().get().nameProperty());
}
}
Program compiles at this point but this exception is generated at runtime:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.lang.NullPointerException
at OriginalExBespokeObjectVersion2.WorkerState.<init>(WorkerState.java:21)
at OriginalExBespokeObjectVersion2.FxConcurrentBespokeObjectVersion2.start(FxConcurrentBespokeObjectVersion2.java:29)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
... 1 more
Exception running application OriginalExBespokeObjectVersion2.FxConcurrentBespokeObjectVersion2
As I mention, I've already managed to bind to library classes so don't see why I can't bind to my custom class in same scenario (though I can bind to it fine in standalone example above). Can anyone suggest please?
In case anyone wonders, 'Why not use Task (String) ?'... The objective of my program is to return several properties from the same Task (String was just 1 example), hence needing to encapsulate the properties in a custom class.
Yes, both worker.valueProperty() and worker.valueProperty().get() return null at this point. Earlier I tried this:
value.textProperty().bind(
new When(worker.valueProperty().isNull()).then("Unknown")
.otherwise(worker.valueProperty().get().nameProperty()));
...but the outcome was the same. It get that being null is a problem but I can't see how it's different to before when I managed to bind fine with a library type such as Long. In that case this line worked fine:
value.textProperty().bind(worker.valueProperty().asString());
I checked and in the case of property type being Long worker.valueProperty() was also null at time of bind and it wasn't an issue.
Update:
I checked the worker.valueProperty().asString() used in the working example and saw it was returning StringBinding so I modified my custom class to do the same as follows:
public class TaskOutput {
private final String textValue = new String("Start value");
public TaskOutput() {
}
public StringBinding getStringBinding() {
return new StringBinding() {
#Override
protected String computeValue() {
return textValue;
}
};
}
}
I've deployed this in WorkerState class as follows:
value.textProperty().bind(worker.valueProperty().get().getStringBinding());
But still it's the same result, InvocationTargetException and Runtime Exception. Not sure what else I can try?

Java 1.8 overridden equals() not called by Collection removeAll()

on my IDE (eclipse neon) i m running jre 1.8. As you can see in the snippet code below i developed My Custom class overriding the equals method. That s cause i want to use my overridden version when i execute the removeAll method from a Set of my custom class.
Looking inside the jdk source code it's possible to verify that removeAll method uses the contains method which in turn uses the equals method of the Object class.
public class MyClass {
private String connectionID;
public MyClass (){
...
}
#Override
public boolean equals(Object obj) {
if (obj instanceof MyClass ){
if (((MyClass )obj).getConnectionID().equalsIgnoreCase(this.getConnectionID())){
return true;
}
}
return false;
}
...
}
public class MyClassContainer{
private Set<MyClass> classes = new HashSet<>();
public Set<MyClass> getClasses () {
return this.classes ;
}
}
public class Main (){
private void method(MyClassContainer contClass) {
if (true){
Set<MyClass> temp = some valid Set;
temp.removeAll(contClass.getClasses());
}
}
Launching this code i m realizing that the overridden equals method is never called.
What is it wrong?
Thanks
For it to work correctly, you need to override hashCode as well:
#Override
public int hashCode() {
return Objects.hash(getConnectionID());
}

java.lang.IllegalStateException: ServletConfig has not been initialized

I am trying to create an UI component that allow the user to customize the timeout of sessions. So I created a servlet as below:
public class SessionTimeoutServlet extends AbstractBaseServlet {
private static final long serialVersionUID = 2567293974465204729L;
public static final String REQUEST_TIMEOUT_PARAMETR_NAME = "timeout";
private static final String TIMEOUT_TYPE_INIT_PARAMETER_NAME = "timeoutType";
private static final String WEB_TYPE_TIMEOUT = "web";
private static final String WEBSERVICE_TYPE_TIMEOUT = "webService";
#EJB(mappedName = SessionSettingsRemote.BEAN_NAME)
private SessionSettingsRemote sessionSettingsBean;
#PostConstruct
public void initTimeout() {
try {
String timeoutType = getServletContext().getInitParameter(TIMEOUT_TYPE_INIT_PARAMETER_NAME);
if (WEBSERVICE_TYPE_TIMEOUT.equals(timeoutType)) {
setCustomTimeout(sessionSettingsBean.getSessionSettingsDTO().getWebServiceSessionTimeoutInterval());
} else if (WEB_TYPE_TIMEOUT.equals(timeoutType)) {
setCustomTimeout(sessionSettingsBean.getSessionSettingsDTO().getWebSessionTimeoutInterval());
} else {
setCustomTimeout(30);
}
} catch (ApplicationException e) {
setCustomTimeout(30);
}
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int timeout = Integer.parseInt(request.getParameter(REQUEST_TIMEOUT_PARAMETR_NAME));
setCustomTimeout(timeout);
}
public static void setCustomTimeout(int customTimeout) {
SessionManagerListener.setCustomTimeout(customTimeout);
}
}
However, when I deploy this on GlassFish, I get below exception.
Caused by: java.lang.IllegalStateException: ServletConfig has not been initialized
at javax.servlet.GenericServlet.getServletContext(GenericServlet.java:199)
at com.accedian.ems.uiapplication.server.servlets.SessionTimeoutServlet.initTimeout(SessionTimeoutServlet.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl$3.run(InjectionManagerImpl.java:766)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.invokeLifecycleMethod(InjectionManagerImpl.java:760)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:531)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:141)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:127)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:347)
at com.sun.enterprise.web.WebContainer.createServletInstance(WebContainer.java:991)
at com.sun.enterprise.web.WebModule.createServletInstance(WebModule.java:2130)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1404)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1381)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5732)
I have used getServletConfig() before getServletContext() but it was null. So why is my config and context are not properly set ?
Servlets predate managed beans and annotations and all the fancy stuff you see since Java EE 6. Previously, you have to explicitly implement a predefined abstract/template method in order to perform a task at a certain moment in the lifecycle.
For servlets, in order to hook on its initialization the same way you'd use #PostConstruct on a "normal" managed bean, you have to override the predefined GenericServlet#init() method.
#Override
public void init() {
// ...
}
The getServletContext() will be available there.
If you pay attention to the GenericServlet javadoc, you'll notice that there's also an init(ServletConfig). It's however strongly recommended to not use that method, but use init() instead. The default implementation of init(ServletConfig) namely takes care that the ServletContext is properly set. You'd have to mind calling super.init(config) to not make the same mistake. As a historical note, see that the canonical name of a #PostConstruct method as you see on managed beans, "init", is inherited from exactly this Servlet API.
In case you wonders, the #PreDestroy equivalent is the GenericServlet#destroy() method.
#Override
public void destroy() {
// ...
}

Spring-Boot-jdbcTemplate object not initialized

I am a beginner to Spring Boot/MVC. I have been trying to build a very basic example of querying a table containing master data for doctors.However I am repeatedly getting "java.lang.NullPointerException".Most probably because jdbcTemplate object is not getting initialized.
Some of the other users also faced this issue however in their case the problem was resolved after either including starter-jdbc jar or after removing usage of new operator to create jdbctemplate object.I have already factored these suggestions in my code. Any help on the matter would be appreciated.My code snippets are as following:
1. application.properties :
server.port=8181
spring.datasource.url = jdbc:mysql://localhost:3306/my_sample_schema
spring.datasource.username = qwerty
spring.datasource.password = qwerty
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.driverClassName=com.mysql.jdbc.Driver
debug=true
2. Test123Application.java
package com.example;
....all imports...
#SpringBootApplication
public class Test123Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Test123Application.class, args);
}
}
3.Testcontroller.java
package com.example.controller;
....all imports...
#Controller
public class TestController {
#RequestMapping(value = "/")
public String demofunction(){
return "dummytemplate";
}
#RequestMapping("/default")
public String demofunction2(Model model){
Docrepo docrepo = new Docrepoimpl();
List<Docmaster> listContact = docrepo.list();
model.addAttribute("listContact", listContact);
return "dummytemplate2";
}
}
4. Docrepoimpl.java
package com.example.repository;
----all imports---
#Configuration
#Repository
public class Docrepoimpl implements Docrepo{
#Autowired
private JdbcTemplate jdbcTemplate;
public void adddoctor(Docmaster doc){
String sql = "INSERT INTO docmastertable (docid,name,yoe,speciality,degree,college,hospital,regno)"
+ " VALUES (?,?,?,?,?,?,?,?)";
jdbcTemplate.update(sql, doc.getdocid(), doc.getname(),doc.getyoe(), doc.getspeciality(),doc.getdegree(),doc.getcollege(),doc.gethospital(),doc.getregno());
}
public List <Docmaster> list(){
String sql = "SELECT * FROM docmastertable";
if(jdbcTemplate != null)
System.out.println("jdbc seems ok...");
else
System.out.println("jdbc is null...");
List<Docmaster> listContact = jdbcTemplate.query(sql, new RowMapper<Docmaster>() {
#Override
public Docmaster mapRow(ResultSet rs, int rowNum) throws SQLException {
Docmaster doc = new Docmaster();
doc.setdocid(rs.getString("docid"));
doc.setname(rs.getString("name"));
doc.setyoe(rs.getInt("yoe"));
doc.setspeciality(rs.getString("speciality"));
doc.setdegree(rs.getString("degree"));
doc.setcollege(rs.getString("college"));
doc.sethospital(rs.getString("hospital"));
doc.setregno(rs.getString("regno"));
return doc;
}
});
return listContact;
}
}
Error Dump:
java.lang.NullPointerException: null
at com.example.repository.Docrepoimpl.list(Docrepoimpl.java:52) ~[classes/:na]
at com.example.controller.TestController.demofunction2(TestController.java:43) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_40]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_40]
...
Actually you are creating the repo directly in your controller class with a new statement. I'd recommend to also inject your Repo into your controller class by creating a local member and annotate it with #Autowired. If you don't want to follow this way you can also ask the Context to return a ready to use bean.
It always happens when you try to access Spring class that are not managed by the Spring Boot framework AKA the Spring boot container.
With the following line you can get any spring boot class for which the #Autowired does not work.
Here is a class that i used to access JdbcTemplate without #Autowired.
public class MysqlServiceJava {
// You don't need #Autowired
JdbcTemplate jdbcTemplate;
public MysqlServiceJava() {
// Get JdbcTemplate through Context container AKA !! THE MAGIC !!
jdbcTemplate = ApplicationContextHolder.getContext().getBean(JdbcTemplate.class);
}
public List<Integer> findAllEasyId(){
List<Integer> Ids = new ArrayList<>();
String sql = "SELECT id FROM master_table";
jdbcTemplate.query(
sql, new Object[] {},
(rs, rowNum) -> new MasterTable(rs.getInt("id"))
).forEach(
masterTable ->
Ids.add(masterTable.getId()) // add Id to Ids List array
);
return Ids;
}
}
class MasterTable {
private Integer id;
public MasterTable(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
#Override
public String toString() {
return "MasterTable{" +
"id=" + id +
'}';
}
public void setId(Integer id) {
this.id = id;
}
}
Thumbs up if you like =)

Resources