@SuppressWarnings("unchecked") @Test public void linksFieldIsInjectedAutomaticallyInSublass() { DummySubClass dummyEntity = new DummySubClass("someId", 1L); DummySubClass returnedEntity = (DummySubClass) tested.injectLinks( dummyEntity, linkProducer, HateoasVerbosity.MINIMUM); assertNotSame(dummyEntity, returnedEntity); assertEquals("someId", returnedEntity.getId()); assertEquals(1L, returnedEntity.getTime()); Collection<Map<String, Object>> links = (Collection<Map<String, Object>>) ReflectionUtils .getFieldValue(returnedEntity, "links"); assertSame(EXPECTED_MAP, Iterables.getOnlyElement(links)); }
@Override public Object injectLinks(Object entity, LinkProducer<Object> linkProducer, final HateoasVerbosity verbosity) { if (entity == null) { return null; } String newClassName = entity.getClass().getPackage().getName() + "." + entity.getClass().getSimpleName() + "_generated"; Class<?> clazz; if (!TRANSFORMED_CLASSES.containsKey(newClassName)) { synchronized (this) { try { log.debug("Creating HATEOAS subclass for DTO : {}", entity.getClass()); boolean valid = false; for (Constructor<?> c : entity.getClass().getConstructors()) { if (c.getParameterTypes().length == 0) { valid = true; break; } } if (!valid){ throw new HateoasInjectException("DTO's must have no arg constructor. Check " + entity.getClass().getName()); } CtClass newClass = CLASS_POOL.makeClass(newClassName); newClass.setSuperclass(CLASS_POOL.get(entity.getClass().getName())); CtConstructor ctConstructor = new CtConstructor(new CtClass[0], newClass); ctConstructor.setBody("super();"); newClass.addConstructor(ctConstructor); CtField newField = CtField.make("public java.util.Collection links;", newClass); newClass.addField(newField); CtMethod linksGetterMethod = CtMethod.make("public java.util.Collection getLinks(){ return this.links; }", newClass); newClass.addMethod(linksGetterMethod); CtMethod linksSetterMethod = CtMethod.make("public void setLinks(java.util.Collection links){ this.links = links; }", newClass); newClass.addMethod(linksSetterMethod); newClass.addInterface(CLASS_POOL.get("com.jayway.jaxrs.hateoas.HateoasLinkBean")); StringBuilder cloneMethodBody = new StringBuilder(); for (Field field : ReflectionUtils.getFieldsHierarchical(entity.getClass())) { cloneMethodBody.append("com.jayway.jaxrs.hateoas.support.ReflectionUtils.setFieldHierarchical(this, \"" + field.getName() + "\", com.jayway.jaxrs.hateoas.support.ReflectionUtils.getFieldValueHierarchical(other, \"" + field.getName() + "\"));"); } String method = "public void hateoasCopy(" + entity.getClass().getName() + " other ){ " + cloneMethodBody.toString() + "}"; CtMethod cloneMethod = CtMethod.make(method, newClass); newClass.addMethod(cloneMethod); URLClassLoader classLoader = new URLClassLoader(new URL[0], entity.getClass().getClassLoader()); clazz = newClass.toClass(classLoader, entity.getClass().getProtectionDomain()); TRANSFORMED_CLASSES.put(newClassName, clazz); } catch (Exception e) { if(e instanceof HateoasInjectException){ throw (HateoasInjectException)e; } throw new RuntimeException(e); } } } else { clazz = TRANSFORMED_CLASSES.get(newClassName); } Object newInstance = null; try { newInstance = clazz.newInstance(); Method copyMethod = newInstance.getClass().getMethod("hateoasCopy", entity.getClass()); copyMethod.invoke(newInstance, entity); } catch (Exception e) { log.error("could not create instance of " + clazz.getName(), e); } return injector.injectLinks(newInstance, linkProducer, verbosity); }
JavassistHateoasLinkInjector implements HateoasLinkInjector<Object> { @Override public Object injectLinks(Object entity, LinkProducer<Object> linkProducer, final HateoasVerbosity verbosity) { if (entity == null) { return null; } String newClassName = entity.getClass().getPackage().getName() + "." + entity.getClass().getSimpleName() + "_generated"; Class<?> clazz; if (!TRANSFORMED_CLASSES.containsKey(newClassName)) { synchronized (this) { try { log.debug("Creating HATEOAS subclass for DTO : {}", entity.getClass()); boolean valid = false; for (Constructor<?> c : entity.getClass().getConstructors()) { if (c.getParameterTypes().length == 0) { valid = true; break; } } if (!valid){ throw new HateoasInjectException("DTO's must have no arg constructor. Check " + entity.getClass().getName()); } CtClass newClass = CLASS_POOL.makeClass(newClassName); newClass.setSuperclass(CLASS_POOL.get(entity.getClass().getName())); CtConstructor ctConstructor = new CtConstructor(new CtClass[0], newClass); ctConstructor.setBody("super();"); newClass.addConstructor(ctConstructor); CtField newField = CtField.make("public java.util.Collection links;", newClass); newClass.addField(newField); CtMethod linksGetterMethod = CtMethod.make("public java.util.Collection getLinks(){ return this.links; }", newClass); newClass.addMethod(linksGetterMethod); CtMethod linksSetterMethod = CtMethod.make("public void setLinks(java.util.Collection links){ this.links = links; }", newClass); newClass.addMethod(linksSetterMethod); newClass.addInterface(CLASS_POOL.get("com.jayway.jaxrs.hateoas.HateoasLinkBean")); StringBuilder cloneMethodBody = new StringBuilder(); for (Field field : ReflectionUtils.getFieldsHierarchical(entity.getClass())) { cloneMethodBody.append("com.jayway.jaxrs.hateoas.support.ReflectionUtils.setFieldHierarchical(this, \"" + field.getName() + "\", com.jayway.jaxrs.hateoas.support.ReflectionUtils.getFieldValueHierarchical(other, \"" + field.getName() + "\"));"); } String method = "public void hateoasCopy(" + entity.getClass().getName() + " other ){ " + cloneMethodBody.toString() + "}"; CtMethod cloneMethod = CtMethod.make(method, newClass); newClass.addMethod(cloneMethod); URLClassLoader classLoader = new URLClassLoader(new URL[0], entity.getClass().getClassLoader()); clazz = newClass.toClass(classLoader, entity.getClass().getProtectionDomain()); TRANSFORMED_CLASSES.put(newClassName, clazz); } catch (Exception e) { if(e instanceof HateoasInjectException){ throw (HateoasInjectException)e; } throw new RuntimeException(e); } } } else { clazz = TRANSFORMED_CLASSES.get(newClassName); } Object newInstance = null; try { newInstance = clazz.newInstance(); Method copyMethod = newInstance.getClass().getMethod("hateoasCopy", entity.getClass()); copyMethod.invoke(newInstance, entity); } catch (Exception e) { log.error("could not create instance of " + clazz.getName(), e); } return injector.injectLinks(newInstance, linkProducer, verbosity); } }
JavassistHateoasLinkInjector implements HateoasLinkInjector<Object> { @Override public Object injectLinks(Object entity, LinkProducer<Object> linkProducer, final HateoasVerbosity verbosity) { if (entity == null) { return null; } String newClassName = entity.getClass().getPackage().getName() + "." + entity.getClass().getSimpleName() + "_generated"; Class<?> clazz; if (!TRANSFORMED_CLASSES.containsKey(newClassName)) { synchronized (this) { try { log.debug("Creating HATEOAS subclass for DTO : {}", entity.getClass()); boolean valid = false; for (Constructor<?> c : entity.getClass().getConstructors()) { if (c.getParameterTypes().length == 0) { valid = true; break; } } if (!valid){ throw new HateoasInjectException("DTO's must have no arg constructor. Check " + entity.getClass().getName()); } CtClass newClass = CLASS_POOL.makeClass(newClassName); newClass.setSuperclass(CLASS_POOL.get(entity.getClass().getName())); CtConstructor ctConstructor = new CtConstructor(new CtClass[0], newClass); ctConstructor.setBody("super();"); newClass.addConstructor(ctConstructor); CtField newField = CtField.make("public java.util.Collection links;", newClass); newClass.addField(newField); CtMethod linksGetterMethod = CtMethod.make("public java.util.Collection getLinks(){ return this.links; }", newClass); newClass.addMethod(linksGetterMethod); CtMethod linksSetterMethod = CtMethod.make("public void setLinks(java.util.Collection links){ this.links = links; }", newClass); newClass.addMethod(linksSetterMethod); newClass.addInterface(CLASS_POOL.get("com.jayway.jaxrs.hateoas.HateoasLinkBean")); StringBuilder cloneMethodBody = new StringBuilder(); for (Field field : ReflectionUtils.getFieldsHierarchical(entity.getClass())) { cloneMethodBody.append("com.jayway.jaxrs.hateoas.support.ReflectionUtils.setFieldHierarchical(this, \"" + field.getName() + "\", com.jayway.jaxrs.hateoas.support.ReflectionUtils.getFieldValueHierarchical(other, \"" + field.getName() + "\"));"); } String method = "public void hateoasCopy(" + entity.getClass().getName() + " other ){ " + cloneMethodBody.toString() + "}"; CtMethod cloneMethod = CtMethod.make(method, newClass); newClass.addMethod(cloneMethod); URLClassLoader classLoader = new URLClassLoader(new URL[0], entity.getClass().getClassLoader()); clazz = newClass.toClass(classLoader, entity.getClass().getProtectionDomain()); TRANSFORMED_CLASSES.put(newClassName, clazz); } catch (Exception e) { if(e instanceof HateoasInjectException){ throw (HateoasInjectException)e; } throw new RuntimeException(e); } } } else { clazz = TRANSFORMED_CLASSES.get(newClassName); } Object newInstance = null; try { newInstance = clazz.newInstance(); Method copyMethod = newInstance.getClass().getMethod("hateoasCopy", entity.getClass()); copyMethod.invoke(newInstance, entity); } catch (Exception e) { log.error("could not create instance of " + clazz.getName(), e); } return injector.injectLinks(newInstance, linkProducer, verbosity); }  }
JavassistHateoasLinkInjector implements HateoasLinkInjector<Object> { @Override public Object injectLinks(Object entity, LinkProducer<Object> linkProducer, final HateoasVerbosity verbosity) { if (entity == null) { return null; } String newClassName = entity.getClass().getPackage().getName() + "." + entity.getClass().getSimpleName() + "_generated"; Class<?> clazz; if (!TRANSFORMED_CLASSES.containsKey(newClassName)) { synchronized (this) { try { log.debug("Creating HATEOAS subclass for DTO : {}", entity.getClass()); boolean valid = false; for (Constructor<?> c : entity.getClass().getConstructors()) { if (c.getParameterTypes().length == 0) { valid = true; break; } } if (!valid){ throw new HateoasInjectException("DTO's must have no arg constructor. Check " + entity.getClass().getName()); } CtClass newClass = CLASS_POOL.makeClass(newClassName); newClass.setSuperclass(CLASS_POOL.get(entity.getClass().getName())); CtConstructor ctConstructor = new CtConstructor(new CtClass[0], newClass); ctConstructor.setBody("super();"); newClass.addConstructor(ctConstructor); CtField newField = CtField.make("public java.util.Collection links;", newClass); newClass.addField(newField); CtMethod linksGetterMethod = CtMethod.make("public java.util.Collection getLinks(){ return this.links; }", newClass); newClass.addMethod(linksGetterMethod); CtMethod linksSetterMethod = CtMethod.make("public void setLinks(java.util.Collection links){ this.links = links; }", newClass); newClass.addMethod(linksSetterMethod); newClass.addInterface(CLASS_POOL.get("com.jayway.jaxrs.hateoas.HateoasLinkBean")); StringBuilder cloneMethodBody = new StringBuilder(); for (Field field : ReflectionUtils.getFieldsHierarchical(entity.getClass())) { cloneMethodBody.append("com.jayway.jaxrs.hateoas.support.ReflectionUtils.setFieldHierarchical(this, \"" + field.getName() + "\", com.jayway.jaxrs.hateoas.support.ReflectionUtils.getFieldValueHierarchical(other, \"" + field.getName() + "\"));"); } String method = "public void hateoasCopy(" + entity.getClass().getName() + " other ){ " + cloneMethodBody.toString() + "}"; CtMethod cloneMethod = CtMethod.make(method, newClass); newClass.addMethod(cloneMethod); URLClassLoader classLoader = new URLClassLoader(new URL[0], entity.getClass().getClassLoader()); clazz = newClass.toClass(classLoader, entity.getClass().getProtectionDomain()); TRANSFORMED_CLASSES.put(newClassName, clazz); } catch (Exception e) { if(e instanceof HateoasInjectException){ throw (HateoasInjectException)e; } throw new RuntimeException(e); } } } else { clazz = TRANSFORMED_CLASSES.get(newClassName); } Object newInstance = null; try { newInstance = clazz.newInstance(); Method copyMethod = newInstance.getClass().getMethod("hateoasCopy", entity.getClass()); copyMethod.invoke(newInstance, entity); } catch (Exception e) { log.error("could not create instance of " + clazz.getName(), e); } return injector.injectLinks(newInstance, linkProducer, verbosity); }  @Override boolean canInject(Object entity); @Override Object injectLinks(Object entity, LinkProducer<Object> linkProducer,
                              final HateoasVerbosity verbosity); }
JavassistHateoasLinkInjector implements HateoasLinkInjector<Object> { @Override public Object injectLinks(Object entity, LinkProducer<Object> linkProducer, final HateoasVerbosity verbosity) { if (entity == null) { return null; } String newClassName = entity.getClass().getPackage().getName() + "." + entity.getClass().getSimpleName() + "_generated"; Class<?> clazz; if (!TRANSFORMED_CLASSES.containsKey(newClassName)) { synchronized (this) { try { log.debug("Creating HATEOAS subclass for DTO : {}", entity.getClass()); boolean valid = false; for (Constructor<?> c : entity.getClass().getConstructors()) { if (c.getParameterTypes().length == 0) { valid = true; break; } } if (!valid){ throw new HateoasInjectException("DTO's must have no arg constructor. Check " + entity.getClass().getName()); } CtClass newClass = CLASS_POOL.makeClass(newClassName); newClass.setSuperclass(CLASS_POOL.get(entity.getClass().getName())); CtConstructor ctConstructor = new CtConstructor(new CtClass[0], newClass); ctConstructor.setBody("super();"); newClass.addConstructor(ctConstructor); CtField newField = CtField.make("public java.util.Collection links;", newClass); newClass.addField(newField); CtMethod linksGetterMethod = CtMethod.make("public java.util.Collection getLinks(){ return this.links; }", newClass); newClass.addMethod(linksGetterMethod); CtMethod linksSetterMethod = CtMethod.make("public void setLinks(java.util.Collection links){ this.links = links; }", newClass); newClass.addMethod(linksSetterMethod); newClass.addInterface(CLASS_POOL.get("com.jayway.jaxrs.hateoas.HateoasLinkBean")); StringBuilder cloneMethodBody = new StringBuilder(); for (Field field : ReflectionUtils.getFieldsHierarchical(entity.getClass())) { cloneMethodBody.append("com.jayway.jaxrs.hateoas.support.ReflectionUtils.setFieldHierarchical(this, \"" + field.getName() + "\", com.jayway.jaxrs.hateoas.support.ReflectionUtils.getFieldValueHierarchical(other, \"" + field.getName() + "\"));"); } String method = "public void hateoasCopy(" + entity.getClass().getName() + " other ){ " + cloneMethodBody.toString() + "}"; CtMethod cloneMethod = CtMethod.make(method, newClass); newClass.addMethod(cloneMethod); URLClassLoader classLoader = new URLClassLoader(new URL[0], entity.getClass().getClassLoader()); clazz = newClass.toClass(classLoader, entity.getClass().getProtectionDomain()); TRANSFORMED_CLASSES.put(newClassName, clazz); } catch (Exception e) { if(e instanceof HateoasInjectException){ throw (HateoasInjectException)e; } throw new RuntimeException(e); } } } else { clazz = TRANSFORMED_CLASSES.get(newClassName); } Object newInstance = null; try { newInstance = clazz.newInstance(); Method copyMethod = newInstance.getClass().getMethod("hateoasCopy", entity.getClass()); copyMethod.invoke(newInstance, entity); } catch (Exception e) { log.error("could not create instance of " + clazz.getName(), e); } return injector.injectLinks(newInstance, linkProducer, verbosity); }  @Override boolean canInject(Object entity); @Override Object injectLinks(Object entity, LinkProducer<Object> linkProducer,
                              final HateoasVerbosity verbosity);  }