Configure Spring Property of Subclass Field with Same Name as Parent's - java

Suppose I have the following classes:
package wild;
import moco.GeneralMovement;
public class Animal{
protected GeneralMovement movement;
public getMovement (){
return movement;
}
public void setMovement (GeneralMovement movement){
this.movement = movement;
}
}
package sur;
import loco.QuadripedalMovement;
import wild.Animal;
public class Mammal extends Animal{
protected QuadripedalMovement movement;
public QuadripedalMovement getMovement (){
return movement;
}
public void setMovement (QuadripedalMovement movement){
this.movement = movement;
}
public void test(){
super.movement.move();
}
}
package zoo;
import sur.Mammal;
public class Gorilla extends Mammal{
public void doSomething(){
test();
movement.grove();
}
}
package moco;
public class GeneralMovement {
public void move(){
System.out.println("Moving");
}
}
package loco;
import moco.GeneralMovement;
public class QuadripedalMovement extends GeneralMovement{
public void grove(){
System.out.println("Grooving...");
}
}
import zoo.Gorilla;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
private ApplicationContext ctx;
public static void main(String[] args) {
Test test = new Test();
test.doProcess();
}
public void doProcess(){
String cfgFiles[] = {"zoo.xml"};
ctx = new ClassPathXmlApplicationContext(cfgFiles);
Gorilla gorilla = (Gorilla) ctx.getBean("Gorilla");
gorilla.doSomething();
}
}
Then the following XML config:
<bean id="Gorilla" class="zoo.Gorilla">
<property name="movement">
<ref bean="QuadripedalMovement"/>
</property>
</bean>
<bean id="QuadripedalMovement" class="loco.QuadripedalMovement" />
</beans>
The above would give a NullPointerException upon calling doSomething() movement.grove().
Moving
Exception in thread "main" java.lang.NullPointerException
at zoo.Gorilla.doSomething(Gorilla.java:9)
at Test.doProcess(Test.java:64)
at Test.main(Test.java:49)
From what I understood from a little research this has something to do with Java not being capable of overriding fields. The above (please correct me if my understanding is wrong) would actually refer to two(?) different fields.
Why does the above code work when move() is invoked through using super keyword? Does this mean that Spring would assign the created QuadripedalMovement class to the parent field instead of the child's despite the class type being explicitly defined in the bean definition class attribute?
How do I configure spring to assign it to the (Mammal) subclass' field so I can reference it through an instance of Gorilla? I cannot modify the Java code for Animal and Gorilla. I can only modify the Mammal class. My temporary solution is to let Mammal implement InitializingBean and setting the value of movement there.
public void afterPropertiesSet() throws Exception {
this.movement = (QuadripedalMovement) super.movement;
}
But I've only recently began to study Spring (and Java) so I don't know if this is correct (or good practice). Any help would be appreciated.
Note: The above code is the same structure as the code I am currently studying. I cannot provide the original. The version of spring used is 2.5.6

Related

TestNG Listener equivalent for #BeforeClass, with access to context

I've spent several days looking for a way to move one of my #BeforeClass methods to listener class I can reference in xml where I define content os test suite.
Problem I'm facing is that I'm using Spring for DI, and in #BeforeClass method I add some attributes to testng context, so I can use them in other places (other listeners).
I tried using onStart(final ITestContext context) from ITestListener. But that method seems to be invoked before spring manages to create beans, and I cannot perform my operations, because all my beans are nulls.
I tried using onBeforeClass(ITestClass testClass) from IClassListener. But that method only provides ITestClass, which does not give me access to context, so I can't set my attributes.
Now I'm experimenting with onConfigurationSuccess(final ITestResult itr) from IConfigurationListener, but that requires using if statement to run my code only if configuration method name is equal to springTestContextPrepareTestInstance.
Does anyone know a better way of doing this?
[EDIT] code sample
#Component
public class CleanupHelper {
private static SomeBean someBean;
#Autowired
public CleanupHelper(SomeBean someBean){
CleanupHelper.someBean = someBean;
}
public static Object getSomething(){
return someBean.getSomething();
}
}
public class ExcludedGroupsListener implements IConfigurationListener {
#Override
public void onConfigurationSuccess(final ITestResult itr) {
if (itr.getName().contains("springTestContextPrepareTestInstance")) {
var something = CleanupHelper.getSomething();
if (something != null && someOtherCondition) {
itr.setAttribute("someObject", something);
}
}
}
}
#ContextConfiguration(classes = TestConfig.class)
public class SomeTests extends AbstractTestNGSpringContextTests {
#Test
public void someTest(){
// doSomething
}
}
#Configuration
#ComponentScan(basePackages = "com.some",
excludeFilters = #Filter(type = FilterType.REGEX, pattern = "com.some.else..*"))
public class TestConfig {
}
Above code works... unfortunately onConfigurationSuccess method is invoked after each configuration method.
Try with Annotation Transformers.
You can add it in your testng.xml like any other listener.
And in there you can do things like:
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.testng.IAnnotationTransformer;
import org.testng.annotations.ITestAnnotation;
public class TestAnnotationTransformer implements IAnnotationTransformer {
#SuppressWarnings("rawtypes")
#Override
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
if (testMethod.getName().equals("MyTest1"))
annotation.setGroups( new String[] {"GroupA" });
if(ignoreTestDependencies)
annotation.setIgnoreMissingDependencies(true);
}
}
Just an example, but you have many things there to play with.
Just bear in mind that, as I stated in the comments, this runs before runtime, so you won't be able to change things on the go like you would do with a normal listener.

how to make a bean prototype using only #scope("prototype) annotation in spring?

i have this main class
public class Draw {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Triangle t = (Triangle) context.getBean("triangle");
Triangle t1 = (Triangle) context.getBean("triangle");
t.show();
System.out.println(t == t1);
}
}
TRIANGLE CLASS
#Service
#Scope("prototype")
public class Triangle {
private Point pointa;
public Point getPointa() {
return pointa;
}
public Triangle(Point pointa) {
this.pointa = pointa;
}
public void show() {
System.out.println("POINT A (" + pointa.getX() + "," + pointa.getY() + ")");
}
#Override
public String toString() {
return "Triangle [pointa=" + pointa + "]";
}
}
AND SPRING.XML
<context:component-scan base-package="com.spring.demo" />
<mvc:annotation-driven />
<context:component-scan base-package="com.spring.demo" />
<bean id="triangle" class="com.spring.demo.Triangle" autowire="constructor">
</bean>
<bean id="pointabc" class="com.spring.demo.Point">
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<context:annotation-config />
i know that to make a bean prototype we use scope="prototype" in spring.xml.
but i want to make bean prototype by using #scope("prototype") only.
i don't know why the above code is not working correctly.
I've researched a lot but couldn't find any answer
System.out.println(t == t1); this gives me true while ideally it should be false.
Declaring Triangle as prototype has no effect as it is instantiated in your spring.xml as singleton.
The key is to ask for a new prototype bean everytime you need one.
This can be achieved by using a configuration class (and removing <bean id="triangle" ... from spring.xml:
package com.spring.demo;
#Configuration
public class MyProvider {
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Triangle create() {
return new Triangle();
}
}
Usage is as follows:
package com.spring.demo;
#Component
public class MySingleton {
#Autowired
private MyProvider myProvider;
#PostConstruct // will execute this method once app context loaded
public void doStuffThatNeedsAPrototypeBeanInstance() {
Triangle t1 = myProvider.create();
Triangle t2 = myProvider.create();
...
}
}
Adding a #PostConstruct has the effect that the method is called once the application context has been initialized, as alternative to running things in the main method. This way, execution is inside a spring bean with the benefit of easily accessing other spring beans through annotations.
As ApplicationContext has several implementations, ClassPathXmlApplicationContext one is used for XML bean configuration.
In XML ways you simply set the scope attribute in bean element.
AnnotationConfigApplicationContext is implementation of ApplicationContext used for Java Based Configuration means for annotation based configuration like #Bean etc.
If you want to use annotation way, then you need to define Java Based Configuration and need to use AnnotationConfigApplicationContext object.
#Configuration
public class AppConfiguration{
#Bean
#Scope("prototype")
public Triangle triangle(){
return new Triangle();
}
}
Then obtained the bean as below.
ApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfiguration.class);
Triangle triangle= ctx.getBean(Triangle.class);
for annotation configuration we use AnnotationConfigApplicationContext an implementation of Abstract Application Context
public class Scope{
public static void main(String[] args) {
AbstractApplicationContext context = new AnnotationConfigApplicationContext(TeacherConfig.class);
Teacher tea=(Teacher) context.getBean("teacher");
Teacher tea1=(Teacher) context.getBean("teacher");
System.out.println(tea==tea1);
}
}
TEACHER CLASS
public class Teacher {
public void print(String msg){
System.out.println("TEACHER -->"+msg);
}
TeacherConfig
#Configuration
public class TeacherConfig {
#Bean(name = "teacher")
#Scope(value=ConfigurableBeanFactory.SCOPE_SINGLETON)
public Teacher Teacher() {
return new Teacher();
}
}
#Configuration to tell Spring that this is the core Spring configuration file equivalent to spring.xml, and define bean via #Bean.
OUTPUT OF System.out.println(tea==tea1); is TRUE
By extending the answer given by #AshishUpadhyay, I made couple of changes in code. The above answer is for singleton scope. For prototype need to make few changes.
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class Scope{
public static void main(String[] args) {
AbstractApplicationContext context = new AnnotationConfigApplicationContext(TeacherConfig.class);
Teacher tea=(Teacher) context.getBean(Teacher.class);
Teacher tea1=(Teacher) context.getBean(Teacher.class);
System.out.println(tea);
System.out.println(tea1);
System.out.println(tea==tea1);
}
}
Teacher class:
public class Teacher {
public void print(String msg) {
System.out.println("TEACHER -->" + msg);
}
}
TeacherConfig class:
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
#Configuration
public class TeacherConfig {
#Bean()
#Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Teacher Teacher() {
return new Teacher();
}
}
After running the Scope class the output is false which is expected in case of prototype.
Hope this will help someone.

Proxy for abstract class without changing the usage

I have an abstract class (database mapping) implementing an interface where default implementations are injected at runtime (this is part of another library and cannot be changed).
I want to override one of the default implementation via a proxy (as that seems like the way to override this).
public abstract class Table1 implements Storable<Table1>
{
#Sequence("ID_SEQUENCE")
#Alias("ID")
public abstract String getID();
public abstract void setID(String ID);
#Alias("NAME")
public abstract String getAvailabilityZone();
public abstract void setAvailabilityZone(String value);
}
public interface Storable<S extends Storable<S>> {
//a bunch of method definition.
boolean tryLoad() throws Exception;
}
Let's say I want to override tryLoad() method to do my own things instead of what the generated code provides. Given the nature of the library, it is not something I can achieve by simple #Override.
The simple way this is currently used is as following:
public void method() {
Table1 t = Repository.storageFor(Table1.class).prepare();
t.setName( "temp" );
if (!t.tryLoad())
t.tryInsert();
}
I want to proxy tryLoad() without making changes in all the methods across the whole codebase - that would be to get proxied instance instead of actual one and perform the operation on that.
Is there any recommended way to achieve this?
Thanks!
I woke up last night and felt bored, so despite your lack of feedback I created a little Carbonado showcase project and shared it on GitHub. I made three commits:
Initial commit with Maven project already prepared for AspectJ and a JUnit test for me to find out how Carbonado actually works, because I had never used it before.
Add failing unit test for behaviour of tryLoad() expected to be provided by aspect.
Add aspect to make unit test pass. Aspect hooks into tryLoad() and auto-creates non-existent record. I do not know if I guessed right what you actually wanted to achieve, but if it was a different thing, just change the aspect implementation.
Sample code
Carbonado storable:
package de.scrum_master.app;
import com.amazon.carbonado.Nullable;
import com.amazon.carbonado.PrimaryKey;
import com.amazon.carbonado.Storable;
#PrimaryKey("ID")
public interface StoredMessage extends Storable<StoredMessage> {
long getID();
void setID(long id);
#Nullable String getMessage();
void setMessage(String message);
}
Aspect:
package de.scrum_master.aspect;
import com.amazon.carbonado.Storable;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class CarbonadoAspect {
#Around("call(boolean tryLoad()) && target(storable)")
public boolean tryInsertIfNotFound(ProceedingJoinPoint thisJoinPoint, Storable storable) throws Throwable {
System.out.println(thisJoinPoint);
if ((boolean) thisJoinPoint.proceed())
return true;
System.out.println("Not found: " + storable + " -> inserting");
return storable.tryInsert();
}
}
JUnit test:
package de.scrum_master.app;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.amazon.carbonado.FetchException;
import com.amazon.carbonado.PersistException;
import com.amazon.carbonado.Repository;
import com.amazon.carbonado.RepositoryException;
import com.amazon.carbonado.Storage;
import com.amazon.carbonado.SupportException;
import com.amazon.carbonado.repo.map.MapRepositoryBuilder;
import de.scrum_master.app.StoredMessage;
public class CarbonadoTest {
private Repository repo;
private Storage<StoredMessage> storage;
StoredMessage message;
#Before
public void setUp() throws Exception {
repo = MapRepositoryBuilder.newRepository();
storage = repo.storageFor(StoredMessage.class);
message = storage.prepare();
}
#After
public void tearDown() throws Exception {
repo.close();
repo = null;
storage = null;
message = null;
}
// (...)
#Test
public void aspectCreatesNonExistentRecord() throws SupportException, RepositoryException {
message.setID(1);
// Without the aspect this would be false
assertTrue(message.tryLoad());
assertEquals(message.getID(), 1);
assertEquals(message.getMessage(), null);
}
}
Enjoy!

AOP on methods implemented from interface Spring

I want to perform AOP on implemented method by an interface in a class.
Interface
package a.b.c;
public interface A
{
void f1(Object ob);
}
Class Implementation
package a.b.c.d;
public class B implements A
{
public void f1(Object ob){}
}
Advice
#Component
#Aspect
public class MyOwnAdvice
{
#Before("execution(public void a.b.c.A+.f1(..))")
public void f2()
{
System.out.println("MyOwnAdvice.f2()");
}
}
EDIT :
sorry for sharing half info.The actual implementation is like this :
package x.y;
public class NormalClass
{
A a;
void executeThis()
{
a.f1();
}
}
<bean class="x.y.NormalClass" id="normalClass" >
<property name="a" ref="b" />
</bean>
<bean class="a.b.c.d.B" id="b" />
Its not working for me.
Please update me if I am making any mistake.
Thanks
A objectA=new B(); is not dependency injection. Spring must create B and inject it, e.g.
...
#Autowired
A a;
...

Test cases in inner classes with JUnit

I read about Structuring Unit Tests with having a test class per class and an inner class per method. Figured that seemed like a handy way to organize the tests, so I tried it in our Java project. However, the tests in the inner classes doesn't seem to be picked up at all.
I did it roughly like this:
public class DogTests
{
public class BarkTests
{
#Test
public void quietBark_IsAtLeastAudible() { }
#Test
public void loudBark_ScaresAveragePerson() { }
}
public class EatTests
{
#Test
public void normalFood_IsEaten() { }
#Test
public void badFood_ThrowsFit() { }
}
}
Does JUnit not support this, or am I just doing it wrong?
You should annontate your class with #RunWith(Enclosed.class), and like others said, declare the inner classes as static:
#RunWith(Enclosed.class)
public class DogTests
{
public static class BarkTests
{
#Test
public void quietBark_IsAtLeastAudible() { }
#Test
public void loudBark_ScaresAveragePerson() { }
}
public static class EatTests
{
#Test
public void normalFood_IsEaten() { }
#Test
public void badFood_ThrowsFit() { }
}
}
public class ServicesTest extends TestBase {
public static class TestLogon{
#Test
public void testLogonRequest() throws Exception {
//My Test Code
}
}
}
Making the inner class static works for me.
In JUnit 5, you simply mark non-static inner classes as #Nested:
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
public class DogTests {
#Nested
public class BarkTests {
#Test
public void quietBark_IsAtLeastAudible() { }
#Test
public void loudBark_ScaresAveragePerson() { }
}
#Nested
public class EatTests {
#Test
public void normalFood_IsEaten() { }
#Test
public void badFood_ThrowsFit() { }
}
}
I think some of the answers might be for older versions of JUnit. In JUnit 4 this worked for me:
#RunWith(Suite.class)
#Suite.SuiteClasses({ DogTests.BarkTests.class, DogTests.EatTests.class })
public class DogTests
{
public static class BarkTests
{
#Test
public void quietBark_IsAtLeastAudible() { }
#Test
public void loudBark_ScaresAveragePerson() { }
}
public static class EatTests
{
#Test
public void normalFood_IsEaten() { }
#Test
public void badFood_ThrowsFit() { }
}
}
I've had success with Nitor Creation's Nested Runner as well.
How to use Nitor Creation's Nested Runner
There is a post explaining it here:
Add this dependency:
<dependency>
<groupId>com.nitorcreations</groupId>
<artifactId>junit-runners</artifactId>
<version>1.2</version>
<scope>test</scope>
</dependency>
And a #RunWith to your test:
import com.nitorcreations.junit.runners.NestedRunner
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
#RunWith(NestedRunner.class)
public class RepositoryUserServiceTest {
public class RegisterNewUserAccount {
public class WhenUserUsesSocialSignIn {
public class WhenUserAccountIsFoundWithEmailAddress {
#Test
public void shouldThrowException() {
assertTrue(true);
}
}
}
}
}
PS: The example code has been taken and modified from the above blog post
I just ran across this posting (11 years later) regarding the testing of inner classes. An inner class can be trivially converted to equivalent static form only if the class should have been static in the first place. Static inner classes are not really inner classes because there is no enclosing this. They have exactly the same semantics (except for visibility restrictions) as top-level classes.
To test a "true" inner class [one that depends on its enclosing instance] you need to use the interface that the Java language provides for creating inner class instances outside the scope of the enclosing class. That interface includes an extra parameter in each constructor which is the enclosing instance. In this way, the Java compiler converts an inner class to a special top-level class with a mangled name (lots of $ signs) and augmented constructors. The same transformation can be performed at the source level. In principle, these transformed classes can be tested but it is a complex process because the tested program has transformed syntax and the test code must construct a (mock) object that serves as the enclosing instance.
Another way to test true inner classes is to write an executable method contract for each method consisting of an executable logical pre-condition and an executable logical post-condition. Then these executable contracts can be evaluated in the course of running a conventional top-level test that invokes the inner class methods.
In practice, I typically settle for the indirect testing of inner class methods in the course of top-level testing. Writing and testing executable contracts for all methods is a more rigorous, albeit significantly more expensive, alternative.

Categories