Solve the circular dependencies error with Jackson, without using annotations - spring

Currently, I'm writing some webapp using Spring framework. For all #RestController APIs, I use Jackson to generate Json objects.
The #RestController looks like
#RestController
#RequestMapping("/api")
public class SomeAPI {
#RequestMapping(method = RequestMethod.GET)
public A getA() {
A a = new A();
return a;
}
}
But there are circular dependency problems when two objects have bi-direction-reference. For example, there are two POJO classes as follows:
class A {
private B b;
// constructor
...
// setters and getters.
...
}
class B {
private A a;
// constructor
...
// setters and getters.
...
}
I can solve it easily by this way, using annotations: http://java.dzone.com/articles/circular-dependencies-jackson
But that's not my point.
Now, I cannot change the code of A and B classes, so that I cannot use any annotations in them. Then how can I solve this problem without using annotations?
Thanks in advance for any advice!

Finally, I've found the Mixin Annotations to solve the circular without touching the existing POJO.
There is a reference of Minin Annotations here: http://wiki.fasterxml.com/JacksonMixInAnnotations
The following is a brief steps to use Mixin:
Add ObjectMapper to your web-spring-servlet.xml
<bean id="myFrontObjectMapper" class="my.anying.web.MyObjectMapper"></bean>
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="myObjectMapper"></property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
Implement MyObjectMapper
public class MyObjectMapper extends ObjectMapper {
public MyObjectMapper() {
this.registerModule(new MixinModule());
}
}
Implement MixinModule
public class MixinModule extends SimpleModule {
private static final long serialVersionUID = 8115282493071814233L;
public MixinModule() {
super("MixinModule", new Version(1, 0, 0, "SNAPSHOT", "me.anying",
"web"));
}
public void setupModule(SetupContext context) {
context.setMixInAnnotations(Target.class, TargetMixin.class);
}
}
Done.
Now all annotations on TargetMixin class will be applied to Target class.

Related

I want to load a specific class based on a flag instead of loading two class and using one the required in Springs

In configurations I have a flag isFlagEnabled.
So I have to read the flag from spring config and based on that I want to execute specific class A or B . Meaning I want to load A class only when isFlagEnabled is true and similarly load class B only when isFlagEnabled is false.
I have written the below code but i am stuck when ingesting .
public interface MediatorInt {
public void init();
}
class A implements MediatorInt {
init() { It does some task }
}
class B implements MediatorInt {
init(){ It does some task }
}
public class MasterNewGenImpl {
#Autowired
#Qualifier("config")
private Configuration config;
#Autowired
MediatorInt mediatorInt;
private final Logger logger = Logger.getLogger(getClass());
public void startService() {
mediatorInt.init();
}
}
context.xml file
<context:component-scan base-package="com.ca"/>
<bean id="config" class="com.ca.configuration.ConfigImplementation"/>
<bean id="masterSlave" class="com.ca.masterslave.A"/>
<bean id="systemState" class="com.ca.masterslave.B"/>
<bean id="masterSlaveNewGen" class="com.ca.masterslave.MasterNewGenImpl">
<property name = "mediatorOrMasteSlave" value="#{config.getMediatorMode() == 'true' ? 'systemState' : 'masterSlave'}" />
</bean>
So now i am not getting how to inject specific object based on the config flag . I want to make it through Lazy-init so that other object will not get loaded when its not required .
I greatly appreciate the suggestions.
If you are okay with spring scanning both the implementations, then you can select the needed one using #Qualifier. If you want spring not to scan some class based on a property, You can use #Conditional
class SomeCondition implements Condition {
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String isFlagEnabled = context.getEnvironment().getProperty("isFlagEnabled");
return isFlagEnabled.equals("true"));
}
}
#Configuration
#Conditional(value = SomeCondition.class)
class A implements MediatorInt {
init() { It does some task }
}
In the above config, class A is scanned only if matches() in SomeCondition class returns true, where you can define the condition.
You can use
#Autowired
#Qualifier( "systemState" )
MediatorInt systemSateMeidator;
#Autowired
#Qualifier( "masterSlave" )
MediatorInt masterSateMeidator;
With #Qualifier you are instructing spring on how to fulfill your component request.

Define and inject a map in EJB 3.1 or CDI

After several years developing in Spring, I switched to EJB and I am not happy that I have no solution for this use-case. Let's say it is the strategy pattern implemented by a map. In Spring, it could look like this.
<bean id="myBean" class="MyBeanImpl">
<property name="handlers">
<map>
<entry key="foo" value-ref="fooHandler"/>
<entry key="bar" value-ref="barHandler"/>
</map>
</property>
</bean>
In EJB/CDI, I have this.
#Stateless
public class MyBeanImpl implements MyBean {
private Map<String, Class<? extends Handler>> handlers = new HashMap<>();
#PostConstruct
public void init() {
handlers.put("foo", FooHandlerImpl.class);
handlers.put("bar", BarHandlerImpl.class);
}
//jndi lookup handlerClass.getSimpleName()
}
Mind that jndi lookup works with implementations, not interfaces. Isn't there any better solution? And no, I do not want to have separate fields (foo, bar), inject them and create the map afterwards (It can be huge list and changed often). Ideally, in case of any configuration change, I would not touch the MyBeanImpl class at all.
The more CDI like way would look something like:
#Qualifier
#Target({ TYPE, METHOD, PARAMETER, FIELD })
#Retention(RUNTIME)
#Documented
public #interface Handles {
String value();
}
public class HandlerLiteral extends AnnotationLiteral<Handles> implements Handles{
private final String value;
public HandlerLiteral(String value) {
this.value = value;
}
#Override
public String value() {
return value;
}
}
You would then annotate each of your Handler implementations with #Handles("someName"), e.g. the class name as you're using it here. The use of a qualifier here is more in line with how CDI works, and we use the internal Instance object to resolve appropriate beans. Then in your service code (or wherever) you would simply do:
#Inject #Any
private Instance<HandlerService> handlerInstance;
...
handlerInstance.select(new HandlerLiteral("whateverName")).get().handle(context);
If you're really constrained to using a map, this wouldn't work for you. But this should allow for more dynamic registration and essentially looks at every handler in your context.
Try this:
#Inject #Any
private Instance<Handler> handlers;
private Map<String, Handler> handlerMap = new HashMap<>();
#PostConstruct
private void init() {
for (Handler handler : handlers) {
handlerMap.put(handler.getName(), handler);
}
}
assuming your Handler interface has some sort of getName() method.

Spring can you autowire inside an abstract class?

Spring is failing to autowire my object? Is it possible to autowire an object within an abstract class. Assume all schemas are supplied in application-context.xml
Question: What annotation should be on the base and extending classes (if any) #Service #Component?
Example
abstract class SuperMan {
#Autowire
private DatabaseService databaseService;
abstract void Fly();
protected void doSuperPowerAction(Thing thing) {
//busy code
databaseService.save(thing);
}
}
Extending class
public class SuperGirl extends SuperMan {
#Override
public void Fly() {
//busy code
}
public doSomethingSuperGirlDoes() {
//busy code
doSuperPowerAction(thing)
}
application-context.xml
<context:component-scan base-package="com.baseLocation" />
<context:annotation-config/>
I have that kind of spring setup working
an abstract class with an autowired field
public abstract class AbstractJobRoute extends RouteBuilder {
#Autowired
private GlobalSettingsService settingsService;
and several children defined with #Component annotation.
Normally, Spring should do the autowiring, as long as your abstract class is in the base-package provided for component scan.
See this and this for further reference.
#Service and #Component are both stereotypes that creates beans of the annotated type inside the Spring container. As Spring Docs state,
This annotation serves as a specialization of #Component, allowing for
implementation classes to be autodetected through classpath scanning.
What if you need any database operation in SuperGirl you would inject it again into SuperGirl.
I think the main idea is using the same object reference in different classes.
So what about this:
//There is no annotation about Spring in the abstract part.
abstract class SuperMan {
private final DatabaseService databaseService;
public SuperMan(DatabaseService databaseService) {
this.databaseService = databaseService;
}
abstract void Fly();
protected void doSuperPowerAction(Thing thing) {
//busy code
databaseService.save(thing);
}
}
#Component
public class SuperGirl extends SuperMan {
private final DatabaseService databaseService;
#Autowired
public SuperGirl (DatabaseService databaseService) {
super(databaseService);
this.databaseService = databaseService;
}
#Override
public void Fly() {
//busy code
}
public doSomethingSuperGirlDoes() {
//busy code
doSuperPowerAction(thing)
}
In my opinion, inject once run everywhere :)
In my case, inside a Spring4 Application, i had to use a classic Abstract Factory Pattern(for which i took the idea from - http://java-design-patterns.com/patterns/abstract-factory/) to create instances each and every time there was a operation to be done.So my code was to be designed like:
public abstract class EO {
#Autowired
protected SmsNotificationService smsNotificationService;
#Autowired
protected SendEmailService sendEmailService;
...
protected abstract void executeOperation(GenericMessage gMessage);
}
public final class OperationsExecutor {
public enum OperationsType {
ENROLL, CAMPAIGN
}
private OperationsExecutor() {
}
public static Object delegateOperation(OperationsType type, Object obj)
{
switch(type) {
case ENROLL:
if (obj == null) {
return new EnrollOperation();
}
return EnrollOperation.validateRequestParams(obj);
case CAMPAIGN:
if (obj == null) {
return new CampaignOperation();
}
return CampaignOperation.validateRequestParams(obj);
default:
throw new IllegalArgumentException("OperationsType not supported.");
}
}
}
#Configurable(dependencyCheck = true)
public class CampaignOperation extends EO {
#Override
public void executeOperation(GenericMessage genericMessage) {
LOGGER.info("This is CAMPAIGN Operation: " + genericMessage);
}
}
Initially to inject the dependencies in the abstract class I tried all stereotype annotations like #Component, #Service etc but even though Spring context file had ComponentScanning for the entire package, but somehow while creating instances of Subclasses like CampaignOperation, the Super Abstract class EO was having null for its properties as spring was unable to recognize and inject its dependencies.After much trial and error I used this **#Configurable(dependencyCheck = true)** annotation and finally Spring was able to inject the dependencies and I was able to use the properties in the subclass without cluttering them with too many properties.
<context:annotation-config />
<context:component-scan base-package="com.xyz" />
I also tried these other references to find a solution:
http://www.captaindebug.com/2011/06/implementing-springs-factorybean.html#.WqF5pJPwaAN
http://forum.spring.io/forum/spring-projects/container/46815-problem-with-autowired-in-abstract-class
https://github.com/cavallefano/Abstract-Factory-Pattern-Spring-Annotation
http://www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring
https://www.madbit.org/blog/programming/1074/1074/#sthash.XEJXdIR5.dpbs
Using abstract factory with Spring framework
Spring Autowiring not working for Abstract classes
Inject spring dependency in abstract super class
Spring and Abstract class - injecting properties in abstract classes
Spring autowire dependency defined in an abstract class
Please try using **#Configurable(dependencyCheck = true)** and update this post, I might try helping you if you face any problems.

Spring beans with runtime initialization parameters

I have a class which needs
Dependency injection for various beans it uses
Runtime parameters for initialization
The class would look something similar to this
public class Validator {
#Autowired
private ServiceA serviceA;
#Autowired
private ServiceB serviceB;
private String s;
private ClassA a;
private ClassB b;
public void initialize(String s, ClassA a, ClassB b) {
this.s = s;
this.a = a;
this.b = b;
}
public void performTaskA() {
//use serviceA, serviceB, s, a and b
}
public void performTaskB() {
//use serviceA, serviceB, s, a and b
}
public void performTaskC() {
//use serviceA, serviceB, s, a and b
}
}
What are various options through which I can define the above class as spring bean (to take the advantage of dependency injection) and also make sure that the caller calls initialize() before calling any performTask*() methods?
Note - I am aware of Object getBean(String name, Object... args) throws BeansException; but it doesn't look good since we would loose type safety. Any other suggestions?
Update -
The solution mentioned here with lookup method injection is a nice option. Until it is implemented in spring, what's your opinion on the below alternative of using inner classes
public class MyService {
private ServiceA serviceA;
private ServiceB serviceB;
public class DataClass {
private Integer counter;
public DataClass(Integer counter) {
this.counter = counter;
}
public Integer performActionAndGetCount() {
serviceB.performAction();
return this.counter++;
}
}
}
//client module
MyService service = beanFactory.getBean("myService");
MyService.DataClass dataClass = service.new DataClass(1);
Any drawbacks of this approach?
Use component,service or repository annotation to annotate your class. This would enable your class to be considered as a spring bean and you can then use dependency injection and runtime initialization.
Make sure in your {dispatcher-servlet}.xml(replace the name in {} to the name you have given your dispatcher servlet in web.xml} file you have written this line
This can be accomplished using a combination of scope="prototype" and a <lookup-method>.
First, define the class you want to parameterize as a bean with scope="prototype". This will cause the context to generate a new instance every time the bean is requested.
<bean class="com.example.Validator" scope="prototype"/>
Then, define a "factory class" that will wrap the generation and initialization of new objects.
<bean class="com.example.ValidatorFactory">
<lookup-method name="newValidator"/>
</bean>
This class would look like this:
public class ValidatorFactory {
public Validator createValidator(String str, Class<?> classA, Class<?> classB) {
Validator v = newValidator();
v.initialize(str, classA, classB);
return v;
}
protected void newValidator() {
// Spring will implement this via AOP
}
}
This forces clients to go through a routine that will call initialize() while still loading beans via the Spring context.
I am not so clear about your requirement. But I think #PostConstruct annotated method can come to your rescue. You can find more details about #PostConstruct annotation here.
Hope this helps you. Cheers.

How to do Spring Lookup Method Injection with Annotations?

Is there any way to use Lookup Method Injection using annotations?
Given the following class:
#Service
public abstract class A {
protected abstract createB();
}
In order to get it to work I have to declare in spring applicationContext.xml the following:
<bean id="b" class="com.xyz.B">
</bean>
<bean id="a" class="com.xyz.A">
<lookup-method name="createB" bean="b"/>
</bean>
Even though I am using <context:component-scan base> I have to declare it also in the XML. Not a good approach I think.
How to do it with annotations?
It is possible to use javax.inject.Provider. All thanks go to Phil Webb.
public class MySingleton {
#Autowired
private Provider<MyPrototype> myPrototype;
public void operation() {
MyPrototype instance = myPrototype.get();
// do something with the instance
}
}
It is also possible with org.springframework.beans.factory.ObjectFactory if you want to keep up with Spring API
public class MySingleton {
#Autowired
private ObjectFactory<MyPrototype> myPrototypeFactory;
public void operation() {
MyPrototype instance = myPrototypeFactory.getObject();
// do something with the instance
}
}
you can read more in the documentation.
It is implemented only with Spring >= 4.1 See the ticket.
Finally introduced as #Lookup annotation. Here is discussion on how to use it.

Resources