+ All Categories
Home > Documents > Decoupling shared code with state that needs to cleared in between uses

Decoupling shared code with state that needs to cleared in between uses

Date post: 14-Apr-2017
Category:
Upload: michael-fons
View: 128 times
Download: 0 times
Share this document with a friend
35
Decoupling shared code with state that needs to be cleared/reinstantiated after each use Tim Fritschel Michael Fons
Transcript

Decoupling shared code with state that needs to be cleared/reinstantiated after each use

Tim FritschelMichael Fons

Why are we here today, again?

• We are here to learn about method injection – specifically a kind of method injection called “lookup-method” in the Spring framework.– What it is…– How/why it is used…– To walk through an actual example.

Why are we using Spring?

• Oracle 11g SOA seems to use it by default in its configuration non-BPEL services.

• Our architects chose this for default configuration for new services.

• Spring has many good features, of which we want to take advantage – like…– SCA integration– Dependency injection– Many other advantages

Is it more complicated to program in Spring?

• Not really…mostly you just need to be aware of what the configuration file is doing too.

• Mostly it is just a matter of getting used to it.

Is Dependency Injection any good?

• Dependency Injection has many advantages; among them are…– Separating configuration from use/interfaces from

implementation.• Increasing testability.• Changing implementations without changing the

dependent class.• Promotes loose coupling and separation of

responsibilities.• Promotes code readability and simplicity.

Is method injection like dependency injection?

• The kind we are talking about is closely related.

• This kind of method injection addresses an issue with scoping, which I will cover a bit later.

Can you give me a real example of method injection?

• That’s exactly what I wanted to do next…• Our example will involve sharing common validation

code in our SOA 11g framework.• As part of the evolution of our S2F SOA 11g

architecture, we have debated with the architecture team to choose whether to put this shared code…– In the project– In the infrastructure library– In it’s own service

Was your shared code complex? Did it have state?

• Yes; the accumulation of error messages was its “state”.

• Without clearing this state, or re-instantiating the object, this state got garbled when called multiple times for that singleton.

What do you mean, Singleton?

• Spring-managed beans have “scope.”• Default scope is “singleton” – for each class

loader created, there is one instance created by the spring context (at Web server startup?).

• “Prototype” scope can be selected – which gets a new instance each time the dependent class is instantiated.

What if we just make the shared code “prototype” and left parent code “singleton?”

• In order to see any real effect with making a bean “prototype”, if it’s parent bean (i.e., the bean we are injecting the prototype bean into) is “singleton”, then we have two options within Spring– Make the parent “prototype” also.– Use method injection (“lookup-method”) and

inject a factory method for the child bean, into the parent bean.

What is wrong with making everything prototype?

• Well, that means that every call of the service gets a whole new set of objects allocated in memory.

• That could be needlessly wasteful in some cases, and could lead to server instability.

• I do not know if the architecture team has any experimental data on this possibility. They have not mentioned any yet…

OK…but “method injection” sounds weird and complex…

• It’s not too bad…there is not really a difference in the lines of code required.

• A group of us converted code that uses common code that had to have its state cleared each time because we had it set to singleton scope.

• With method-injection we were able to set this common code bean to prototype, without changing the parent bean from its default scope of “singleton”.

Why is method injection needed in this case?

• Look at http://static.springsource.org/spring/docs/2.5.x/spring-reference.pdf

• Within this document look at 3.3.7 and 3.3.7.1.

• If you do you will see the way we solved this problem, was the default way to solve this using Spring.

• This creates a factory method.

Are there other things you can do with method injection in Spring other than solving this

scoping issue?

• Yes. For example, Tim Fritschel told me that in a prior job he and his coworkers found a use of a more complex kind of Spring method injection to solve a particular kind of problem.

• Please ask him, or check Google/Spring website for more information.

Couldn’t you have just used “new” to create a new instance of VaoErrors?

• Yes, but VaoErrors required a datasource which was also conveniently supplied in Spring configuration file.

• So with “new” the code would be messier, passing datasource down with an additional parameter.– Or further mix and match by adding a dataSource property

to the Vao implementation, and injecting it there.• All this jumps around and increases code clutter and

detracts from the point of the code, making it less readable.

Let’s see what you did to convert this code…

New library, ok. What else?

Spring context has some bean changes…

• Yes, there were two changes to spring context.• There are two beans in use here…– Vao – this is the parent bean, that is using

vaoErrors.– vaoErrors – the child bean.

• Vao is Singleton scope.• VaoErrors is “prototype” scope.

Can you explain the changes further?

• Vao has gone from direct property injection, to injection via the “lookup-method” element.– This creates a deploy-time implementation of the

createVaoErrors method in the vao bean– When the method is called it will return an instance

of the vaoErrors bean (with the scope set in spring configuration).

– VaoErrors bean changes its scope to prototype now that we can use this scope without also changing the scope of the vao bean!

Great. What else do I have to do?

OK. The parent object needs the method we are injecting “declared”. What else?

What the hell?• OK, this is a bit weird, but listen…

– The “lookup-method” element actually instructs spring to sub-class the parent bean, and create an implementation (or override the existing implementation) of the specified method.

– The return-type of this method must be the same as the type of the bean mentioned in the “lookup-method” element’s “bean” attribute value.

– The name of the method must match the “name” attribute in the lookup-method element.

– It should take no arguments.– So since we will be implementing a method, it makes it easier to

remember to adjust for this by making the parent class “abstract”. Alternatively you could create a method with a don’t-care implementation, but this would be misleading.

OK. Fine. Is method injection better than clearing the state?

• Using this technique trades clearing the state with creating a new instance.

• After comparing these two approaches on many different levels, these two seem to be equivalent.

• Without the benefit of 20-20 hindsight, this equivalence was not apparent at the time we were considering our options; we thought we were improving things.

Right. What does that change look like?

OK, that makes sense. Added a factory call before the validation, and removed the “clearing” afterward. Anything else?

• No, that is the last code change.• If you have JUnit tests, you will need to alter

them a bit though.

Great. Is that hard?

• Not too bad. You have at least two choices here– Either subclass your parent and implement the

method which simply returns your new child bean (VaoErrors in this case).

– Or create a test context in your SCA-INF/src in project root, and copy in your bean definitions, so that spring continues to implement this method for you.

OK. What does the first solution look like?

That’s not too bad. What does the other look like?

OK, I need a dataSource and the parent and child beans. What else?

Need a property for the parent bean and the context, and you need to instantiate the context. What else?

Well, that’s all clean-up, right?

• Correct; the first change is because we no longer need to inject our datasource into the child since spring does this for us.

• The second change is to get the parent bean from the context and store it on our test class property we just created.

• The third change is more stuff that Spring now does for use…dependency injection, etc.

That’s great! Any other advantages?

Wow, I had not though of that!

• Yes, it’s true. You can actually conduct tests to verify that your method injection is working properly!

Hey man: thanks for the info, dude!

• Any time! See you at stand up!

What did you reference to get this information?

• SOA 11g implementation experiences here as S2F.

• http://martinfowler.com/articles/injection.html

• http://static.springsource.org/spring/docs/2.5.x/spring-reference.pdf (especially chapter 3 and section 3.3.7)

• http://javapapers.com/spring/dependency-injection-di-with-spring/#diadvantages


Recommended