How to suppress azure cache client warnings from the WAD logs - caching

We have 2 roles which use a cache role to share data. When we deploy we get many many of the following entries in the logs:
INFORMATION: <CASClient> Updated partition table to (1-901) generation: 635036190744461419:0 with transfer (1-901) generation: 635036190744461419:0; TraceSource 'w3wp.exe' event
INFORMATION: <Complaint> Add hard complaint :0 ; TraceSource 'w3wp.exe' event
Changing the values of the setting:
<Setting name="Microsoft.WindowsAzure.Plugins.Caching.ClientDiagnosticLevel" value="0" />
seems to have no effect.
Any ideas how we can remove this noise from the WADLogs table?

It seems there is a bug in Caching (see this post). I tried to get rid of these log entries with no luck running SDK1.8. Recently I switched to SDK2.0 but unfortunately the problem is still not fixed.
Bug report on GitHub

I'm going to be adding a filter for this.
Sample for web.config:
<system.diagnostics>
<trace>
<listeners>
<add name="console" type="System.Diagnostics.ConsoleTraceListener">
<filter type="Namespace.TraceFilter, Assembly" initializeData="Information"/>
</add>
</listeners>
</trace>
</system.diagnostics>
Note: The attribute initializeData is set to the text from System.Diagnostics.SourceLevels enum. See here.
TraceFilter.cs
public class TraceFilter : EventTypeFilter
{
public TraceFilter(SourceLevels level)
: base(level) {}
public override bool ShouldTrace(TraceEventCache cache, string source, TraceEventType eventType, int id, string formatOrMessage, object[] args, object data1, object[] data)
{
return !Regex.IsMatch(formatOrMessage, "INFORMATION: <[^>*]*>");
}
}
You could extend this to a more generic filter which could run off a configuration accepting different patterns to include/ignore.

After reading a suggestion at the end of this thread on GitHub we managed to disable this by running the following code in the application:
DataCacheClientLogManager.ChangeLogLevel(TraceLevel.Off);
DataCacheClientLogManager.SetSink(DataCacheTraceSink.DiagnosticSink, TraceLevel.Off);
This stops all logging from the Azure Cache Client without you having to turn off your own Warning or Information level logs.
We ended up adding this in the constructor of our Cache Provider wrapper around the DataCacheClient:
public class AzureCacheProvider : ICacheProvider
{
public AzureCacheProvider()
{
DataCacheClientLogManager.ChangeLogLevel(TraceLevel.Off);
DataCacheClientLogManager.SetSink(
DataCacheTraceSink.DiagnosticSink,
TraceLevel.Off);
InitializeCache();
}

Here is a complete solution
Just make sure to use your namespace and corresponding assembly name.
using Microsoft.WindowsAzure.Diagnostics;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace MyNamespace
{
/*
Solves the Azure In-Role Cache client warnings bug which is too verbose in the WAD logs
Also Solves Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener not using Filter
For roles which uses in-role caching, configure your Web.config or app.config with the following system.diagnostics listner and filter:
<system.diagnostics>
<trace>
<listeners>
<add name="AzureDiagnostics" type="MyNamespace.FilteringDiagnosticMonitorTraceListener, MyAssemblyName">
<!-- WARNING: does not work with type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=2.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
because the DiagnosticMonitorTraceListener does not call the filter's ShouldTrace method as is was supposed to... -->
<!-- Note: working with type="System.Diagnostics.ConsoleTraceListener" -->
<filter type="MyNamespace.SuppressCacheClientWarningsTraceFilter, MyAssemblyName" initializeData="Information"/>
<!-- Note: The attribute initializeData is set to the text from System.Diagnostics.SourceLevels enum. -->
</add>
</listeners>
</trace>
</system.diagnostics>
*/
/// <summary>EventTypeFilter which suppress the 'noise' messages from the In-Role Azure Cache client
/// </summary>
/// <remarks>It's a workaround for the following problem http://social.msdn.microsoft.com/Forums/windowsazure/en-US/7ebbc44e-7b61-4bbe-aa54-a85a7788079f/complaint-add-hard-complaint?forum=windowsazuredata.
/// The solution is based on http://stackoverflow.com/questions/16443856/how-to-suppress-azure-cache-client-warnings-from-the-wad-logs and http://pastebin.com/qKc1aTTW
/// </remarks>
public class SuppressCacheClientWarningsTraceFilter : EventTypeFilter
{
public SuppressCacheClientWarningsTraceFilter(SourceLevels level)
: base(level) { }
public override bool ShouldTrace(TraceEventCache cache, string source, TraceEventType eventType, int id, string formatOrMessage, object[] args, object data1, object[] data)
{
return !(
(eventType == TraceEventType.Information && Regex.IsMatch(formatOrMessage, #"^INFORMATION:\ <(CASClient|Complaint)>"))
|| (eventType == TraceEventType.Warning && Regex.IsMatch(formatOrMessage, #"^WARNING:\ <SimpleSendReceiveModule>\ DeadServerCallback"))
);
//return !Regex.IsMatch(formatOrMessage, #"^INFORMATION: <[^>*]*>");
}
}
/// <summary>Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener which uses the configured Trace Filter
/// </summary>
/// <remarks>It's a workaround for the following problem http://social.msdn.microsoft.com/Forums/en-US/92ed1175-d6b7-4173-a224-0f7eb3e99481/diagnosticmonitortracelistener-ignors-filter?forum=windowsazuretroubleshooting
/// The solution is based on the thread comment from "Qin Dian Tang - MSFT": "If you need to use trace filter, then it is needed to use a custom trace listener which derives from DiagnosticMonitorTraceListener, override TraceData, and either manually check filters or call the root class's (TraceListener) TraceData."
/// </remarks>
public class FilteringDiagnosticMonitorTraceListener : DiagnosticMonitorTraceListener
{
public FilteringDiagnosticMonitorTraceListener() : base() { }
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
{
if (this.Filter == null || this.Filter.ShouldTrace(eventCache, source, eventType, id, format, args, null, null))
base.TraceEvent(eventCache, source, eventType, id, format, args);
}
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
{
if (this.Filter == null || this.Filter.ShouldTrace(eventCache, source, eventType, id, message, null, null, null))
base.TraceEvent(eventCache, source, eventType, id, message);
}
}
}
Hope it helps.

Related

Struts2 validating 3 times on single textfield

I am having really upsetting issue with Struts(2.2.3). Here is my field validations on ActionName-validation.xml
<field name="txtRequestDateFrom">
<field-validator type="conversion">
<param name="repopulateField">false</param>
<message>${getText("E011", {"Date from"})}</message>
</field-validator>
</field>
I don't have validate() method in my action class. And I have this in my action class:
private Date txtRequestDateFrom;
{getter, setters}
When I enter letters on my txtRequestDateFrom field I get 3 validation messages on
<s:fielderror fieldName="txtRequestDateFrom"/>
It look like this
Invalid field value for field "txtRequestDateFrom".
Invalid field value for field "txtRequestDateFrom".
Date from has an invalid value
I have my custom theme, and I am sure there is not any much modification from SIMPLE theme. My interceptor stack is pretty much as same default value stack.
<interceptor-stack name="defaultStack">
<interceptor-ref name="security"/>
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUploadStack" />
<interceptor-ref name="fileUpload" >
<param name="maximumSize">4000000</param>
</interceptor-ref>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError" />
<interceptor-ref name="validation">
<param name="excludeMethods">execute, complete ...</param>
</interceptor-ref>
<interceptor-ref name="workflow"/>
</interceptor-stack>
I found out that one field error can be removed by removing conversionError interceptor from the stack. But I don't think that would cause this problem. Struts should be able to show errors only defined by developer, right?
Please help me on this
You need to understand how Struts2 handles conversion errors.
Any error that occurs during type conversion may or may not wish to be reported. For example, reporting that the input "abc" could not be converted to a number might be important. On the other hand, reporting that an empty string, "", cannot be converted to a number might not be important - especially in a web environment where it is hard to distinguish between a user not entering a value vs. entering a blank value.
...
It is important to know that none of these errors are actually reported directly. Rather, they are added to a map called conversionErrors in the ActionContext. There are several ways this map can then be accessed and the errors can be reported accordingly.
There are two ways the error reporting can occur:
Globally, using the Conversion Error Interceptor
On a per-field basis, using the conversion validator
You are using both mechanisms, thus duplicating the errors found. As the documentation states, usually you don't want to report all conversion errors, and thus should remove the ConversionErrorInterceptor from the stack. Now you can selectively raise conversion errors as field errors using the conversion validator.
I found that my custom DateTimeConverter was causing the exceptions and the extra error message. Because I found the code below from Struts2 book in order to change my Date's normal format. When it throws an exception, it shows the exception on console and error message on field error rather than passing the exception to the validator. I think it is sort of bug because this class extends StrutsTypeConverter and it should work as normal converters.
public class StringToDateTimeConverter extends StrutsTypeConverter {
private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd");
public Object convertFromString(Map context, String[] strings, Class toClass) {
if (strings == null || strings.length == 0 || strings[0].trim().length() == 0) {
return null;
}
try {
Calendar calendar = Calendar.getInstance();
calendar.setTime(DATETIME_FORMAT.parse(strings[0]));
calendar.set(Calendar.HOUR, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
return calendar.getTime();
} catch (ParseException e) {
throw new TypeConversionException(e);
}
}
public String convertToString(Map context, Object date) {
if (date != null && date instanceof Date) {
return DATETIME_FORMAT.format(date);
} else {
return null;
}
}
}
Anyway I changed throw new TypeConversionException(e); to return null; and added REQUIRED validator on validation XML. Now it shows me error when I put invalid date on my date fields.
PS: Is there any other way to change Struts global date format? Thanks
I faced a similar problem yesterday and finally found a solution which I like to share. I'm using annotations in my actions for validation, so I changed default struts interceptor stack and put my SensibleConversionErrorInterceptor instead of StrutsConversionErrorInterceptor in. This one is total identically but doesn't create any validation errors. Instead they are generated by validation configured in annotations in my actions.
Here is my converter:
public class SensibleConversionErrorInterceptor extends StrutsConversionErrorInterceptor {
private static final long serialVersionUID = 8186282792289268544L;
#Override
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext invocationContext = invocation.getInvocationContext();
Map<String, Object> conversionErrors = invocationContext.getConversionErrors();
ValueStack stack = invocationContext.getValueStack();
HashMap<Object, Object> fakie = null;
for (Map.Entry<String, Object> entry : conversionErrors.entrySet()) {
String propertyName = entry.getKey();
Object value = entry.getValue();
if (shouldAddError(propertyName, value)) {
// removed cause error messages are generated from annotations in actions
// String message = XWorkConverter.getConversionErrorMessage(propertyName, stack);
// Object action = invocation.getAction();
// if (action instanceof ValidationAware) {
// ValidationAware va = (ValidationAware) action;
// va.addFieldError(propertyName, message);
// }
if (fakie == null) {
fakie = new HashMap<Object, Object>();
}
fakie.put(propertyName, getOverrideExpr(invocation, value));
}
}
if (fakie != null) {
// if there were some errors, put the original (fake) values in place right before the result
stack.getContext().put(ORIGINAL_PROPERTY_OVERRIDE, fakie);
invocation.addPreResultListener(new PreResultListener() {
public void beforeResult(ActionInvocation invocation, String resultCode) {
Map<Object, Object> fakie = (Map<Object, Object>) invocation.getInvocationContext().get(ORIGINAL_PROPERTY_OVERRIDE);
if (fakie != null) {
invocation.getStack().setExprOverrides(fakie);
}
}
});
}
return invocation.invoke();
}
}
And an example action:
#Conversion
public class ProductAction extends ActionSupport {
private Product product;
// getter, setter and so on...
#Action(...)
#Validations(
requiredFields = {
#RequiredFieldValidator(
type = ValidatorType.FIELD,
fieldName = "product.validFrom",
message = "required.product.validFrom",
shortCircuit = true
)
},
conversionErrorFields = {
#ConversionErrorFieldValidator(
fieldName = "product.validFrom",
key = "invalid.fieldvalue.product.validFrom'",
shortCircuit = true
)
}
)
public String saveOrUpdate() {
// do something here...
}
}

ASP.NET Membership for one website but multiple and potentially unknown sql server instance

This my problem. I have 1 and only 1 website for multiple customer. To access to their data, customers use urls like this :
http://customer1.mysite.com
http://customer2.mysite.com
etc
Each customer have a SqlServer instance with their data.
Depends to the URL the website connect to the right sql server instance. This is good.
My issue is about Membership, each instance have is own "membership database". In my webconfig I configure a dummy section like this :
<membership defaultProvider="MyMembershipProvider">
<providers>
<clear />
<add name="MyMembershipProvider"
type="MapApp.MyMembershipProvider, MyApp"
enablePasswordRetrieval="true"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Encrypted"
minRequiredPasswordLength="5"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""
connectionStringName="A_DATABASE" />
</providers>
</membership>
Also I have a custom Membershipprovider with code like this :
public class MyMembershipProvider : SqlMembershipProvider
{
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
base.Initialize(name, config);
// Update the private connection string field in the base class.
string connectionString = "my new connection string depdend of the customer"
// Set private property of Membership provider.
FieldInfo connectionStringField = GetType().BaseType.GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic);
connectionStringField.SetValue(this, connectionString);
}
}
but is not enough a have some issues like "already instanciate" when I call my custom membership provider.
Someone can help me ? Please...
Sorry for my bad english in this long post
This is an interesting problem. Seems like you are attempting to use a different connection string for the database, based on the URL. This might be a bit less elegant, but how about getting the code for the sql membership provider and modifying it so that the connection string which it uses is based on the users URL. I think this could be a good work around if you are truly only using one asp.net application.
I think I have the solution but it's a bit strange.
In my customMemberShipProvider class I must have an empty constructor even if I never call it. And I need another constructor (with args even if I never use it).
So this is my code :
public class myMembershipProvider : SqlMembershipProvider
{
public myMembershipProvider()
{
//never use
}
public myMembershipProvider(string dummyArg)
{
string configPath = "~/web.config";
Configuration config = WebConfigurationManager.OpenWebConfiguration(configPath);
MembershipSection section = (MembershipSection)config.GetSection("system.web/membership");
ProviderSettingsCollection settings = section.Providers;
NameValueCollection membershipParams = settings[section.DefaultProvider].Parameters;
if ((HttpContext.Current.Session != null) && (HttpContext.Current.Session["SubDomainInstanceName"] != null) && (!string.IsNullOrEmpty(HttpContext.Current.Session["SubDomainInstanceName"].ToString())))
{
membershipParams.Add("Instance", HttpContext.Current.Session["SubDomainInstanceName"].ToString());
}
else
{
membershipParams.Add("Instance", "default");
}
Initialize(section.DefaultProvider, membershipParams);
}
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
//need to remove the key before call Initialize method
string instance = config["Instance"];
config.Remove("Instance");
base.Initialize(name, config);
// Update the private connection string field in the base class.
string connectionString = //my specific connectionstring;
// Set private property of Membership provider.
FieldInfo connectionStringField = GetType().BaseType.GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic);
connectionStringField.SetValue(this, connectionString);
}
Regards

dotlesscss does not show errors

There's something wrong with my css because no styles are being added to my website after compilation.
How do I get dotlesscss to show errors? Regular .less shows you a nice message that's very handy.
You can do this very easily with web.config. In your dotless configuration section, add the following: logger="dotless.Core.Loggers.AspResponseLogger". This will make dotless output the errors instead of blank css.
I've included the following as an example. ("..." represents existing stuff in your web.config). In my example below cache is set to false. This is useful for debugging purposes. It should probably be set to true under normal circumstances.
<configuration>
<configSections>
...
<section name="dotless" type="dotless.Core.configuration.DotlessConfigurationSectionHandler,dotless.Core" />
</configSections>
<dotless minifyCss="false" cache="false"
logger="dotless.Core.Loggers.AspResponseLogger" />
...
</configuration>
I just faced this today in my RequestReduce project. I was getting blank less -> css transforms because there were parse errors that appeared to be going into the ether. Thanks to
this related answer How can I output errors when using .less programmatically? I was able to work out a solution where I could write the errors to the response stream. You have to create a Logger derriving from dotless.Core.Loggers.ILogger:
public class LessLogger : ILogger
{
public void Log(LogLevel level, string message)
{
}
public void Info(string message)
{
}
public void Debug(string message)
{
}
public void Warn(string message)
{
}
public void Error(string message)
{
Response.Write(message);
}
public HttpResponseBase Response { get; set; }
}
You pass this into the Configuration sent to the EngineFactory:
var engine = new EngineFactory(new DotlessConfiguration
{
CacheEnabled = false,
Logger = typeof (LessLogger)
}
).GetEngine();
For unit testing purposes I wanted to pass in my HttpResponseBase that would write the error. This is where I felt things getting ugly with some nasty casting to get a reference to my logger:
((LessLogger)((LessEngine)((ParameterDecorator)engine).Underlying).Logger).Response = response;
I hope this helps you out.

Sterling serialization problem on Windows Phone 7

I have a problem with Sterling Database for Windows Phone. I implemented the database step by step in my wp7app, but it doesn't serialize my data when new entities are saved. For example: I serialize credentials using sterling database:
var userCredentials = new UserCredentials(userName, password);
App.Database.Save(userCredentials);
App.Database.Flush();
But when the application is reactivated (or re-launched) Sterling doesn't return any values from isolated storage:
var firstOrDefault = App.Database.Query<UserCredentials, string>()
.ToList()
.FirstOrDefault();
My ActivateEngine method looks are standard and TableDefinition is:
CreateTableDefinition< UserCredentials, string >(t => t.UserName),
Why is sterling database doesn't serialize my data? Everything seems to be implemented fine. Please help.
Are you activating and registering the database on startup and diposing on completion as described in the Quickstart?
My personal preference is to use an application service similar to the following:
namespace MyApp.Data
{
using System.Windows;
using Wintellect.Sterling;
using Wintellect.Sterling.IsolatedStorage;
///
/// Defines a an application service that supports the Sterling database.
///
public class SterlingDatabaseService : IApplicationService, IApplicationLifetimeAware
{
public static SterlingDatabaseService Current { get; private set; }
public ISterlingDatabaseInstance Database { get; private set; }
private SterlingEngine _engine;
///
/// Called by an application in order to initialize the application extension service.
///
/// Provides information about the application state.
public void StartService(ApplicationServiceContext context)
{
Current = this;
_engine = new SterlingEngine();
}
///
/// Called by an application in order to stop the application extension service.
///
public void StopService()
{
_engine = null;
}
///
/// Called by an application immediately before the event occurs.
///
public void Starting()
{
_engine.Activate();
Database = _engine
.SterlingDatabase
.RegisterDatabase(new IsolatedStorageDriver());
}
///
/// Called by an application immediately after the event occurs.
///
public void Started()
{
return;
}
///
/// Called by an application immediately before the event occurs.
///
public void Exiting()
{
_engine.Dispose();
}
///
/// Called by an application immediately after the event occurs.
///
public void Exited()
{
return;
}
}
}
If you use this approach, don't forget to add an instance in App.xaml:
<Application.ApplicationLifetimeObjects>
<!-- Required object that handles lifetime events for the application. -->
<shell:PhoneApplicationService Activated="Application_Activated"
Closing="Application_Closing"
Deactivated="Application_Deactivated"
Launching="Application_Launching" />
<data:SterlingDatabaseService />
</Application.ApplicationLifetimeObjects>

OSGi Declarative Services - NullPointer Exception

I have a problem with my Declarative Services. I have 2 bundles, one is a server provider and another the user interface that consumes the service.
On server side, the implementation is:
public boolean checkUser(){
return true;
}
And the XML file inside OSGi-INF folder:
<component name="ZBService">
<implementation class="service.ZBService" />
<service>
<provide interface="service.IZBService" />
</service>
</component>
On client side, the implementation is:
public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService{
IZBService zb;
public void setZBService(IZBService eventAdmin) {
this.zb = eventAdmin;
}
public void unsetZBService(IZBService eventAdmin){
if(this.zb == eventAdmin){
this.zb = null;}
}
public boolean greetServer(String input, String input2) throws Exception {
return zb.checkUser();
}
}
And XML file:
<component name="ZBService">
<implementation class="main.java.com.gwt.app.server.GreetingServiceImpl" />
<service>
<provide interface="main.java.com.gwt.app.client.GreetingService"/>
</service>
<reference name="zb" interface="service.IZBService" bind="setZBService" unbind="unsetZBService" cardinality="0..n" policy="dynamic" />
</component>
Also, I have included the tag Service-Component on manifest file and I have deployed the equinox ds bundle that is ACTIVE.
The client is a GWT user interface, then I inject the service reference into server side of GWT. Well, when I deploy the application on Equinox it runs, but when I push the button, I launch an event to call ZBService. I have debugged the application and the error is zb attribute is null. It is to say, the dependence is nos injected. However the services are exposed on Equinox. If I write services on Equinox console, the services are deployed. Then, my conclusion is the error is due to the injection does not perform.
I would like to know if someone knows what is the reason??
Thanks a lot in advance!!
Nice day
EDIT:
I did your suggestions but it doesn't run. I change the component names and condinality/policy. The result is the same --> NullPointerException due to the injection isn't done.
Also I have debug the application to see if the methods bind and/or unbind are called, but they aren't.
The complete class is:
public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService{
static protected IZBService zb;
public GreetingServiceImpl(){
System.out.println("Constructor GreetingServiceImpl");
}
public IZBService getZb() {
return zb;
}
public void setZb(IZBService zb) {
GreetingServiceImpl.zb = zb;
}
public void unsetZb(IZBService zb) {
GreetingServiceImpl.zb = zb;
}
#Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// Cache the current thread
Thread currentThread = Thread.currentThread();
// We are going to swap the class loader
ClassLoader oldContextClassLoader = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(this.getClass().getClassLoader());
super.service(req, resp);
currentThread.setContextClassLoader(oldContextClassLoader);
}
public void activate(ComponentContext context) {
System.out.println("Creating new greeter for " + context.getProperties().get("name")
+ ": " + context.getComponentInstance().toString());
}
public void activate() {
System.out.println("Activando la referencia al servicio");
}
public void deactivate(ComponentContext context) {
System.out.println("Deactivating greeter for " + context.getProperties().get("name")
+ ": " + context.getComponentInstance().toString());
}
public boolean greetServer(String input, String input2) throws Exception {
return zb.checkUser();
}
}
And the XML client is:
<?xml version="1.0" encoding="UTF-8" ?>
<scr:component name="serviceZB" xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0">
<implementation class="main.java.com.gwt.app.server.GreetingServiceImpl" />
<!-- <service>
<provide interface="main.java.com.gwt.app.client.GreetingService"/>
</service> -->
<reference name="zb" interface="service.IZBService"
bind="setZb" unbind="unsetZb" cardinality="1..1"
policy="static" />
</scr:component>
Why isn't the service injected if the service is deployed???
Here is a list of things you can try:
First, remove the "static" of zb, that could be the problem.
If you are using Equinox, add the -Dequinox.ds.print=true flag to the VM arguments and see more information about parsing XMLs and so
Of course, add sysouts to setZB and unsetZB :)
Remember that IZBService implementation needs a constructor without arguments
If you are using Equinox use the "list -c" command to obtain information of each component (it's cool because says exactly why a component is not registered).
Set the "inmediate=true" in XMLs to force to inmediatly activation.
You have both components with the same name, , which is kind of awkward when discussing them.
The reference on the client side has: cardinality="0..n" policy="dynamic". Which means it can be activated with zero to n references. Yet your code does not handle this. It seems to expect exactly one reference. Perhaps you should use cardinality="1..1" policy="static".

Resources