I am new to IOC.
I've MethodProfilerAspectAttribute attribute which has to be applied on any method like this
[MethodProfilerAspectAttribute(5)]
public void MethodName(){}
Here is the implementation of MethodProfilerAspectAttribute
[Serializable]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class MethodProfilerAspectAttribute : OnMethodBoundaryAspect
{
public ILogger logger { get; set; }
public int x{get;set;}
public MethodProfilerAspectAttribute(int x)
{
this.x=x;
}
public override void OnSuccess(MethodExecutionArgs args)
{
logger.CustomLogging("logMe");
base.OnSuccess(args);
}
}
I want to resolve my ILogger dependency using Log4NetLogger which is registered and resolving constructor dependencies properly by using following :
container.Register(Component.For<ILogger>().ImplementedBy(typeof(Log4NetLogger)));
but unfortunately whatever I've tried for resolving property dependency, is not working.
Any help would be greatly appreciated.
The link you provided just describes property injection for components resolved from the container. Attributes are not resolved from the container, but instead are created by the CLR. You might be able to jigger a way to set attribute properties by providing a custom IContributeComponentModelConstruction implementation, but I'm not so sure. See answers for similar questions here, here, and here (from the creator of Windsor).
In any case, attributes is not where you want to put functionality. They should be minimal, just providing metadata. I see here you're trying to provide some sort of functionality across all method invocations. You may want to consider Windsor's interceptors to provide similar behavior.
Related
I process messages from a queue. I use data from the incoming message to determine which class to use to process the message; for example origin and type. I would use the combination of origin and type to look up a FQCN and use reflection to instantiate an object to process the message. At the moment these processing objects are all simple POJOs that implement a common interface. Hence I am using a strategy pattern.
The problem I am having is that all my external resources (mostly databases accessed via JPA) are injected (#Inject) and when I create the processing object as described above all these injected objects are null. The only way I know to populate these injected resources is to make each implementation of the interface a managed bean by adding #stateless. This alone does not solve the problem because the injected members are only populated if the class implementing the interface is itself injected (i.e. container managed) as opposed to being created by me.
Here is a made up example (sensitive details changed)
public interface MessageProcessor
{
public void processMessage(String xml);
}
#Stateless
public VisaCreateClient implements MessageProcessor
{
#Inject private DAL db;
…
}
public MasterCardCreateClient implements MessageProcessor…
In the database there is an entry "visa.createclient" = "fqcn.VisaCreateClient", so if the message origin is "Visa" and the type is "Create Client" I can look up the appropriate processing class. If I use reflection to create VisaCreateClient the db variable is always null. Even if I add the #Stateless and use reflection the db variable remains null. It's only when I inject VisaCreateClient will the db variable get populated. Like so:
#Stateless
public QueueReader
{
#Inject VisaCreateClient visaCreateClient;
#Inject MasterCardCreateClient masterCardCreateClient;
#Inject … many more times
private Map<String, MessageProcessor> processors...
private void init()
{
processors.put("visa.createclient", visaCreateClient);
processors.put("mastercard.createclient", masterCardCreateClient);
… many more times
}
}
Now I have dozens of message processors and if I have to inject each implementation then register it in the map I'll end up with dozens of injections. Also, should I add more processors I have to modify the QueueReader class to add the new injections and restart the server; with my old code I merely had to add an entry into the database and deploy the new processor on the class path - didn't even have to restart the server!
I have thought of two ways to resolve this:
Add an init(DAL db, OtherResource or, ...) method to the interface that gets called right after the message processor is created with reflection and pass the required resource. The resource itself was injected into the QueueReader.
Add an argument to the processMessage(String xml, Context context) where Context is just a map of resources that were injected into the QueueReader.
But does this approach mean that I will be using the same instance of the DAL object for every message processor? I believe it would and as long as there is no state involved I believe it is OK - any and all transactions will be started outside of the DAL class.
So my question is will my approach work? What are the risks of doing it that way? Is there a better way to use a strategy pattern to dynamically select an implementation where the implementation needs access to container managed resources?
Thanks for your time.
In a similar problem statement I used an extension to the processor interface to decide which type of data object it can handle. Then you can inject all variants of the handler via instance and simply use a loop:
public interface MessageProcessor
{
public boolean canHandle(String xml);
public void processMessage(String xml);
}
And in your queueReader:
#Inject
private Instance<MessageProcessor> allProcessors;
public void handleMessage(String xml) {
MessageProcessor processor = StreamSupport.stream(allProcessors.spliterator(), false)
.filter(proc -> proc.canHandle(xml))
.findFirst()
.orElseThrow(...);
processor.processMessage(xml);
}
This does not work on a running server, but to add a new processor simply implement and deploy.
I have automapper setup like this
services.AddAutoMapper(typeof(MappingAssembly).Assembly, typeof(AssemblyWithExtensionMethods).Assembly);
And in one of my profiles
public class UserModuleMapper : Profile {
public UserModuleMapper() {
IncludeSourceExtensionMethods(typeof(UserGroup));
CreateMap<UserGroup, UserGroupDto>(MemberList.Destination);
}
}
And I have defined the extension method as
public static List<string> GetRoleNames(this UserGroup group) {
return group.UserGroupRoles.Select(x => x.Role.Name).ToList();
}
I have a property on DTO defined as
public List<string> RoleNames { get; set; }
As per the automapper documentation, I have made the following assumptions:
IncludeSourceExtensionMethods, which include extension methods while mapping
while mapping it will also look for methods with prefix Get
But when I validate the automapper extension I get error for unmapped property
Unmapped properties: RoleNames
What is missing in my configuration, automapper should detect the extension method.
I have tried (a) remove GET from the method name, but still does not work (b) moving CreateMap before or after the IncludeSourceExtensionMethods to see if sequence matters, but none of it helped.
With in few minutes after posting the question I got the answer by carefully looking at this issue on Github
The issue was with below statement
IncludeSourceExtensionMethods(typeof(UserGroup));
the type mentioned here should be of extension class
IncludeSourceExtensionMethods(typeof(UserGroupExtensions));
Not deleting the question, as it might help someone in future.
We are facing one issue in our Mule Adapter related to JAXB context, needed some opinion on the same
We are using xpath to evaluate some expressions in the choice blocks in our adapter like below for instance,
<choice doc:name="Choice">
<when expression="//env:abc/env:Body/ref:dataelement/ref:/ref:element" evaluator="xpath">
......
</when>
Now, this works perfectly fine in our application but the problem arises when one of other team uses this Adapter as a jar in their application.
When they try to use this adapter, they are getting below error,
Message : More than one object of type class javax.xml.bind.JAXBContext registered but only one expected.
Type : org.mule.api.registry.RegistrationException
Code : MULE_ERROR--2
JavaDoc : http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/registry /RegistrationException.html.
After debugging with the help of loggers etc, we narrowed down to the choice block used above which is causing this particular issue. Also, googled a bit and found one of the posts pointing out the same issue.
Also, to confirm we commented out the choice block having xpath expression and the flow went ahead but broke again where was xpath used in some other way.
https://www.mulesoft.org/jira/browse/MULE-5926
Can anyone please suggest any suitable workaround to resolve this issue?
I agree with you. It is an unresolved issue in Mule.
One solution we have implemented is not define the jaxb context in the config you are providing in the jar file.
Along with the jar file, give instructions to the end application using it, to include the JAXB packages in their JAXB Context object definition.
This way there will be only one JAXB context and it will work smoothly.
Hope this helps.
This is a bit late however the solution that worked was
<mulexml:jaxb-context name=“JAXB_Context“ packageNames=“org.example.test1:org.example.test2“ doc:name=“JAXB Context1“ />
Please note that there must be no space between package names.
Thanks to: http://dominikbial.de/quicktipp-working-with-more-than-one-package-name-in-a-jaxb-context-config-in-mule-esb/
As of now we cannot add more than one JAXBContext in mule. As an alternative you can write your custom transformer.
I implemented something like
public interface MyAppJaxbObj2XmlComponent<I,O> extends
MyAppComponent<I,O>,Callable {
public O marshal(I input) throws Exception;
}
Abstart transformer
public abstract class AbstractMyAppJaxbObj2XmlComponent<I,O> implements
MyAppJaxbObj2XmlComponent<I,O>{
private Class<I> inputType;
public AbstractMyAppJaxbObj2XmlComponent(){
this.inputType = (Class<I>) new TypeToken<I>(getClass())
{}.getRawType();
}
public AbstractMyAppJaxbObj2XmlComponent(Class<I> type){
this.inputType = type;
}
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
I input = eventContext.getMessage().getPayload(inputType);
O output = marshal(input);
return output;
}
}
Your flow transformer this will load your needed jaxb during startup.
#Component
public class MyFlowJaxbObj2XmlComponent extends
AbstractMyAppJaxbObj2XmlComponent<RequestPayloadType,String> {
#PostConstruct
public void init() {
//Load your schema during startup
}
}
You can also implement a fluid interface as an alternative for this.
I finally got my test servlet working from this thread?
Calling HttpServlet class from xpages client side script and regular notes forms?
The issue that remains is I am being asked to login. But my final servlet will need to run without logging in. I have my acl set to Read public document and Write public documents for anonymous.
What I don't know how to do is to make the serlet public access. Other design documents have an "Available to Public Access users" property but I am seeing no such property for java files. Would this be set somewhere else? Maybe in my IServletFactory perhaps?
I don't know why I was required to log in before but it looks like it is now working. The only thing that is requred is that Read Public Public Document be enabled.
This is a bit concerning since it at least appears there is no way to make some servlets non-public. In my case it won't be an issue but it could be an issue for others.
Also what I noticed is that if you change the Public Access acl setting, it looks like you need to rebuild your servlets for some reason or the servlets won't run. When I get a chance I will open a ticket with notes support for both of these issues.
For those wanting to execute a servlet, I suggest this article:
http://8b30b0.wordpress.com/2013/02/04/creating-a-basic-domino-servlet/#comments
But here is a much more simplifed version of IServletFactory that might be easier to understand and get working.
package test;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import com.ibm.designer.runtime.domino.adapter.ComponentModule;
import com.ibm.designer.runtime.domino.adapter.IServletFactory;
import com.ibm.designer.runtime.domino.adapter.ServletMatch;
public class TestFactory implements IServletFactory {
private ComponentModule module;
public ServletMatch getServletMatch(String contextPath, String path)
throws ServletException {
System.out.println("TestFactory:getServletMatch");
String servletPath = "";
String pathInfo = path;
return new ServletMatch(getWidgetServlet(),servletPath,pathInfo);
}
public void init(ComponentModule arg0) {
System.out.println("TestFactory:init");
this.module = arg0;
}
public Servlet getWidgetServlet() throws ServletException {
return module.createServlet("com.pnc.cld.HelloWorld", "testServlet",null);
}
}
I have an asp.net mvc application and I am developing a custom attribute to secure some wcf end points inheriting from a CodeAccessSecurityAttribute.
I'm having difficulty finding out how I would use autofac to inject a service dependancy that I can use within this attribute.
[Serializable]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class SecuredResourceAttribute : CodeAccessSecurityAttribute
{
public ISecurityService SecurityService { get; set; }
public SecuredResourceAttribute(SecurityAction action) : base(action)
{
}
public override IPermission CreatePermission()
{
// I need access to the SecurityService here
// SecurityService == null :(
}
}
I have tried from the application start to register for property auto wiring, but this is not working. What's the best way to inject a dependancy into an attribute?
builder.RegisterType<SecuredResourceAttribute>().PropertiesAutowired();
Thanks
The way you are approaching this is not going to pan out for a couple reasons:
Registering an attribute in autofac will do nothing as you're not using autofac to instantiate the attribute.
Attributes are applied before code execution, and thus rely on constant inputs.
You're going to have to use a service location pattern inside your CreatePermission() method to locate the SecurityService, as I am assuming the CreatePermission() call comes after the container is setup (and the constructor does not!)
Keep in mind ServiceLocation will hinder your class testability, as you will have to configure/set-up the service locator for each test.
Please use with caution
You should start your journey into ServiceLocation here but honestly this should make you question your design. Is an attribute best suited for the role you've tasked it? Perhaps you should look into Aspect-Oriented Programming like PostSharp