I have a question regarding static method access. I have a class within i have 4 static method. as shown in code:
package com.itrucking.util;
public class ZKUtil implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
* #author Shekhar
* #param _class
* #param listbox
* To make Listbox sorting enabled
* #throws NoSuchMethodException
* #throws SecurityException
*/
public static void setSortingEnabled(Class<?> _class, Listbox listbox){
Map<Listheader, String> sortingPair = new HashMap<Listheader, String>();
sortingPair = getMapForSorting(_class, listbox);
if (!sortingPair.isEmpty()) {
for (Map.Entry<Listheader, String> entry : sortingPair.entrySet()) {
entry.getKey().setSortAscending(
new FieldComparator(entry.getValue(), true));
entry.getKey().setSortDescending(
new FieldComparator(entry.getValue(), false));
}
}
}
/**
* #author Shekhar
* #param _class
* #param listbox
* #return Map<Listheader, String>
*/
private static Map<Listheader, String> getMapForSorting(Class<?> _class,Listbox listbox) {
List<Listheader> headerList = getListHeaderList(listbox);
Map<Listheader, String> sortingPair = new HashMap<Listheader, String>();
System.out.println(_class);
Field[] fields = _class.getDeclaredFields();
for (Field f : fields) {
// System.out.println(f.getName()+":"+f.getType());
for (Listheader lh : headerList) {
if (f.getName().equals(getId(lh)))
sortingPair.put(lh, f.getName());
}
}
System.out.println(sortingPair);
return sortingPair;
}
private static String getId(Listheader listheader) {
String listheaderId = null;
if (listheader.getId().contains("_")) {
listheaderId = listheader.getId().split("_")[1];
// System.out.println("listheaderId->"+listheaderId);
}
return listheaderId;
}
/**
* #author Shekhar
* #param listbox
* #return List<Listheader>
*/
#SuppressWarnings("unchecked")
private static List<Listheader> getListHeaderList(Listbox listbox) {
List<Listheader> headerList = new ArrayList<Listheader>();
Listhead listhead = null;
List<Component> listboxComponentList = listbox.getChildren();
for (Component listboxComponent : listboxComponentList) {
if (listboxComponent instanceof Listhead) {
listhead = (Listhead) listboxComponent;
break;
}
}
List<Component> listOfComp = listhead.getChildren();
if (listhead != null) {
for (Component c : listOfComp) {
if (c instanceof Listheader)
headerList.add((Listheader) c);
}
}
return headerList;
}
}
and i am calling setSortingEnabled() method from onLoadShipperDetailsListCtrl() from code bellow :
package com.itrucking.webui.controller;
public class ShipperDetailsListCtrl{
/**
* #param e
* #return void
*/
public void onCreate$window_shipperDetailsList(Event e){
onLoadShipperDetailsListCtrl();
}
/**
* #return void
*/
public void onLoadShipperDetailsListCtrl(){
System.out.println("onLoadShipperDetailsListCtrl called.");
shipperList = shipperService.getShipperList();
doRenderListboxShipperDetailsList(shipperList);
ZKUtil.setSortingEnabled(ShipperMaster.class, listbox_shipperDetailsList);
}
}
so what i think if i am calling setSortingEnabled() method from other class so i kept is as public and other method's i kept as private but it's giving me error as :
java.lang.NoSuchMethodError: com/itrucking/util/ZKUtil.getMapForSorting(Ljava/lang/Class;Lorg/zkoss/zul/Listbox;)Ljava/util/Map;
Why there is error NoSuchMethodError for ZKUtil.getMapForSorting() call in setSortingEnabled()
I know we can call private method from public in the same class. So i am not able to understand what is the problem.
Thanks in advance.
A NoSuchMethodError (the runtime error saying a method can't be found, instead of a compiler error) usually means that the .class files you're using are of a different version than the files you compiled against. In this case, you probably made changes to ZKUtil.java, but the JVM is loading an outdated version of ZKUtil.class. Clean and rebuild all of your .class files.
Related
I'm trying to consume wsdl client that can be found on this link https://tim-erp.com/ERPX_WEB/awws/ErpX.awws?wsdl
My java code looks like this
public class SoapServicesImpl extends WebServiceGatewaySupport implements SoapServices {
#Override
public String doAuth(AuthDto authDto){
AuthStrct authStrct = new AuthStrct();
authStrct.setFirmaNaziv(authDto.getNazivFirme());
authStrct.setGodina(authDto.getGodina());
authStrct.setPassword(authDto.getPassword());
authStrct.setUsername(authDto.getUsername());
return callService(new ObjectFactory().createAuthStrct(authStrct));
}
#SuppressWarnings("unchecked")
public <T> T callService(JAXBElement<?> jaxbRequest) {
jaxbRequest.getValue();
JAXBElement<T> jaxbResponse;
try {
jaxbResponse = (JAXBElement<T>) getWebServiceTemplate().marshalSendAndReceive(jaxbRequest);
} catch (WebServiceException e) {
e.printStackTrace();
throw e;
}
return jaxbResponse.getValue();
}
}
package-info looks like this
#javax.xml.bind.annotation.XmlSchema(namespace = "urn:ErpX")
package rs.sweetchoice.commonservice.generated;
Generated ObjectFactory snippet:
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.3.0
// See https://javaee.github.io/jaxb-v2/
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2020.09.05 at 01:28:42 PM CEST
//
package rs.sweetchoice.commonservice.generated;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.namespace.QName;
/**
* This object contains factory methods for each
* Java content interface and Java element interface
* generated in the rs.sweetchoice.commonservice.generated package.
* <p>An ObjectFactory allows you to programatically
* construct new instances of the Java representation
* for XML content. The Java representation of XML
* content can consist of schema derived interfaces
* and classes representing the binding of schema
* type definitions, element declarations and model
* groups. Factory methods for each of these are
* provided in this class.
*
*/
#XmlRegistry
public class ObjectFactory {
private final static QName _WSID_QNAME = new QName("urn:ErpX", "WSID");
private final static QName _AUTH_QNAME = new QName("urn:ErpX", "authStrct");
/**
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: rs.sweetchoice.commonservice.generated
*
*/
public ObjectFactory() {
}
/**
* Create an instance of {#link AutoCompleteStrct }
*
*/
public AutoCompleteStrct createAutoCompleteStrct() {
return new AutoCompleteStrct();
}
/**
* Create an instance of {#link KorpaStrct }
*
*/
public KorpaStrct createKorpaStrct() {
return new KorpaStrct();
}
/**
* Create an instance of {#link CmbStrct }
*
*/
public CmbStrct createCmbStrct() {
return new CmbStrct();
}
/**
* Create an instance of {#link AuthStrct }
*
*/
#XmlElementDecl(namespace = "urn:ErpX", name = "authStrct")
public JAXBElement<AuthStrct> createAuthStrct(AuthStrct value) {
return new JAXBElement<>(_AUTH_QNAME, AuthStrct.class, null, value);
}
/**
* Create an instance of {#link FilterStrct }
*
*/
public FilterStrct createFilterStrct() {
return new FilterStrct();
}
/**
* Create an instance of {#link ProfakStavStrct }
*
*/
public ProfakStavStrct createProfakStavStrct() {
return new ProfakStavStrct();
}
/**
* Create an instance of {#link ProfakStrct }
*
*/
public ProfakStrct createProfakStrct() {
return new ProfakStrct();
}
/**
* Create an instance of {#link RacunStavStrct }
*
*/
public RacunStavStrct createRacunStavStrct() {
return new RacunStavStrct();
}
/**
* Create an instance of {#link RacunStrct }
*
*/
public RacunStrct createRacunStrct() {
return new RacunStrct();
}
/**
* Create an instance of {#link UplKomitStrct }
*
*/
public UplKomitStrct createUplKomitStrct() {
return new UplKomitStrct();
}
/**
* Create an instance of {#link UplListaStavStrct }
*
*/
public UplListaStavStrct createUplListaStavStrct() {
return new UplListaStavStrct();
}
/**
* Create an instance of {#link UplListaStrct }
*
*/
public UplListaStrct createUplListaStrct() {
return new UplListaStrct();
}
/**
* Create an instance of {#link WsGetRoba }
*
*/
public WsGetRoba createWsGetRoba() {
return new WsGetRoba();
}
/**
* Create an instance of {#link WsGetKomit }
*
*/
public WsGetKomit createWsGetKomit() {
return new WsGetKomit();
}
/**
* Create an instance of {#link WsGetGrpRoba }
*
*/
public WsGetGrpRoba createWsGetGrpRoba() {
return new WsGetGrpRoba();
}
/**
* Create an instance of {#link WsGetGrpKomit }
*
*/
public WsGetGrpKomit createWsGetGrpKomit() {
return new WsGetGrpKomit();
}
/**
* Create an instance of {#link WsGetManuf }
*
*/
public WsGetManuf createWsGetManuf() {
return new WsGetManuf();
}
/**
* Create an instance of {#link WsUplProfak }
*
*/
public WsUplProfak createWsUplProfak() {
return new WsUplProfak();
}
/**
* Create an instance of {#link WsGetMagacin }
*
*/
public WsGetMagacin createWsGetMagacin() {
return new WsGetMagacin();
}
/**
* Create an instance of {#link WsGetAkcijskeCene }
*
*/
public WsGetAkcijskeCene createWsGetAkcijskeCene() {
return new WsGetAkcijskeCene();
}
/**
* Create an instance of {#link WsUplKomit }
*
*/
public WsUplKomit createWsUplKomit() {
return new WsUplKomit();
}
/**
* Create an instance of {#link WsUplKomitResponse }
*
*/
public WsUplKomitResponse createWsUplKomitResponse() {
return new WsUplKomitResponse();
}
/**
* Create an instance of {#link WsUplRacun }
*
*/
public WsUplRacun createWsUplRacun() {
return new WsUplRacun();
}
/**
* Create an instance of {#link JAXBElement }{#code <}{#link byte[]}{#code >}
*
* #param value
* Java instance representing xml element's value.
* #return
* the new instance of {#link JAXBElement }{#code <}{#link byte[]}{#code >}
*/
#XmlElementDecl(namespace = "urn:ErpX", name = "WSID")
#XmlJavaTypeAdapter(HexBinaryAdapter.class)
public JAXBElement<byte[]> createWSID(byte[] value) {
return new JAXBElement<byte[]>(_WSID_QNAME, byte[].class, null, ((byte[]) value));
}
}
And i get error
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Fault"). Expected elements are <{urn:ErpX}WSID>,<{urn:ErpX}authStrct>
Using java 11 and spring boot 2.3.3.
EDIT this is my config class
#Configuration
public class WsConfig {
#Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("rs.sweetchoice.commonservice.generated");
return marshaller;
}
#Bean
public SoapServicesImpl soapServicesImpl(Jaxb2Marshaller marshaller) {
SoapServicesImpl client = new SoapServicesImpl();
client.setDefaultUri("https://tim-erp.com/ERPX_WEB/awws/ErpX.awws");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
return client;
}
}
Try to setCheckConnectionForFault to false on WebServiceTemplate. For example, replace the method:
public <T> T callService(JAXBElement<?> jaxbRequest) {
jaxbRequest.getValue();
JAXBElement<T> jaxbResponse;
try {
WebServiceTemplate webServiceTemplate = getWebServiceTemplate();
webServiceTemplate.setCheckConnectionForFault(false);
jaxbResponse = (JAXBElement<T>) webServiceTemplate.marshalSendAndReceive(jaxbRequest);
} catch (WebServiceException e) {
e.printStackTrace();
throw e;
}
return jaxbResponse.getValue();
}
I have an object in use throughout my codebase, UnsecureObject. This object is auto-generated with no getters/setters, and all member fields are public. So editing is done by doing something like the following:
unsecureObjInstance.firstName = "Jane";
This is not desirable for numerous reasons that I probably don't have to explain here. But using this generated class is required for some other technical details with our messaging pipeline that I won't go into.
I have a desire is to leverage a mapping utility written by someone else on my team to convert this UnsecureObject to a pojo that I am writing.
An example of the mapper in action (with two normal classes w/ getters/setters) would be something like:
new MapperBuilder<>(PojoOne.class, PojoTwo.class)
.from(PojoOne::getName).to(PojoTwo::getFirstName)
.build();
This will map the PojoOne#name field to the PojoTwo#firstName field.
Is there a way to translate this to input my UnsecureObject here? I have tried something like the following:
new MapperBuilder<>(UnsecureObject.class, SecureObject.class)
.from(u -> u.firstName).to(SecureObject::getFirstName)
.build();
But get an error here, something along the lines of 'u -> u.firstName' could not be invoked.
So the question is:
Is there a way to essentially "construct" a getter on the fly using these public members? So in the .from() method, I can construct the call to look like a standard method that will yield my u.firstName?
Thanks for the help!
EDIT:
this is approx what the MapperBuilder class looks like (attempted to edit a bit to take away project specific wrappers/simplify)
/**
* This class is used to convert between POJO getter method references to the corresponding field names.
* #param <B> type
*/
public interface PojoProxy<B> {
/**
* Invokes the given getter method and returns information about the invocation.
* #param getter the getter to invoke
* #return information about the method invoked
*/
<T> GetterInvocation<T> invokeGetter(Function<B, T> getter);
}
/**
* Stores information about a method invocation.
* #param <T> method return type
*/
public interface GetterInvocation<T> {
public Class<T> getReturnType();
public String getFieldName();
}
/**
* A builder class to create {#link Mapper} instances.
* #param <FROM> source type
* #param <TO> target type
*/
public class MapperBuilder<FROM, TO> {
private final Class<FROM> _fromClass;
private final Class<TO> _toClass;
private final PojoProxy<FROM> _fromProxy;
private final PojoProxy<TO> _toProxy;
public MapperBuilder(Class<FROM> fromClass, Class<TO> toClass) {
_fromClass = fromClass;
_toClass = toClass;
//We will pretend there is an impl that provides the proxy.
//Proxies wrap the from and to classes in order to get reflection information about their getter calls.
_fromProxy = PojoProxy.of(fromClass);
_toProxy = PojoProxy.of(toClass);
}
public <FROM_VALUE> ToFieldBuilder<FROM_VALUE> from(Function<FROM, FROM_VALUE> getter) {
GetterInvocation<FROM_VALUE> methodInvocation = _fromProxy.invokeGetter(getter);
return new ToFieldBuilder<>(methodInvocation.getFieldName(), methodInvocation.getReturnType());
}
public class ToFieldBuilder<FROM_VALUE> {
private final String _fromFieldPath;
private final Class<FROM_VALUE> _fromClass;
public ToFieldBuilder(String fromFieldPath, Class<FROM_VALUE> fromClass) {
_fromFieldPath = fromFieldPath;
_fromClass = fromClass;
}
public <TO_VALUE> FromFieldBuilder<FROM_VALUE, TO_VALUE> to(Function<TO, TO_VALUE> getter) {
//similar to above, but now using a FromFieldBuilder.
}
}
public class FromFieldBuilder<FROM_VALUE, TO_VALUE> {
//impl..
}
}
I dont see MapperBuilder.from() method details, you can try this implementation of MapperBuilder.java Function (getter) -> (BiConsumer) setter
public class MapperBuilder<S, D> {
private final S src;
private final D dest;
public MapperBuilder(S src, Class<D> dest) {
this.src = src;
try {
this.dest = dest.newInstance();
} catch (Exception e) {
throw new RuntimeException("Required default constructor for: " + dest);
}
}
//getter - function to get value from source instance
//setter - biConsumer to set value to destination instance
//example - map(SrcClass::getSrcValue, DestClass::setDestValue)
public <V> MapperBuilder<S, D> map(Function<S, V> getter, BiConsumer<D, V> setter) {
setter.accept(dest, getter.apply(src));
return this;
}
public D build() {
return dest;
}
}
SrcClass.java some source class:
public class SrcClass {
private String srcValue;
public String getSrcValue() {
return srcValue;
}
public void setSrcValue(String srcValue) {
this.srcValue = srcValue;
}
}
DestClass.java some destination class:
package com.example.demo;
public class DestClass {
private String destValue;
public String getDestValue() {
return destValue;
}
public void setDestValue(String destValue) {
this.destValue = destValue;
}
}
DemoApplication.java demo:
public class DemoApplication {
public static void main(String[] args) {
SrcClass src = new SrcClass();
src.setSrcValue("someValue");
DestClass dest = new MapperBuilder<>(src, DestClass.class)
.map(SrcClass::getSrcValue, DestClass::setDestValue)
// map another fields
.build();
// for your UnsecureObject case
UnsecureObject unsecureObject = new MapperBuilder<>(src, UnsecureObject.class)
.map(SrcClass::getSrcValue,
(unsecure, srcValue) -> unsecure.unsecureValue = srcValue)
.build();
}
}
I am testing my DTOs using a generic dto testing code that I found online https://objectpartners.com/2016/02/16/automatically-junit-test-dto-and-transfer-objects/. Most of the time, it works perfect. Suddenly one day, I got an test failure for just one test class. And it is occasionally occurred, which means sometime it happened, most of the time, it works fine.
pubic class MyDtoClass implements Serializable {
private String includeNullValue;
public String getIncludeNullValue() {
return includeNullValue;
}
public void setIncludeNullValue(String includeNullValue) {
this.includeNullValue = includeNullValue;
}
}
The test output the following error message when it failed:
java.lang.AssertionError: includeNullValue is different expected same:<> was not:<null>
Expected :
Actual :null
My test class is as below
public class MyDtoClassTest extends DtoTest<MyDtoClass> {
private static MyDtoClass myDtoClass;
#Before
public void setup() {
myDtoClass = new MyDtoClass();
}
#Override
protected MyDtoClass getInstance() {
return myDtoClass;
}
}
Any clue? Thanks in advance.
UPDATE: As suggested, I directly post the DtoTest.java here as below
public abstract class DtoTest<T> {
/** A map of default mappers for common objects. */
private static final ImmutableMap<Class<?>, Supplier<?>> DEFAULT_MAPPERS;
static {
final Builder<Class<?>, Supplier<?>> mapperBuilder = ImmutableMap.builder();
/* Primitives */
mapperBuilder.put(int.class, () -> 0);
mapperBuilder.put(double.class, () -> 0.0d);
mapperBuilder.put(float.class, () -> 0.0f);
mapperBuilder.put(long.class, () -> 0l);
mapperBuilder.put(boolean.class, () -> true);
mapperBuilder.put(short.class, () -> (short) 0);
mapperBuilder.put(byte.class, () -> (byte) 0);
mapperBuilder.put(char.class, () -> (char) 0);
mapperBuilder.put(Integer.class, () -> Integer.valueOf(0));
mapperBuilder.put(Double.class, () -> Double.valueOf(0.0));
mapperBuilder.put(Float.class, () -> Float.valueOf(0.0f));
mapperBuilder.put(Long.class, () -> Long.valueOf(0));
mapperBuilder.put(Boolean.class, () -> Boolean.TRUE);
mapperBuilder.put(Short.class, () -> Short.valueOf((short) 0));
mapperBuilder.put(Byte.class, () -> Byte.valueOf((byte) 0));
mapperBuilder.put(Character.class, () -> Character.valueOf((char) 0));
mapperBuilder.put(BigDecimal.class, () -> BigDecimal.ONE);
mapperBuilder.put(Date.class, () -> new Date());
/* Collection Types. */
mapperBuilder.put(Set.class, () -> Collections.emptySet());
mapperBuilder.put(SortedSet.class, () -> Collections.emptySortedSet());
mapperBuilder.put(List.class, () -> Collections.emptyList());
mapperBuilder.put(Map.class, () -> Collections.emptyMap());
mapperBuilder.put(SortedMap.class, () -> Collections.emptySortedMap());
DEFAULT_MAPPERS = mapperBuilder.build();
}
/** The get fields to ignore and not try to test. */
private final Set<String> ignoredGetFields;
/**
* A custom mapper. Normally used when the test class has abstract objects.
*/
private final ImmutableMap<Class<?>, Supplier<?>> mappers;
/**
* Creates an instance of {#link DtoTest} with the default ignore fields.
*/
protected DtoTest() {
this(null, null);
}
/**
* Creates an instance of {#link DtoTest} with ignore fields and additional custom mappers.
*
* #param customMappers Any custom mappers for a given class type.
* #param ignoreFields The getters which should be ignored (e.g., "getId" or "isActive").
*/
protected DtoTest(Map<Class<?>, Supplier<?>> customMappers, Set<String> ignoreFields) {
this.ignoredGetFields = new HashSet<>();
if (ignoreFields != null) {
this.ignoredGetFields.addAll(ignoreFields);
}
this.ignoredGetFields.add("getClass");
if (customMappers == null) {
this.mappers = DEFAULT_MAPPERS;
} else {
final Builder<Class<?>, Supplier<?>> builder = ImmutableMap.builder();
builder.putAll(customMappers);
builder.putAll(DEFAULT_MAPPERS);
this.mappers = builder.build();
}
}
/**
* Calls a getter and verifies the result is what is expected.
*
* #param fieldName The field name (used for error messages).
* #param getter The get {#link Method}.
* #param instance The test instance.
* #param expected The expected result.
*
* #throws IllegalAccessException if this Method object is enforcing Java language access control and the underlying
* method is inaccessible.
* #throws IllegalArgumentException if the method is an instance method and the specified object argument is not an
* instance of the class or interface declaring the underlying method (or of a subclass or implementor
* thereof); if the number of actual and formal parameters differ; if an unwrapping conversion for
* primitive arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to
* the corresponding formal parameter type by a method invocation conversion.
* #throws InvocationTargetException if the underlying method throws an exception.
*/
private void callGetter(String fieldName, Method getter, T instance, Object expected)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
final Object getResult = getter.invoke(instance);
if (getter.getReturnType().isPrimitive()) {
/* Calling assetEquals() here due to autoboxing of primitive to object type. */
assertEquals(fieldName + " is different", expected, getResult);
} else {
/* This is a normal object. The object passed in should be the exactly same object we get back. */
assertSame(fieldName + " is different", expected, getResult);
}
}
/**
* Creates an object for the given {#link Class}.
*
* #param fieldName The name of the field.
* #param clazz The {#link Class} type to create.
*
* #return A new instance for the given {#link Class}.
*
* #throws InstantiationException If this Class represents an abstract class, an interface, an array class, a
* primitive type, or void; or if the class has no nullary constructor; or if the instantiation fails
* for some other reason.
* #throws IllegalAccessException If the class or its nullary constructor is not accessible.
*
*/
private Object createObject(String fieldName, Class<?> clazz)
throws InstantiationException, IllegalAccessException {
try {
final Supplier<?> supplier = this.mappers.get(clazz);
if (supplier != null) {
return supplier.get();
}
if (clazz.isEnum()) {
return clazz.getEnumConstants()[0];
}
return clazz.newInstance();
} catch (IllegalAccessException | InstantiationException e) {
throw new RuntimeException("Unable to create objects for field '" + fieldName + "'.", e);
}
}
/**
* Returns an instance to use to test the get and set methods.
*
* #return An instance to use to test the get and set methods.
*/
protected abstract T getInstance();
/**
* Tests all the getters and setters. Verifies that when a set method is called, that the get method returns the
* same thing. This will also use reflection to set the field if no setter exists (mainly used for user immutable
* entities but Hibernate normally populates).
*
* #throws Exception If an expected error occurs.
*/
#Test
public void testGettersAndSetters() throws Exception {
/* Sort items for consistent test runs. */
final SortedMap<String, GetterSetterPair> getterSetterMapping = new TreeMap<>();
final T instance = getInstance();
for (final Method method : instance.getClass().getMethods()) {
final String methodName = method.getName();
if (this.ignoredGetFields.contains(methodName)) {
continue;
}
String objectName;
if (methodName.startsWith("get") && method.getParameters().length == 0) {
/* Found the get method. */
objectName = methodName.substring("get".length());
GetterSetterPair getterSettingPair = getterSetterMapping.get(objectName);
if (getterSettingPair == null) {
getterSettingPair = new GetterSetterPair();
getterSetterMapping.put(objectName, getterSettingPair);
}
getterSettingPair.setGetter(method);
} else if (methodName.startsWith("set") && method.getParameters().length == 1) {
/* Found the set method. */
objectName = methodName.substring("set".length());
GetterSetterPair getterSettingPair = getterSetterMapping.get(objectName);
if (getterSettingPair == null) {
getterSettingPair = new GetterSetterPair();
getterSetterMapping.put(objectName, getterSettingPair);
}
getterSettingPair.setSetter(method);
} else if (methodName.startsWith("is") && method.getParameters().length == 0) {
/* Found the is method, which really is a get method. */
objectName = methodName.substring("is".length());
GetterSetterPair getterSettingPair = getterSetterMapping.get(objectName);
if (getterSettingPair == null) {
getterSettingPair = new GetterSetterPair();
getterSetterMapping.put(objectName, getterSettingPair);
}
getterSettingPair.setGetter(method);
}
}
/*
* Found all our mappings. Now call the getter and setter or set the field via reflection and call the getting
* it doesn't have a setter.
*/
for (final Entry<String, GetterSetterPair> entry : getterSetterMapping.entrySet()) {
final GetterSetterPair pair = entry.getValue();
final String objectName = entry.getKey();
final String fieldName = objectName.substring(0, 1).toLowerCase() + objectName.substring(1);
if (pair.hasGetterAndSetter()) {
/* Create an object. */
final Class<?> parameterType = pair.getSetter().getParameterTypes()[0];
final Object newObject = createObject(fieldName, parameterType);
pair.getSetter().invoke(instance, newObject);
callGetter(fieldName, pair.getGetter(), instance, newObject);
} else if (pair.getGetter() != null) {
/*
* Object is immutable (no setter but Hibernate or something else sets it via reflection). Use
* reflection to set object and verify that same object is returned when calling the getter.
*/
final Object newObject = createObject(fieldName, pair.getGetter().getReturnType());
final Field field = instance.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(instance, newObject);
callGetter(fieldName, pair.getGetter(), instance, newObject);
}
}
}
}
IMHO is problem with anotation #Before on setup method
Annotating a public void method with #Before causes that method to be run before the Test method
But in your code you don't have any #Test method so object myDtoClass may not be initialize befero test.
Change code to
public class MyDtoClassTest extends DtoTest<MyDtoClass> {
#Override
protected MyDtoClass getInstance() {
return new MyDtoClass();
}
}
In an answer to a question I asked, I was advised to solve a particular (irrelevant) problem by making a class (test_C) designed to test the main class (C) be a child class of C:
public class test_C extends C {
Is this a common pattern in Java development?
Are there any reasons NOT to use this pattern for all test classes (assume that we always have 1-1 mapping between test class and tested class)?
Are there any reasons NOT to use this pattern for all test classes (assume that we always have 1-1 mapping between test class and tested class)?
The class being tested can be final, preventing any class from subclassing it.
public final class C { ... }
If a testing subclass is feasible, it could alter the behavior of the class being tested -- unintentionally as well as intentionally.
1) Well, I do not know if it is a general pattern but i already used it and found some drawbacks.
2) the reasons to not do it are fairy simple. It is recommended to use private accessor and final class or method.
If you really apply the later, you will end up with producing many duplicate classes to test a class or a method. Also, How can you make sure somebody in your team will not end up using the dummy extended class in production?
My solution to this problem was to use reflection to access private constructors and methods. It is somehow a bit tricky but afterwards it is a repetition. I am using now my utility reflection class for all my tests.
Below is my reflection utility class:
import static org.junit.Assert.fail;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* The Class JunitReflectionUtils.
*/
public final class JunitReflectionUtils {
/**
* Instantiates a new junit reflection utils.
*/
private JunitReflectionUtils() {
}
/**
* Gets the method.
*
* #param givenClass_ the given class_
* #param methodName_ the method name
* #param failIfException_ if true, the method will fail
* #param parametersClass_ the parameters
* #return the method
*/
public static Method getMethod(Class<?> givenClass_, String methodName_, boolean failIfException_, Class<?> ... parametersClass_) {
Method _method = null;
try {
_method = givenClass_.getDeclaredMethod(methodName_, parametersClass_);
} catch (Exception _exception) {
_exception.printStackTrace();
if (failIfException_) {
fail("A method called \"" + methodName_ + "\" could not be retrieved: " + _exception.getMessage());
} else {
return null;
}
}
_method.setAccessible(true);
return _method;
}
/**
* Gets the field.
*
* #param givenClass_ the given class
* #param fieldName_ the field name
* #param failIfException_ if true then the method will fail if an exception is thrown
* #return the field
*/
public static Field getField(Class<?> givenClass_, String fieldName_, boolean failIfException_) {
Field _field = null;
try {
_field = givenClass_.getDeclaredField(fieldName_);
} catch (Exception _exception) {
_exception.printStackTrace();
if (failIfException_) {
fail("A field called \"" + fieldName_ + "\" could not be retrieved: " + _exception.getMessage());
} else {
return null;
}
}
_field.setAccessible(true);
return _field;
}
/**
* assign value to a field.
*
* #param field_ the given field
* #param parentObject_ the parent containing the field
* #param failIfException_ if true then the method will fail if an exception is thrown
* #param value_ the value to assign to the field
* #return the field
*/
public static boolean assignValueToField(Field field_, Object parentObject_, boolean failIfException_, Object value_) {
try {
field_.set(parentObject_, value_);
} catch (Exception _exception) {
_exception.printStackTrace();
if (failIfException_) {
fail("An exception has occured while setting a value to a field: " + _exception.getMessage());
}
return false;
}
return true;
}
/**
* Gets the field value from a given object.
*
* #param object_ the object
* #param fieldName_ the field name
* #param failIfException_ if true, this method will fail if an exception is thrown
* #return the field value from object
*/
public static Object getFieldValueFromObject(Object object_, String fieldName_, boolean failIfException_) {
Field _givenField = getField(object_.getClass(), fieldName_, failIfException_);
Object _returnedValue = null;
if (_givenField == null) {
return null;
} else {
try {
_returnedValue = _givenField.get(object_);
} catch (Exception _exception) {
_exception.printStackTrace();
if (failIfException_) {
fail("An exception has occured while retrieving a value from a field : " + _exception.getMessage());
} else {
return null;
}
}
}
return _returnedValue;
}
/**
* Gets the constructor.
*
* #param givenClass_ the given class
* #param failIfException_ if true, a fail statement will be issued when an exception is thrown
* #param parametersClasses_ the parameters classes_
* #return the constructor
*/
public static Constructor<?> getConstructor(Class<?> givenClass_, boolean failIfException_, Class<?> ... parametersClasses_) {
Constructor<?> _constructor = null;
try {
_constructor = givenClass_.getDeclaredConstructor(parametersClasses_);
} catch (Exception _exception) {
_exception.printStackTrace();
if (failIfException_) {
fail("The constructor from the class \"" + givenClass_.getName() + "\" could not be retrieved");
} else {
return null;
}
}
_constructor.setAccessible(true);
return _constructor;
}
/**
* Instantiante an object.
*
* #param givenClass_ the given class
* #param failIfException_ if true then a fail statement will be issued if an exception is thrown
* #param parametersClasses_ the parameters classes
* #param parameters_ the parameters
* #return the object
*/
public static Object instantianteAnObject(Class<?> givenClass_, boolean failIfException_, Class<?> [] parametersClasses_, Object... parameters_) {
Constructor<?> _constructor = getConstructor(givenClass_, failIfException_, parametersClasses_);
Object _returnedObject = null;
if (_constructor != null) {
try {
_returnedObject = _constructor.newInstance(parameters_);
} catch (Exception _exception) {
_exception.printStackTrace();
if (failIfException_) {
fail("An instance of " + givenClass_.getName() + " could not be created : " + _exception.getMessage());
} else {
return null;
}
}
}
return _returnedObject;
}
}
The original reason for my Jaxb Question
JaxB reference resolving
was that I couldn't get the same issue working with the simple-framework:
http://old.nabble.com/Two-Phase-support-for-CycleStrategy--td34802791.html
Today I got the things working with a persister call back to the same point as in my Jaxb Questions:
I get copies - not references. Again I am looking for a solution with proper references. This time for the Simple XML framework.
The example here has the base class "ModelElement" not Person as in the other question. Otherwise the problem is the same.
Again I am calling the unmarshalling twice to get all ids in PASS 1 and use the gathered results from the lookup HashMap created in PASS2.
What would be a solution to get proper references? My assumption is that adding a call back that actually lets the called function modify the unmarshalling result (see How to use an output parameter in Java? for a wrapping approach)
would do the trick (comparable to the JaxB solution I have posted in the meantime).
Persister serializer = new Persister();
ModelElementSimpleXmlImpl.lookup.clear();
serializer.read(result, xml);
System.err.println("PASS 2");
serializer.read(result, xml);
This code is from the ModelElementSimpleXmlImpl base class:
...
protected String ref;
/**
* getter for xsd:string/String id
* #return id
*/
#org.simpleframework.xml.Attribute(name="ref",required=false)
public String getRef() {
return ref;
}
/**
* setter for xsd:string/String id
* #param pid - new value for id
*/
#org.simpleframework.xml.Attribute(name="ref",required=false)
public void setRef(String pRef) {
ref=pRef;
}
private boolean debug=true;
/**
* show debug information
* #param title
* #param key
* #param me
* #param found
*/
public void showDebug(String title,String key,ModelElementSimpleXmlImpl me, ModelElementSimpleXmlImpl found) {
String deref="?";
if (found!=null)
deref="->"+found.getId()+"("+found.getClass().getSimpleName()+")";
if (debug)
System.err.println(title+": "+key+"("+me.getClass().getSimpleName()+")"+deref+" - "+this);
}
/**
* keep track of the elements already seen
*/
public static Map<String,ModelElementSimpleXmlImpl> lookup=new HashMap<String,ModelElementSimpleXmlImpl>();
#Validate
public void validate() {
ModelElementSimpleXmlImpl me=this;
String key=me.getId();
if (key!=null) {
showDebug("id",key,me,null);
lookup.put(key, me);
}
key=me.getRef();
if (key!=null) {
if (lookup.containsKey(key)) {
ModelElementSimpleXmlImpl meRef=lookup.get(key);
showDebug("ref",key,me,meRef);
me.setRef(null);
me.copyFrom(meRef);
} else {
if (debug)
showDebug("ref",me.getRef(),me,null);
}
}
}
Niall Gallagher suggested:
Should be fairly easy to do with something like the CycleStrategy. Just create MyCycleStrategy and where there is an exception with "Invalid reference" just return null and remember the reference. When you have picked up all the ids and the values then do a second pass. In the second pass assign the value to the first occurrence of either the ref or the id. Then all following references should be given the same value. This should work.
And he is right. The following extended Cycle Strategy works as proposed:
/**
* Two Path Cycle Strategy
*
* #author wf
*
*/
public static class TwoPathCycleStrategy extends CycleStrategy {
String id;
String ref;
public static boolean debug = false;
/**
* create a twoPath Cycle Strategy
*
* #param id
* #param ref
*/
public TwoPathCycleStrategy(String id, String ref) {
super(id, ref);
this.id = id;
this.ref = ref;
}
/**
* show debug information
*
* #param title
* #param key
* #param value
*/
public void showDebug(String title, String key, Value value) {
if (debug) {
String id = "?";
Object v = value;
while ((v instanceof Value) && ((Value) v).isReference()) {
v = ((Value) v).getValue();
}
if (v == null) {
id = "null";
} else {
// FIXME - adapt to your code or comment out
//if (v instanceof ModelElement) {
// ModelElement me = (ModelElement) v;
// id = me.getId();
//}
}
System.err.println(title + ":" + key + "->"
+ v.getClass().getSimpleName() + ":"
+ value.getType().getSimpleName() + ":" + value.isReference() + ":"
+ id);
}
}
public Map<String, Value> lookup = new HashMap<String, Value>();
#SuppressWarnings("rawtypes")
#Override
public Value read(Type type, NodeMap node, Map map) throws Exception {
Value value = null;
Node refNode = node.get(ref);
Node keyNode = node.get(id);
try {
value = super.read(type, node, map);
if (keyNode != null) {
String key = keyNode.getValue();
if (value != null) {
showDebug("id", key, value);
lookup.put(key, value);
} else {
showDebug("id?", key, value);
}
}
} catch (CycleException ce) {
if (ce.getMessage().contains("Invalid reference")) {
if (refNode != null) {
String key = refNode.getValue();
if (lookup.containsKey(key)) {
value = lookup.get(key);
showDebug("ref", key, value);
} else {
showDebug("ref?",key,null);
}
}
} else {
throw ce;
}
}
return value;
}
}