Java Bean out of scope on Build Feature



I am trying to use pull data from a config file I have and display that data in a build feature I've created.  In my JSP file I have the following jsp tag:

<jsp:useBean id="adminPageConfigPersistenceManager" type="com.brianelliott.teamcity.agentSelector.Config.AdminPageConfigPersistenceManager" scope="request"/>

But I am getting the following error when trying to reference that object later down in my JSP file:

Error: java.lang.InstantiationException: bean adminPageConfigPersistenceManager not found within scope


<props:selectProperty name="agentSelector" id="agent.selector">
<c:forEach var="versions" items="${adminPageConfigPersistenceManager.configuredXcodeVersions}">
<props:option value="${versions.xcodeVersion}"><c:out value="${versions.xcodeVersion}"/></props:option>

I have this working in a SimpleCustomTab page for my admin config page, but that page has a fillModel() method that I used to be able to use the bean object in my JSP:

public void fillModel(@NotNull Map<String, Object> model, @NotNull HttpServletRequest request) {
super.fillModel(model, request);
model.put("adminPageConfigPersistenceManager", adminPageConfigPersistenceManager);

Working JSP usage:

<jsp:useBean id="adminPageConfigPersistenceManager" type="com.brianelliott.teamcity.agentSelector.Config.AdminPageConfigPersistenceManager" scope="request"/>

<c:forEach var="versions" items="${adminPageConfigPersistenceManager.configuredXcodeVersions}">
<c:set var="onclick">
ConfigTabDialog.showEditDialog(${}, '${versions.xcodeVersion}')
<td class="highlight" onclick="${onclick}">
<c:out value="${versions.xcodeVersion}"/>
<td class="edit highlight">
<a href="#" onclick="${onclick}; return false">edit</a>
<td class="edit">
<a href="#" onclick="ConfigTabDialog.deleteObject(${}); return false">delete</a>

Is it possible to do a similar implementation in the BuildFeature class?  I've checked the OpenAPI docs and I don't see anything that looks like I would be able to do this.  Is there a recommended method to go about this for a build feature? Maybe a better way to use a java object in my JSP?

I'm rather new to JSP files and Java so its possible I am doing something else wrong.  I'm happy to provide code snippets.


Official comment

Hi Brian, if I understand you correctly you need a custom controller implementation for you build feature settings dialog.  In broad strokes you have to extend BaseController overriding doHandle method in it. In that method you have to create an instance of ModelAndView and add the data you are planning to use in JSP to it using ModelAndView::addObject, then return it from doHandle method. The last thing you have to do is to return the same URL the controller is registered with from you implementation of BuildFeature::getEditParametersUrl. 

Please let us know if I misunderstood your question or you need some additional information to make it working for you. 


I'm able to make a new controller and I have it set to return a ModelAndView object with my data attached as an object.  I'm confused on the part where I return the same URL the controller is registered with from my implementation of the BuildFeature::getEditParametersUrl.  In this method I originally needed to return a path to my jsp file where I wrote the build feature jsp.  Do I need to return the new extended BaseController here by the url it is registered at? 


public String getEditParametersUrl() {
return "/xcodeVersions.html";

Or am I missing something?  Where do I provide the jsp for my build feature if I do not return the plugin resource path for it in the getEditParemetersUrl() method?


Alright, so I took what you said and did a big more digging and I was able to come to a solution.

I've changed my controller to have the following code

public class XcodeSelectorConfigController extends BaseController {

private AdminPageConfigPersistenceManager adminPageConfigPersistenceManager;
private PluginDescriptor pluginDescriptor;

public XcodeSelectorConfigController(final AdminPageConfigPersistenceManager adminPageConfigPersistenceManager, PluginDescriptor pluginDescriptor){
this.adminPageConfigPersistenceManager = adminPageConfigPersistenceManager;
this.pluginDescriptor = pluginDescriptor;

protected ModelAndView doHandle(@NotNull HttpServletRequest httpServletRequest, @NotNull HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView(pluginDescriptor.getPluginResourcesPath("editAgentSelector.jsp"));
final Map<String, Object> model = modelAndView.getModel();
model.put("xcodeVersions", adminPageConfigPersistenceManager);
return modelAndView;

And I have edited my BuildFeature class to have the following in the constructor

public AgentSelectorBuildFeature(PluginDescriptor pluginDescriptor, final @NotNull AgentSelectorServerListener serverListener, WebControllerManager webControllerManager) {
this.pluginDescriptor = pluginDescriptor;
this.adminPageConfigPersistenceManager = serverListener.getConfigModel();
webControllerManager.registerController(pluginDescriptor.getPluginResourcesPath("editAgentSelector.html"), new XcodeSelectorConfigController(adminPageConfigPersistenceManager, pluginDescriptor));

and a getEditParametersUrl method of the following

public String getEditParametersUrl() {
return pluginDescriptor.getPluginResourcesPath("editAgentSelector.html");

My JSP useBean tag is now

<jsp:useBean id="xcodeVersions" type="com.brianelliott.teamcity.agentSelector.Config.AdminPageConfigPersistenceManager" scope="request"/>



This is working and I am able to access my data object from my Build Feature.  This seems a lot more complex than the simple tab view, but I guess there is a lot more going on under the hood.  I used these two plugins/features as guidance to help me get to this point along with your help :)


They both implement what I was trying to do, but a bit more complex.  Hopefully someone else can benefit from this post, as this was all a bit unclear from the plugin docs.


Please sign in to leave a comment.