Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Bamboo API - Lazy Init Exception Thrown While Iterating Through Plans and Build Results

Adam Myatt
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 1, 2012

In a class that extends com.atlassian.sal.api.scheduling.PluginJob I am iterating through all plans, then all result summaries of those plans.

Starting with :

PlanManager planManager = (PlanManager) ContainerManager.getComponent("planManager");

I then grab all plans (intentionally skipping permissions check) :

List<TopLevelPlan> list = planManager.getAllPlansUnrestricted();

Then for each Plan in a loop call the result summary list :

List<ResultSummary> results = resultsSummaryManager.getResultSummariesForPlan(plan, 0, 0);

Then for a single result :

ResultSummary res = results.get(0);

I try to get a List of all Comments, Commits, Authors etc. using calls like :

List<Commit> commits = res.getCommits();

That call seems to work, but when I check the SIZE of the list : commits.szie() I get a Lazy Init exxception :

net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection - no session or session was closed
at net.sf.hibernate.collection.PersistentCollection.initialize(PersistentCollection.java:209)
at net.sf.hibernate.collection.PersistentCollection.read(PersistentCollection.java:71)
at net.sf.hibernate.collection.Bag.iterator(Bag.java:256)
at com.atlassian.bamboo.resultsummary.BaseResultSummary.getCommits(BaseResultSummary.java:383)
at com.atlassian.bamboo.resultsummary.BaseResultSummary.getUniqueAuthors(BaseResultSummary.java:286)
at com.pronetbeans.bamboo.myplugin.MyExtendedJob.execute(MyExtendedJob.java:209)
at com.atlassian.sal.core.scheduling.TimerPluginScheduler$PluginTimerTask.run(TimerPluginScheduler.java:72)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)

If I comment it out It does the SAME thing for calls to getAuthors and getCommits.

Any ideas?

2 answers

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

1 vote
bmccoy
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
July 1, 2012

Hi Adam,

Any code that needs to access database objects outside of a web request (e.g. quartz jobs, event listeners, anything else asynchronous) will need to be ran inside a transaction.

To do this inject a com.atlassian.sal.api.transaction.TransactionTemplate into your job

transactionTemplate.execute(new TransactionCallback&lt;Object&gt;()
        {
            @Override
            public Object doInTransaction()
            {
                //do what ever it is you need to do
                return null;
            }
        });

Cheers,

Brydie

Adam Myatt
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 1, 2012

Thanks for the tip. As a folow up, how/which transactionManager do i inject? I tried a few different ones and none of them seem to provide a TransactionTemplate.

0 votes
bmccoy
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
July 2, 2012

You should be able to inject the transactionTemplate directly. Its a SAL class.

Adam Myatt
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 2, 2012

So i tried this :

TransactionTemplate transactionTemplate = (TransactionTemplate) ContainerManager.getInstance().getContainerContext().getComponent("transactionTemplate");

transactionTemplate.execute(new TransactionCallback() {

@Override
public Object doInTransaction() {

// do transaction stuff here

}

...where TransactionTemplate and TransactionCallback were imported from the com.atlassian.sal.api.transaction package.

When it executed It rows an exception the line where I retrieve the transactionTemplate :

org.springframework.transaction.support.TransactionTemplate cannot be cast to com.atlassian.sal.api.transaction.TransactionTemplate

It seems to want Spring's TransactionTemplate instead. If I import Springs TransactionTemplate and re-run it throws the same "cannot cast" error be weirder says it cannot cast Spring's TransactionTemplate to Spring's TransactionTemplate :

org.springframework.transaction.support.TransactionTemplate cannot be cast to org.springframework.transaction.support.TransactionTemplate

Any ideas?

bmccoy
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
July 2, 2012

Interesting. Bamboo has its own internal transactionTemplate which is the spring version. So when you call ContainerManager.getInstance... it must be returning you the Spring one.

We need to get it to return the Sal one. Is this a plugins 1 or plugins 2 plugin?

bmccoy
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
July 2, 2012

The weird cast X to X messages are usually due to different class loaders being used. So I'm guessing it is a plugins 2 plugin. In which case you should not be using the ComponentManager to get any of your dependencies.

Take a look at the component-import and component module types

https://developer.atlassian.com/display/PLUGINFRAMEWORK/Component+Import+Plugin+Module

https://developer.atlassian.com/display/PLUGINFRAMEWORK/Component+Plugin+Module

Essentially everything should be autowired. Any classes instantiated by the plugin framework get autowired automagically, so you can just add the managers it need to its constructor (or setters) and the plugin framework will inject them in for you.

Adam Myatt
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 2, 2012

I tried this :

<component-import key="transactionTemplate">
<interface>com.atlassian.sal.api.transaction.TransactionTemplate</interface>
</component-import>

And then in my class added it via :

private TransactionTemplate transactionTemplate;

with getter/setter :

public TransactionTemplate getTransactionTemplate() {
return transactionTemplate;
}

public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}

Doesn't seem to work as when i run the plugin the transactionTemplate is null.

Adam Myatt
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 12, 2012

Any ideas on my latest comment?

bmccoy
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
July 15, 2012

Perhaps the class you are trying to inject the transaction template into is not being created by the plugin framework? How does the class get created?

TAGS
AUG Leaders

Atlassian Community Events