Blueprint dependency injection within a bundle - dependency-injection

I've come across a case where I want to use Blueprint (Aries) to resolve a dependency at run-time and the implementation is defined in the same bundle which requires it and will not be used in any other bundles. I am abstracting the implementation within this bundle to make it easier to mock the dependency when unit testing. If I put this service in its own bundle, it would lead to poor cohesion.
At run-time, the Blueprint says it is waiting for dependencies. How can I use Blueprint to realize dependency injection within a bundle?
<!-- Interface -->
<reference id="modelEntityMapper" interface="org.example.blog.rest.cxf.server.model.ModelEntityMapper" />
<!-- Implementation defined within same bundle -->
<bean id="modelEntityMapperImpl" class="org.example.blog.rest.cxf.server.model.impl.ModelEntityMapperImpl" />
<service ref="modelEntityMapperImpl" interface="org.example.blog.rest.cxf.server.model.ModelEntityMapper" />
<!-- Object which has dependency -->
<bean id="posts" class="org.example.blog.rest.cxf.server.BlogResourceImpl">
<property name="modelEntityMapper" ref="modelEntityMapper" />
</bean>
Edit
I just tried the suggestion from #christian-scheider and Blueprint is still waiting for some service to satisfy ModelEntityMapper
The XML
<!-- Interface -->
<reference id="modelEntityMapper" interface="org.example.blog.rest.cxf.server.model.ModelEntityMapper" />
<!-- Implementation defined within same bundle -->
<bean id="modelEntityMapperImpl" class="org.example.blog.rest.cxf.server.model.impl.ModelEntityMapperImpl" />
<!-- Object which has dependency -->
<bean id="posts" class="org.example.blog.rest.cxf.server.BlogResourceImpl">
<property name="modelEntityMapper" ref="modelEntityMapperImpl" />
</bean>
The Log
Bundle rest-cxf-server is waiting for dependencies [(objectClass=org.example.blog.rest.cxf.server.model.ModelEntityMapper)]

Can you just refer to the bean of the service directly? If you define the service and the service reference in the same blueprint file then using an OSGi service does not make that much sense.

I was unable to find detailed documentation on the Aries site related to referencing in bundles, so I'm going to reference the Eclipse Gemini Blueprint implementation documentation (formerly Spring Dynamic Modules). See the warning in section 9.2.1.1 of their documentation. Yes, technically this is related to their implementation, but I believe it's likely a similar story in Aries.
It is an error to declare a mandatory reference to a service that is also exported by the same bundle, this behaviour can cause application context creation to fail through either deadlock or timeout.
In a nutshell you typically either import (reference) an OSGi service or you export an OSGi service in the same bundle, usually you don't try to do both in a single bundle.
If you want this bundle to export a service of type ModelEntityMapper, then you'll need to export it with the service element. When other beans need a reference within the same bundle, you would use the ref attribute like you're using it. In this case, you would not need the reference element at all, but instead use the service element.
If you're not going to use the ModelEntityMapper bean outside of this bundle, you don't need to use a reference or service element in the configuration at all. You should be able to use it in the ref attribute without exporting it as an OSGi service - it's basically a bean internal to that bundle. In this case, you should be able to remove the reference element altogether: the <bean id="modelEntityMapperImpl" ... will create a bean internal to the bundle, and the <property name="modelEntityMapper" ref="modelEntityMapperImpl" /> element should be able to use that bean internally to the bundle.
If you want to import a reference of type ModelEntityMapper from OSGi if available, else use an internally defined fallback, that gets more complicated. You'd have to declare a non-mandatory reference and inject that reference into your class along with the internally defined bean and then have defaulting logic that checks the availability of them. Alternatively you could just define the implementation in a separate bundle from the interface.

Related

Parameter substitution in log4j2

I need to allow deployers to specify the path for our Tomcat webapp log4j2 RollingFileLogger. I'd like to use JNDI but can use a plain -D param if I had to. This apache page seems to explain things pretty well.
Only problem is it doesn't work. I will admit to not being particularly experienced in JNDI, but I can't even get a simple JVM param to work. Reading about Property Substitution I got the impression I cannot just put the $${jndi:xxxx} in the filename attribute and that I should use a ${xxx} Property substitution instead. Unfortunately while that property substituion works fine no lookup jndi or env ever resolves.
log4j2.xml:
<Properties>
<Property name="filename">$${jndi:logPath/directory}/ief.log</Property>
</Properties>
....
<RollingFile name="RollingFileLogger" fileName="${filename}" immediateFlush="false" append="true"
Result:
2014-09-16 14:44:46,284 ERROR Unable to create file ${jndi:logPath/directory}/ief.log java.io.IOException: The filename, directory name, or volume label syntax is incorrect
As you can see the property is substituted but the lookup is not done. I am unsure what the context.xml entry should look like. But my best guess is:
<Resource name="logPath"
auth="Container"
directory="/tmp" />
I am using log4j version 2.0 but am fairly certain this is my misunderstanding not a bug. Any help clearing up what I'm doing wrong would be greatly appreciated.
I never found a JNDI browser that would work in Tomcat 7. But it did turn out to be a stupid problem. I defined this as a RESOURCE instead of an ENVIRONMENT. Just for the record the context.xml should look like:
<Environment name="logPath"
auth="Container"
type="java.lang.String"
value="/tmp" />
And log4j2 lookup is then:
<Property name="logName">$${jndi:logPath}/iefrest.log</Property>
<Property name="patternName">$${jndi:logPath}/iefrest</Property>
...
<RollingFile name="RollingFileLogger" fileName="${logName}" immediateFlush="false" append="true"
filePattern="${patternName}-%d{yyyyMMdd-HH}.log.gz">
It is worth noting that the "java:comp/env" (which is clearly documented but misleading to people that don't have a deep knowledge of JNDI - like me) actually maps to the Environment XML element and does not imply a prefix to the name attribute.
From a Log4J2 prespective it is also interesting that the filename attribute is taken EXACTLY as provided. Specifically you cannot say filename="${logName}.log". This will not parse into the desired results. However expected concatenation DOES take place on the filepattern attribute. Inconsistent but not unmanageable.
If you specify $${jndi:logPath/directory}, the lookup will add the prefix java:comp/env/, so the full value that it will look up is java:comp/env/logPath/directory. (This prefix is not added if your jndi lookup key already contains a ':' character.) Perhaps you can use a JNDI browser to see if this gives you the expected value.
Any errors that occur during this lookup will be logged to the status logger at WARN level. Status logs appear in the console. You can enable status logs by specifying <Configuration status="trace" ... in your log4j2.xml configuration file.

Is There A Way to have Struts 2 Resource Bundle Point to a File Location?

I currently have a package on my class path called MyResources with multiple property files that struts uses. Works great:
<constant name="struts.custom.i18n.resources" value="com.company.MyResources"/>
I am trying to move the properties files to a file location, so they can be updated without having to rebuild the package. Is it possible in Struts 2 to refer to this file location?
For example, my new file location with the properties files is:
/g01/properties/
And I would like Struts to use that location for the resource.
Yes, by providing an implementation of ResourceBundleTextProvider and initializing it in your struts.xml configuration file.
The default implementation, com.opensymphony.xwork2.TextProviderSupport defers the text lookup to com.opensymphony.xwork2.util.LocalizedTextUtil.
There are a number of ways to go about this, but if you don't need any of the default S2 behavior, here's the place to start:
<bean type="com.opensymphony.xwork2.TextProvider" name="struts"
class="com.opensymphony.xwork2.TextProviderSupport" scope="default" />
Provide your own ResourceBundleTextProvider implementation that uses whatever configuration management you want, for example, we implemented a DB-backed version (with caching, of course) that allowed translations to live in, and be managed by, a normal DB and I18N front end.
I'll see if I can dig up my original work this weekend and provide a link to a stripped-down solution.
The location of the file cannot be off the class path when you run your app. You should determine which classloader is used to load the resource. Then you should find a way to configure this classloader to be able to use the location as resource. So, it's possible. A short answer.

Configure spring security ldap-server attribute to use different url based on deployed environment

We are using spring security and have it working well. I am trying to figure out one thing that has not being obvious - how do I configure ldap-server attribute to use different url based on deployed environment?
This is what I have that is working:
<ldap-server url="ldap://testserver:port/o=blah" manager-dn="cn=bind,ou=Users,o=blah" manager-password="password"/>
<authentication-manager id="authenticationManager" alias="authenticationManager">
<ldap-authentication-provider
user-search-filter="(cn={0})"
user-search-base="ou=Users"
group-search-filter="(uniqueMember={0})"
group-search-base="ou=groups"
group-role-attribute="cn"
role-prefix="none">
</ldap-authentication-provider>
Now, how do I configure it to use a different url based on deployed environment?
thanks in advance,
Sharath
I've done that with Spring profiles:
In your spring.*.xml config file use this at the end of your file:
<beans profile="production">
...
</beans>
<beans profile="local">
...
</beans>
As VM Arguments the used profile must be provided:
-Dspring.profiles.active=production
Regards
You can use the url as variables and set them in a properties file.
To change the properties file should be easier. I know you can do that with Maven - with jar or war plugin depending on packaging, including generating two (or more) packages with one execution - but I suppose you can with Ant or other managers too.
Of course, you could use that solution to change the whole xml, but it's easier to do that with a properties file because that way, when changing the configuration, the markup will not be in the way, only variables and values.

Does anyone have documentation on CustomActivitiesAndExtensions.xml?

I found this mentioned in a few books I have on TFS2010, but the documentation is pretty sparse, and searching on Google and Bing returns nothing I don't already know.
Does anyone have and detailed information on the using CustomActivitiesAndExtensions.xml and how it works?
The CustomActivitiesAndExtensions.xml file is primarily used to specify additional activities and/or workflow extensions to be loaded by the Build Service to support your build process.
Here's an example:
<?xml version="1.0" encoding="utf-8"?>
<Assemblies DownloadListedItemsOnly="true">
<Assembly LoadListedItemsOnly="true" FileName="CustomAssembly.dll" HostEnvironmentOption="All">
<Activities>
<Activity FullName="CustomAssembly.OnAgentActivity" HostEnvironmentOption="Agent"/>
<Activity FullName="CustomAssembly.OnControllerActivity" HostEnvironmentOption="Controller"/>
<Activity FullName="CustomAssembly.OnBothActivity" HostEnvironmentOption="All"/>
</Activities>
<Extensions>
<Extension FullName="CustomAssembly.OnAgentExtension" HostEnvironmentOption="Agent"/>
<Extension FullName="CustomAssembly.OnControllerExtension" HostEnvironmentOption="Controller"/>
<Extension FullName="CustomAssembly.OnBothExtension" HostEnvironmentOption="All"/>
</Extensions>
</Assembly>
</Assemblies>
The DownloadListedItemsOnly attribute is an optimization you can use to only download the assemblies specified in this file and ignore any others.
Lastly, it's important to note that if you specify an assembly beneath the Activities or Extensions element that doesn't actually have an Activity or Extension (as appropriate) that's discoverable via reflection, then that assembly won't be loaded. The most likely case where this would be a problem would be if you implemented the design-time experience for your activity in a separate assembly.
As you you know TFS based on WF so you just need the documentation of how to create WF custom activity, To create a basic custom activity, you inherit from the Activity class or a derived type. To create a custom composite activity, you inherit from the CompositeActivity class or a derived type.
See this link:
Creating Custom Activities

spring.net used in a class library

I am attempting to use spring.net 's IoC conatiner in a class library which in and of itself is not an executable. A web project simply calls this library , this library contains the references to the spring binaries and to spring's config files.
Essentially the question is:
Does spring.net need to reside in an executable to start, or canit reside in a classs library that will be referenced by an executable?
Any help will be appreciated.
You can include part of your configuration in the class library project as an embedded resource file. Let's say you called it LibraryConfig.xml. Then in your executable's application config file, you include the embedded resource using the assembly: prefix. Here's an example:
<spring>
<context type="Spring.Context.Support.XmlApplicationContext, Spring.Core">
<resource uri="assembly://FooLibrary/FooLibrary/LibraryConfig.xml"/>
<resource uri="config://spring/objects" />
</context>
<objects xmlns="http://www.springframework.net">
<object id="mainForm" type="FooApp.MainForm, FooApp">
<!-- mainController is some object defined in LibraryConfig.xml -->
<property name="Controller" ref="mainController"/>
</object>
</objects>
</spring>
If your main application doesn't need to use Spring itself, I think you can set up the whole application context in the library. Embed the config file as described above, then define a singleton object to hold the application context and load it from the embedded config file. Finally, you need to define some kind of factory methods for the client code to create your classes with. The factory methods can either go on the singleton itself (probably using generics), or have a separate factory method on each class that needs to be instantiated. Those factory methods make the actual requests from the application context and the client code never sees it.
it can reside in a dll which is referenced by an executable, but make sure that the configuration is included in (or referenced by) the executable's config file.

Resources