I've just started developing plugins in jenkins and tried to implement a root action by writing a plugin which implements RootAction. From the documentation of this interface (http://javadoc.jenkins-ci.org/?hudson/model/RootAction.html) it seems very easy compared to other plugins but I'm not getting it to work..
Here is my class which implements RootAction:
#Extension
public class MultiActionView implements RootAction {
public String getIconFileName() {
return "/plugins/multi-action-view/images/24x24/myPicture.png";
}
public String getDisplayName() {
return "My RootAction";
}
public String getUrlName() {
return "http://www.stackoverflow.com/";
}
}
I see that my plugin is installed but nothing shows in the sidepanel despite it says in the documentation that the rootaction will be added automatically. I've tried with and without an index.jelly file in the appropriate folder of my project but with no positive results.
Does anyone have any idea of why this plugin is not showing or can come with a working example of how to create a simple root action in jenkins? Thanks!
// Bogge
Related
I'm working on a Quarkus extension that provides an interceptor (and its annotation) to add some retry logic around business methods this extension offers. Nothing new in there, and this is working when i annotate a public method of a bean in an application that uses this extension.
But the extension also provides some #ApplicationScoped beans that are also annotated, but the interceptor is not intercepting any of these.
Seems like an interceptor does not check / apply on the extension itself.
I would like to know if this is an intended behavior, or an issue in my extension setup, and if so how to fix it. Could not find anything about this in the documentation, but there is so much dos that i may have missed something.
Any idea about this ?
I finally found a way to make this work.
I was using a producer bean pattern to produce my beam as an #ApplicationScoped bean inside the extension.
#ApplicationScoped
public class ProxyProducer {
#Produces
#ApplicationScoped
public BeanA setUpBean(ExtensionConfig config)
{
return new BeamsClientProxy(new InternalBean(config.prop1, config.prop2));
}
}
with the following BeanA class (just an example)
public class BeanA {
private final InternalBean innerBean;
public BeanA(final InternalBean innerBean) {
this.innerBean = innerBean;
}
#MyInterceptedAnnotation
public void doSomething() {
}
}
Due to this setup, the bean is not considered by the interceptor (i guess because it's produced only the first time it's used / injected somewhere else)
Removing the producer pattern and annotating directly the BeanA fixed the issue.
Example:
#ApplicationScoped
public class BeanA {
private final InternalBean innerBean;
public BeanA(final ExtensionConfig config) {
this.innerBean = new InternalBean(config.prop1, config.prop2);
}
#MyInterceptedAnnotation
public void doSomething() {
}
}
with of course adding the following lines to register the bean directly on the extension processor:
#BuildStep
AdditionalBeanBuildItem proxyProducer() {
return AdditionalBeanBuildItem.unremovableOf(BeanA.class);
}
As a conclusion:
Changing the bean implementation to avoid the producer-based bean use case solved my issue (please refers to Ladicek comment below)
Edit:
As Ladicek explained, Quarkus doesn't support interception on producer-based beans.
I am trying out ABP 4.0 using the Blazor UI and want to override the built-in view for User Management.
Inspecting the source code I found the UserManagement.razor file which has the route of "/identity/users" - this matches the view that I want to override.
I have (I believe) followed the steps listed at: https://docs.abp.io/en/abp/latest/UI/Blazor/Customization-Overriding-Components. However when running the site, I still get the standard, built-in user list.
Pages/Identity/UserManagement.razor (within my wwwroot folder):
#inherits Volo.Abp.Identity.Blazor.Pages.Identity.UserManagement
<h2>This is not the standard page</h2>
Pages/Identity/UserManagement.razor.cs
using Volo.Abp.DependencyInjection;
namespace BlazorDemo.Blazor.Pages.Identity
{
[ExposeServices(typeof(UserManagement))]
[Dependency(ReplaceServices = true)]
public partial class UserManagement
{
}
}
Have I missed something here?
Use a diffent name for your own component, like MyUserManagement.razor. Otherwise, compoiler can not distinguish the classes. For example,
using Volo.Abp.DependencyInjection;
namespace BlazorDemo.Blazor.Pages.Identity
{
[ExposeServices(typeof(UserManagement))] //MUST BE Volo.Abp.Identity.Blazor.Pages.Identity.UserManagement
[Dependency(ReplaceServices = true)]
public partial class UserManagement
{
}
}
Here, ExposeServices exposes itself (your class) instead of the Volo.Abp.Identity.Blazor.Pages.Identity.UserManagement. If you rename your component to MyUserManagement than you don't make such mistakes :)
I have seen this post: Nancy: how do I capture all requests irrespective of verb or path and followed along on the github article.
But it does not work. I have simply added a class in my project:
public class MyBootstrapper : Nancy.DefaultNancyBootstrapper
But this class is never instantiated, and the github documentation does not discuss this in any detail.
What do I need to do to cause my bootstrapper to be used?
I found it. There are two ways to add items to the pipeline. One by deriving a Bootstrap class, which failed for me. The other by implementing a class which honored the IApplicationStartup interface. That worked, and here is the code:
public class BeforeAllRequests : IApplicationStartup
{
public void Initialize(IPipelines pipelines)
{
pipelines.BeforeRequest.AddItemToStartOfPipeline(ctx => {
if (ctx != null)
{
Log.Debug("Request: " + ctx.Request.Url);
}
return null;
});
}
}
This worked for me (4 years later, maybe the Wiki changed since then): Bootstrapper
I've been reading through a lot of the Jabbr code to learn Nancy and trying to implement many of the same patterns in my own application. One of the things I can't seem to get working is the concept of an on application start class. The Jabbr code base has an App_Start folder with a Startup.cs file (here) in it with the following implementation.
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
...
SetupNancy(kernel, app);
...
}
}
private static void SetupNancy(IKernel kernel, IAppBuilder app)
{
var bootstrapper = new JabbRNinjectNancyBootstrapper(kernel);
app.UseNancy(bootstrapper);
}
When I tried to do something similar to that in my project the Startup.cs file was just ignored. I searched the Jabbr code base to see if it was used anywhere but I wasn't able to find anything and the only differences I could see is Jabbr uses Ninject while I wanted to use AutoFac
Is there a way to register a startup class in nancy?
Take a look at my project over on GitHub, you'll be interested in the Spike branch and may have to unload the ChainLink.Web project to run I can't remember.
I had some trouble finding a way to configure the ILifetimeScope even after reading the accepted answer here by TheCodeJunkie. Here's how you do the actual configuration:
In the bootstrapper class derived from the AutofacNancyBootstrapper, to actually configure the request container, you update the ILifetimeScope's component registry.
protected override void ConfigureRequestContainer(
ILifetimeScope container, NancyContext context)
{
var builder = new ContainerBuilder();
builder.RegisterType<MyDependency>();
builder.Update(container.ComponentRegistry);
}
The application container can be updated similarly in the ConfigureApplicationContainer override.
You should install the Nancy.Bootstrappers.Autofac nuget, inherit from the AutofacNancyBootstrapper type and override the appropriate method (depending on your lifetime scope requirements: application or request). For more info check the readme file https://github.com/nancyfx/nancy.bootstrappers.autofac
HTH
After following the advice from TheCodeJunkie you can use the Update method on the ILifetimeScope container parameter which gives you a ContainerBuilder through an Action:
protected override void ConfigureRequestContainer(ILifetimeScope container, NancyContext context)
{
container.Update(builder =>
{
builder.RegisterType<MyType>();
});
}
I found that I was unable to return collections from my JAX-WS Web Service.
I appreciate that the Java Collections API may not be supported by all clients, so I switched to return an array, but I can't seem to do this either.
I've set up my web service as follows:
#WebService
public class MyClass {
public ReturnClass[] getArrayOfStuff() {
// extremely complex business logic... or not
return new ReturnClass[] {new ReturnClass(), new ReturnClass()};
}
}
And the ReturnClass is just a POJO. I created another method that returns a single instance, and that works. It just seems to be a problem when I use collections/arrays.
When I deploy the service, I get the following exception when I use it:
javax.xml.bind.MarshalException - with linked exception:
[javax.xml.bind.JAXBException: [LReturnClass; is not known to this context]
Do I need to annotate the ReturnClass class somehow to make JAX-WS aware of it?
Or have I done something else wrong?
I am unsure of wheter this is the correct way to do it, but in one case where I wanted to return a collection I wrapped the collection inside another class:
#WebService
public class MyClass {
public CollectionOfStuff getArrayOfStuff() {
return new CollectionOfStuff(new ReturnClass(), new ReturnClass());
}
}
And then:
public class CollectionOfStuff {
// Stuff here
private List<ReturnClass> = new ArrayList<ReturnClass>();
public CollectionOfStuff(ReturnClass... args) {
// ...
}
}
Disclaimer: I don't have the actual code in front of me, so I guess my example lacks some annotations or the like, but that's the gist of it.