How to connect interface<T> and implementation<T> in autofac .config file - dependency-injection

I have following class
namespace MyApplication.Services
{
public class TagEqualityComparer : IEqualityComparer<Tag>{/*code goes here*/}
}
Now what I would like to register it in autofac using .config file based configuration:
<autofac>
<components>
<component type="MyApplication.Services.TagEqualityComparer, MyApplication.Services"
service="System.Collections.Generic.IEqualityComparer, mscorlib" />
</components>
</autofac>
I have already spent whole sunday searching for solution I failed to find any. Other registrations, non templates, works perfectly but this one refuses.
Any idea how to solve it?

You need to define the rest of the generic type to specify the parameter type. Something like this:
<component type="MyApplication.Services.TagEqualityComparer, MyApplication.Services"
service="System.Collections.Generic.IEqualityComparer`1[[MyApplication.Services.Tag, MyApplication.Services]], mscorlib" />

Related

Sitecore: inject dependency into sitecore components

I'm using Sitecore 8.1 MVC with Autofac as the DI. I was wondering what is the recommended way to injecting resolved objects into sitecore created objects i.e. pipelines, commands, computed fields etc... As an example, i am using a membership provider in which i need to invoke my business layer. Is it possible for me to define a constructor on the class and sitecore would injects the objects?
Thanks
With things like pipeline processors, commands etc... Basically anything that Sitecore creates - you are fairly limited. The normal approach is to use the Service Locator pattern to resolve dependencies:
var membershipProvider = DependencyResolver.Current.Resolve<IMembershipProvider>()
There are other ways tho. This post: https://cardinalcore.co.uk/2014/07/02/sitecore-pipelines-commands-using-ioc-containers/ uses a container factory class to resolve the dependencies in the pipeline. This is the class used:
using System;
using System.Diagnostics.CodeAnalysis;
using Sitecore.Reflection;
public class ContainerFactory : IFactory
{
private readonly IContainerManager containerManager;
public ContainerFactory() : this(new LocatorContainerManager()) // service locate an appropriate container
{
}
public ContainerFactory(IContainerManager containerManager)
{
this.containerManager = containerManager;
}
public object GetObject(string identifier)
{
Type type = Type.GetType(identifier);
return this.containerManager.Resolve(type);
}
}
Then this would be setup as the factory for the event or processor using the factory attribute in the config. Example config:
<sitecore>
<events>
<event name="item:saved">
<handler factory="ContainerFactory" ref="MyApp.MyHandler, MyApp" method="MyMethod">
<database>master</database>
</handler>
</event>
</events>
<pipelines>
<MyPipeline>
<processor type="1" factory="ContainerFactory" ref="MyApp.MyProcessor, MyApp" />
</MyPipeline>
</pipelines>
<factories>
<factory id="ContainerFactory" type="MyApp.ContainerFactory"></factory>
</factories>
</sitecore>
With this second method, you can inject your dependencies in your constructor as you normally would.
These are probably the 2 most commonly used options.

Sub Domain implementation In MVC 5 Application

We are developing a MVC 5 application. Suppose the main site is like www.sport.com
Now we want to create 3 sub domain like cricket.sport.com, football.sport.com and hockey.sport.com
Most of the functionality will be same for this 3 sub-sites.
We have implemented 2 approaches :
Approach 1: Create 3 area for each cricket/football/hockey. But this will create code redundancy. So whenever request comes from URL we check and forward request to specific area.
Approach 2 : Create Single Controller - Check URL SubDomain and redirect depending upon each request and display specific view. In this approach, each time we need to check request sub domain and forward to same.
What is best possible way to implement sub domain in MVC application?
We want to deploy this site on Windows Azure.
What you mean by implement sub domain isn't all too clear.
If you are trying to host the same sight at different sub domains and expect them to work differently then you should have something in your web.config or some other setting that then tell each site what it is.
Something like:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="AppType" value="criket" />
</appSettings>
</configuration>
Then inside your application you'll do:
if(ConfigurationSettings.AppSettings["AppType"] == "cricket")
{
//do cricket app specific stuff
} else { /* do something else */ }
If this whole thing doesn't need to be dynamic you could also have a build symbol :
//uncomment or comment accordingly
#define CRIKET
//#define FOOTBALL
public class HomeController
{
public ActionResult Index()
{
#if CRICKET
return View("Cricket");
#elif FOOTBALL
return View("Football");
#endif
}
}
A config setting is slower than a build symbol but it gives you a dynamic approach. Choose according to your need.

Can I pass other components into Castle Windsor config?

Lets say I have a main component that I want to initialize in a specific way and I have it's constructor take an Interface for this purpose. Is there a way to define the implementation I want for this interface in my xml and in turn inject that into the main component as a parameter? Like this:
public interface IComponent2 {
void DoStuff();
}
public class ConcreteCompImpl2 : IComponent2 {
IComponent1 _comp;
public ConcreteCompImpl2(IComponent1 comp) {
_comp = comp;
}
public void DoStuff(){
//do stuff
}
}
<component id="component1" service="ABC.IComponent1, ABC" type="ABC.ConcreteCompImpl1, ABC" />
<component id="component2" service="ABC.IComponent2, ABC" type="ABC.ConcreteCompImpl2, ABC" >
<parameters>
<component1>???</component1>
</parameters>
</component>
Or am I thinking about this all wrong and there is a much simpler way to accomplish this? The main thing I want to be able to do is configure what 'kind' of IComponent1 will get injected whenever an IComponent2 is created. Thanks
If you have only one concrete class implementing IComponent1, then it will automatically be injected when you resolve IComponent2.
If you have several classes implementing IComponent1 and want a specific one every time IComponent2 is resolved, you need to specific an inline dependency:
container.Register(
Component.For<IComponent2>()
.ImplementedBy<Component2>()
.DependsOn(Dependency.OnComponent<IComponent1, YourSpecialComponent1>())
);
I'm not completely sure you can specify this in the XML configuration, but honestly you should use the Fluent API instead of the XML configuration unless you have a really compelling reason to use it. As mentioned in the above link:
Ability to register components in XML is mostly a leftover from early days of Windsor before Fluent Registration API was created. It is much less powerful than registration in code and many tasks can be only accomplished from code.

Date conversion exception inside JSF composite component

When I access a JPA managed date value from JSF, it comes back with an javax.faces.component.UdateModelException saying
'Cannot convert 01.01.10 00:00 of type class java.util.Date to class org.apache.openjpa.util.java$util$Date$proxy
Using a JPA-managed date value (which means it is proxied) works fine when it is used directly from the EL likes this:
'<h:outputLabel value="MyDateValue" for="input"/>
'<h:inputText id="inputDate" value="#{bean.myDate}"/>
However, it causes trouble when trying to use it with composite components
and gives back the following converter exception and thus can't update the model...
The (simplified) JSF composite component inputDate.xhtml
<head>
<title>A date input field</title>
</head>
<composite:interface>
<composite:attribute name="dateValue"/>
</composite:interface>
<composite:implementation>
<h:outputLabel value="MyDateValue" for="input"/>
<h:inputText id="input" value="#{cc.attrs.dateValue}"/>
</composite:implementation>
Assumption:
It seems the proxy replacement in OpenJPA is handled differently when the value is being accessed from inside a composite. My guess is the EL-resolver handles calls to object values differently when it is passed to composites. Passing it to composites means it is first accessed within the composite, which is too late and the required replacement of the proxy is not accomplished (thus the converter exception)
So I tried to change the Expression Language for MyFaces, but it didn't work in Websphere, even though I changed the class loading to parent last and provided el-impl and el-api from glassfish in the lib folder and inserted the necessary context-param for MyFaces
How do you guys use JPA-managed dates (or other proxied entities) in composite components???
If you are using the sun EL implementation you might use the following ELResolver which works around this issue:
public class BugfixELResolver extends ELResolver {
//...
#Override
public Class<?> getType(ELContext anElContext, Object aBase, Object aProperty) {
if (aBase.getClass().getCanonicalName().equals("com.sun.faces.el.CompositeComponentAttributesELResolver.ExpressionEvalMap")){
Object tempProperty=((Map)aBase).get(aProperty);
if (tempProperty!=null&&tempProperty.getClass().getCanonicalName().equals("org.apache.openjpa.util.java.util.Date.proxy")) {
anElContext.setPropertyResolved(true);
return java.util.Date.class;
}
}
return null;
}
}
Add it to the faces-config this way:
<el-resolver>
xxx.BugfixELResolver
</el-resolver>
This workaround can also be used in environments where you can not change the EL implementation (like websphere etc.).
Here is the workaround. The problem seems to be WebSpheres' ExpressionLanguage Implementation or rather the order resolvers are executed. Registering the JBoss EL implementation works and resolves the date proxies before calling the composite component. I also tried the Glassfish EL, but it didn't work either...
Registering a alternative EL is quite strange: The setting in web.xml for MyFaces is
<context-param>
<param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
<param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>
Additionally under WebContent/META-INF/services/ a file named javax.el.expressionFactory is needed with this single line org.jboss.el.ExpressionFactoryImpl. The class comes from jboss-el-2.0.2.CR1.jar
(sorry, couldn't find the link to a maven repo)
I will keep you updated once I find a better solution...

Struts2 - How to use the Struts2 Annotations?

I'm trying to implement the Struts 2 Annotations in my project, but I don't know how.
I added the convention-plugin v 2.1.8.1 to my pom
I modified the web.xml
...
<init-param>
<param-name>actionPackages</param-name>
<param-value>org.apache.struts.helloworld.action</param-value>
</init-param>
...
My Action
package org.apache.struts.helloworld.action;
import org.apache.struts.helloworld.model.MessageStore;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
#Results({
#Result(name="success", location="HelloWorld.jsp")
})
public class HelloWorld extends ActionSupport {
public String execute() throws Exception {
messageStore = new MessageStore() ; return SUCCESS;
}
The jsp page from where I'm trying to use my action.
<body>
<h1>Welcome To Struts 2!</h1>
<p>Hello World</p>
</body>
When I press the link associated to the action helloWorld, but it's sends me to the exactly the same page. So, from index.jsp, it's sends to index.jsp.
The way it should behave: it should send me to HelloWorld.jsp.
I uploaded the project (a very simple HelloWorld app) to FileFront, maybe someone sees where is the problem. http://www.filefront.com/16364385/Hello_World.zip
Convention uses a different convention to convert CamelCaseAction names to url's and jsp's names. If you are using Convention's defaults, I believe you should have used the following names:
ActionClass: HelloWorldAction.java
JSP: hello-world.jsp
Action: hello-world
Also, notice that by default convention will look for your JSPs on WEB-INF/content . The documentation is a bit shallow, you have to understand by the examples, but you can consult all default values there: http://struts.apache.org/2.x/docs/convention-plugin.html
I havent used Struts2 with annotations (which Struts2 version? are you following some tutorial or doc?) . But should not that location attribute (in the Result annotation) be instead value ?
What do the logs say? Have you tried using /HelloWorld.jsp for "success". I think that struts framework does not find the resource and is loading the same page.
When you use /HelloWorld.jsp, hopefully you will see the result page.

Resources