How can I keep my using interfaces in classes I want to use JiBX binding with?
Example:
I have this very simple model in java:
public interface A {
B getB();
void setB(B b);
}
public interface B {
String getData();
void setData(String data);
}
public class AImpl implements A {
B b;
#Override
public B getB() {
return b;
}
#Override
public void setB(B b) {
this.b = b;
}
}
public class BImpl implements B {
private String data;
#Override
public String getData() {
return data;
}
#Override
public void setData(String data) {
this.data = data;
}
}
And this binding document:
<binding>
<mapping name="A"
class="com.test.AImpl">
<structure name="B" usage="optional" get-method="getB" set-method="setB"/>
</mapping>
<mapping name="B"
class="com.test.BImpl">
<value name="data" set-method="setData" get-method="getData" usage="optional"/>
</mapping>
</binding>
When I try to run my code I get this exception:
java.lang.ClassFormatError: Method
in class com/test/B has illegal
modifiers: 0x1001
I've tried to use 'abstract="true"' on both mapping, only to get this exception:
...Caused by:
org.jibx.runtime.JiBXException: Unable
to access binding information for
class com.test.A Make sure the binding
has been compiled...
The only solution I've found is to have AImpl hold a BImpl instead of a B, and have the getter return BImpl and the setter recieve BImpl. This is very wrong as it breaks the interface completely.
How can I solve this? I've been pulling hairs out, having tantrums (the real issue is much more complex, and JiBX cryptic error messages don't help) - nothing help.
Is this solvable? Is JiBX really that intrusive (in that it requires me to abandon all interface programming?)
Please don't answer "use AbstractB" as it's the same problem, only one level removed.
In the mapping, you should be able use the "create-type" attribute to specify the concrete class that JiBX should instantiate for bean properties that have an interface type. I use this a lot for collection properties. For example, you can tell JiBX to instantiate a java.util.HashSet for a property of type java.util.Set. But I believe it works just as well for non-collection properties. Your mapping would look something like:
<mapping class="com.mypackage.AImpl" name="A">
<structure get-method="getB" set-method="setB" create-type="com.mypackage.BImpl">
...
</structure>
...
</mapping>
JiBX will call the no-arg constructor to create the B object. Alternatively, you could use a factory or a custom serializer/deserializer if you need fancy instantiation logic. See this reference page for details.
Another good resource is the binding.dtd - apparently it's not in the distribution but can be downloaded from here: http://jibx.cvs.sourceforge.net/viewvc/checkout/jibx/core/docs/binding.dtd. Put this file somewhere (c:\binding.dtd for example). Then, in the top binding entry, use this:
<binding xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="file://jibx/binding.dtd">
and register file://jibx/binding.dtd to point to your saved binding.dtd for documentation and verification goodies.
It's amazing what inertia does - I know that xml files should have schemas / dtds, I've used them before and always said "without a schema understanding this would've been impossible". Yet when I've entered this project, it never occurred to me to search for the schema / dtd for this xml - I just accepted it as given that it had none.
Lesson learned.
Related
I would like to declare a Java 8 method reference as a Spring bean. What is the easiest way of doing this in a Spring XML file?
For example, suppose I have:
class Foo {
Foo(ToLongFunction<Bar> fn) { ... }
}
class Bar {
long getSize() { ... }
}
... and I want to create a Foo that takes the method reference Bar::getSize as the constructor argument.
How do I declare the Foo instance in a Spring bean XML file?
My proposed solution below is probably not the best idea, but I found the question interesting and decided to try to give it a shot. This is the best I could come up with.
I don't know if there is a way to do this directly in this moment (aside from defining some kind of factory bean), but alternatively you could do it using dynamic language support, for instance with Groovy.
The following example ran for me using the latest version of Spring (as of today 4.1.6)
Supposing a bean like this
public class Foo {
private Function<String, String> task;
#Autowired
public Foo(Function<String, String> task){
this.task = task;
}
public void print(String message) {
System.out.println(task.apply(message));
}
}
Then I could define an XML configuration like:
<lang:groovy id="func">
<lang:inline-script>
<![CDATA[
import java.util.function.Function
{ text -> "Hello " + text } as Function
]]>
</lang:inline-script>
</lang:groovy>
<bean id="foo" class="demo.services.Foo">
<constructor-arg name="task" ref="func"/>
</bean>
Of course, the syntax of your lambda will depend on the language you choose. I have no idea if Groovy has something like method reference, but any method reference could be expressed with a lambda/closure as I did above.
Would the following use case be considered as justified for Reflection?
There are bunch of classes generated from XSDs (hundreds currently on project) which represent various Responses.
All of these Responses include common response data structure, rather then extending it.
When event such as timeout happens, i only need to set single String to specific value.
If these classes were extending common response structure i could always set this response code without reflection, but this is not the case.
Therefore i wrote simple utility for my services which uses reflection to get setter method for the String field and invoke it with predefined value.
Only known alternative to me would be to have class specific methods which would duplicate code to handle timeout, with the only difference of returned Response class.
protected T handleTimeout(Class<T> timeoutClass) {
try {
T timeout = timeoutClass.newInstance();
Method setCode = timeoutClass.getDeclaredMethod(SET_RESPONSE_CODE, String.class);
setCode.invoke(timeout, Response.TIMEOUT.getCode());
return timeout;
} catch (InstantiationException | IllegalAccessException | SecurityException | NoSuchMethodException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
throw new RuntimeException("Response classes must have field: \"code\" !");
}
}
Relevant fact:
this setter method should never change as it would require rework of hundreds of interfaces
Could somebody point out if there are some pitfalls i have missed or if there is alternate solution for reflection which would achieve the same result ?
Edit: I simply have no authority to get any changes done on XSDs, so any solution would have to be done locally. There should be no problems with serializing such objects, as they are shared between components.
Firstly there is a standard, normal everyday solution as suggested by #kutschkem, specifically: declare an interface that only contains this one setter method and implement that interface in every class which requires it. This uses standard polymorphism to do exactly what you need.
I understand this requires changing the definition of a lot of classes (but the change is trivial - just add 'implements MytimeoutThing' to every class) - even for 1000's of classes this seems a fairly easy fix for me.
I think that there are real problems with reflection:
You are creating a secret interface to all your classes that must be supported but there is no contract for this interface - when a new developer wants to add a new class he has to magically know about the name and signature for this method - if he gets it wrong the code fails at run-time as the compiler doesn't know about this contract. (So something as simple as misspelling the setters name isn;t picked up by the compiler)
It's ugly, hidden and not clearly part of any particular part of the software. A dev maintaining ANY of these classes will find this function (the setter) notice that it is never being called and just delete it - after all no code in the rest of the project refers to that setter so it obviously isn't needed.
A whole lot of static analysis tools won;t work - for example in most IDE's you can establish all the places that specific function is called from and all the places that a specific function calls - obviously this kind of functionality is not available if you use reflection. In a project with hundreds of near identical classes I would hate to loose this facility.
The actual problem you are facing is that you have a lot of classes that should share a common abstraction between them (inheriting the same class or implementing the same interface), but they don't. Trying to keep it that way and designing around would basically be taking care of the symptoms instead of the cause and will likely cause more problems in the future.
I suggest to solve the root cause instead by making all the generated classes have a common interface / superclass. You do not have to do this by hand - as they are all generated it should be possible to change them automatically without much struggle.
I'd try an alternate solution for generating your classes from the xml schema, in preference over reflection.
You can supply xjc with a custom binding like this:
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd" version="2.1">
<globalBindings>
<xjc:superClass name="XmlSuperClass" />
</globalBindings>
</bindings>
and implement you XmlSuperClass like this:
#XmlTransient // to prevent that the shadowed responseCode be marshalled
public class XmlSuperClass {
private String responseCode; // this will be shadowed
public String getResponseCode() { // this will be overridden
return responseCode;
}
public void setResponseCode(String value) { //overridden too
this.responseCode = value;
}
}
Invoking xjc like this:
xjc -extension -b <yourbinding.xjb> -cp <XmlSuperClass> <xmlschemas.xsd...>
will generate bound classes like:
#XmlRootElement(name = "whatever")
public class Whatever extends XmlSuperClass {
#XmlElement(required = true)
protected String responseCode; // shadowing
public void setResponseCode(String...) //overriding
}
To become objective again:
There is no mention of the object instantiation.
If you would have postulated a constructor with a String code parameter:
T timeout = timeoutClass.getConstructor(String.class)
.newInstance(Response.TIMEOUT.getCode());
Would the save critics arise? To a lower extent, as parametrized constructors are even more indeterminate. Let's await the voting here.
Interface is better looking though.
interface CodeSetter {
void setCode(String code);
}
protected <T extends CodeSetter> handleTimeout(Class<T> timeoutClass) {
try {
T timeout = timeoutClass.newInstance();
timeout.setCode(Response.TIMEOUT.getCode());
return timeout;
Okay, so let's suppose you've got this generated code:
public class Response1 {
public void setResponseCode(int code) {...}
}
public class Response2 {
public void setResponseCode(int code) {...}
}
What you need to do then is write an interface:
public interface ResponseCodeAware { //sorry for the poor name
public void setResponseCode(int code);
}
Then you need to write a script that goes through all the generated code files and simply adds implements ResponseCodeAware after every class definition. (That's assuming that there are no interfaces implemented already, in that case you have to play around a bit with the string processing.)
So your generated and post-processed classes will now look like this:
public class Response1 implements ResponseCodeAware {
public void setResponseCode(int code) {...}
}
public class Response2 implements ResponseCodeAware {
public void setResponseCode(int code) {...}
}
Note that nothing else changed, so code that doesn't know about your interface (including serialization) should work exactly the same.
And finally we can rewrite your method:
protected T handleTimeout(Class<T extends ResponseCodeAware> timeoutClass) {
try {
T timeout = timeoutClass.newInstance();
timeout.setResponseCode( Response.TIMEOUT.getCode() );
return timeout;
} catch (InstantiationException | IllegalAccessException | SecurityException | NoSuchMethodException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
throw new RuntimeException("Response class couldn't be instantiated.");
}
}
As you can see, unfortunately we still have to use reflection to create our object, and unless we also create some kind of factory, that will stay that way. But code generation can help you here too, you can build up a factory class in parallel to marking the classes with the interface.
I'm using the jaxb/jaxws libraries to handle Soap messages. When a soap fault occurs, I have to cast it to one of the message types. That is, I do something like this:
if(exceptionObject instanceof Message1Data){
Integer errorCode = ((Message1ExceptionData) exceptionObject).
getExceptionData().getErrorCode();
}
if(exceptionObject instanceof Message2Data){
Integer errorCode = ((Message2ExceptionData) exceptionObject).
getExceptionData().getErrorCode();
}
//...
For a bunch of different types of messages. All of which have the function getErrorCode() but are auto generated so there isn't any kind of class inheritance.
So this turns into a long series of if statements to just get the errorCode out, which always exists. Is there a way to tell the compiler that its OK to call this function on the object, similar how I would cast an object in order to access certain functions. So instead of doing a bunch of if statements I can remove it and do something like
Integer errorCode = exceptionObject.getExceptionData().getErrorCode();
once, instead of the same code for each type of message? Or is there an option in jaxb/jaxws to tell it that each of these classes implement an interface? (Short of writing a custom library that allows this)
JAXB2 Inheritance Plugin allows you to make your classes implement a given interface or extends a certain class.
Customization directly in the schema:
<xs:complexType name="WillBeMadeCloneableType">
<xs:annotation>
<xs:appinfo>
<inheritance:implements>java.lang.Cloneable</inheritance:implements>
</xs:appinfo>
</xs:annotation>
<!-- ... -->
</xs:complexType>
Or in an external binding file:
<jaxb:bindings node="xsd:simpleType[#name='MyType']">
<inheritance:implements>java.lang.Cloneable</inheritance:implements>
</jaxb:bindings>
You can also use generics.
Customizing WSDLs is a bit trickier, but is also possible.
Disclosure: I am the author of the JAXB2 Inheritance plugin which is the part of the JAXB2 Basics package.
Documentation is currently being moved to GitHub. Please check the following links:
Actual documentation on the plugin
Using JAXB2 Basics plugins
Not sure how your objects are setup, hopefully it has a base exception that contains your errorCode, because using instanceOf is very bad way to tell what exception you have. You probably should base what Exception you have base on your errerCode:
interface ExceptionBase extends Exception { public int getErrorCode; }
class Message1ExceptionData implements ExceptionBase {
public int getErrorCode() { return 1; }
}
class Message2ExceptionData implements ExceptionBase { ... return 2; }
switch(exceptionObject.getErrorCode()) {
case 1: Message1ExceptionData exception = (Message1ExceptionData) exceptionObject;
case 2: ...
}
Reflection might work. It depends on the exact structure of the exception classes. Something like that might do the trick:
Method method = exceptionObject.getClass().getMethod("getExceptionData");
ExceptionData exceptionData = (ExceptionData) method.invoke(exceptionObject);
Integer errorCode = exceptionData.getErrorCode();
I've been struggling with how to map to object with generics in Dozer and have not found anything to aid me after extensive searching.
I'm trying to map some objects that I wrote to some that were created by someone else. I started out using annotations and saw a similar error so I moved to using a mapping file instead. However, it doesn't seemed to have helped.
Here's an example of what I'm trying to accomplish.
public interface MyObject<T extends MyContent> {
T getData();
}
public interface MyStaff extends MyContent {
Demo getDemo();
}
public interface Demo {
Name getName();
}
public interface Name {
String getFirstName();
String setFirstName(String firstName);
}
<mapping>
<class-a>com.example.Staff</class-a>
<class-b>com.example.MyObject</class-b>
<field>
<a>firstName</a>
<b>data.demo.name.firstName</b>
</field>
</mapping>
Here's the error I'm seeing:
org.dozer.MappingException: No read or write method found for field (data.demo.name.firstName) in class (interface com.example.MyObject)
I've tried another of permutations (using concrete classes rather than interfaces, for example) and nothing works.
I was able to get this working. It seems the issue was due to the fact that the implementation class was not public. It seems like this might be a bug or at least an enhancement. Dozer should either notify you the class isn't accessible as suggesting the field isn't found is misleading.
I don't want use XmlJavaTypeAdapter annotations with XmlAdapter's class in my code directly.
So, I wrote some wrapper:
class BinderWrapper<MODEL, BEAN> extends XmlAdapter<BEAN, MODEL>{
private final Binder<MODEL, BEAN> target;
private BinderWrapper(Binder<MODEL, BEAN> target){
this.target = target;
}
static <MODEL, BEAN> BinderWrapper<MODEL, BEAN> createInstance(Binder<MODEL, BEAN> binder){
return new BinderWrapper<MODEL, BEAN>(binder);
}
#Override
public MODEL unmarshal(BEAN v) throws Exception {
return target.unBean(v);
}
#Override
public BEAN marshal(MODEL v) throws Exception {
return target.toBean(v);
}
}
that's wrappes my binders like XmlAdapter s. All my binders will implements Binder interface
public interface Binder<MODEL, BEAN> {
MODEL unBean(BEAN bean);
BEAN toBean(MODEL model);
}
But there is a problem. #XmlJavaTypeAdapter require XmlAdapter class without any wrapper. How I can solve this problem? - use other annotation / write some config / write some magic annotation /..
Thanks.
upd
I have model classes that aren't JavaBeans. So I want do some two step mapping : in beans and than into xml. I want do first step with annotations too. Probably I well need this beans not only for JAXB. The real question is : can I do first step with some non JAXB annotations?
I have model classes that aren't
JavaBeans. So I want do some two step
mapping : in beans and than into xml.
I want do first step with annotations
too. Probably I well need this beans
not only for JAXB. The real question
is : can I do first step with some non
JAXB annotations?
The XmlAdapter provides the two step mapping you are looking for. If you look at the example linked below Map is the object that is not a Java Bean. What the XmlAdapter does is convert it to a Java Bean that can be mapped.
You may find it easier to use the #XmlJavaTypeAdapter annotation at the type level rather than the property level. When used at the type level you are saying everyone that references that class should use the adapter instead of per property. See my post on JAXB and Immutable Objects for a type level example.
For more information see:
http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html
http://bdoughan.blogspot.com/2010/12/jaxb-and-immutable-objects.html