So I'm trying to send a simple message from a SharePoint webpart to an endpoint. For now, i'm setting the bus in a simple static class use in the webpart. The class gets called and the bus seems to be working, but when i try to send the message, i get:
No destination specified for message SharePointMessages.CreateProject. Message cannot be sent. Check the UnicastBusConfig section in your config file and ensure that a MessageEndpointMapping exists for the message type.
The class looks like this:
public static class Infrastructure
{
public static IBus Bus { get; private set; }
static Infrastructure()
{
var mappings = new MessageEndpointMappingCollection();
mappings.Add(new MessageEndpointMapping()
{
Messages = "SharePointMessages.CreateProject",
Endpoint = "SharePointProxy"
});
Configure config = Configure.WithWeb();
config
.Log4Net()
.DefaultBuilder()
.XmlSerializer()
.MsmqTransport()
.IsTransactional(true)
.UnicastBus()
.Configurer.ConfigureComponent<UnicastBusConfig>(ComponentCallModelEnum.None)
.ConfigureProperty(x => x.MessageEndpointMappings, mappings);
Bus = config.CreateBus().Start();
}
}
The SharePointMessages.CreateProject class implements IMessage and has two properties.
The queues get created properly if they are not there. So it seems like everything is working but for some reason the mappings are not there. Can anyone see what I'm doing wrong?
Cheers
You have to use a custom configuration source - http://docs.particular.net/nservicebus/messaging/message-owner
Related
I am doing a Publish - Subscribe using external ActiveMQ (5.15.10). My application is deployed on TomEE 8.0.1 server and ActiveMQ configurations are done in tomee.xml.
I am able publish the message successfully but while receiving messages am facing issues. In onMessage method I need to process a pojo and I get below error
"This class is not trusted to be serialized as ObjectMessage payload"
I use EclipseLink JPA in my application and I need to send the pojo that I receive in onMessage method to my #Stateless bean (here UserService) to process it further. So, UserService is injected with #EJB annotation in my MDBSubscriber class below.
#MessageDriven(
activationConfig = {
#ActivationConfigProperty(
propertyName = "destinationType",
propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(
propertyName = "destination",
propertyValue = "userQueue")
}
)
public class MDBSubscriber implements MessageListener {
#EJB
UserService uService;
public void onMessage(Message msg) {
if(msg instanceof ObjectMessage) {
ObjectMessage objMsg = (ObjectMessage) msg;
UserForm uForm= (UserForm) objMsg.getObject();
----
----
uService.process(uForm);
}
}
}
When I read through ActiveMQ docs, it says setTrustAllPackages=true can be set on ActiveMQConnectionFactory object but since am using #MessageDriven Bean I don't have ActiveMQConnectionFactory object in my class defined above.
So, my problem is where or how do we define setTrustAllPackages=true in #MessageDriven Bean?
I am stuck with this problem since more than 10 days and could not find a solution.
Can someone help me here ?
You can configure this via a system property as well which avoids the trustAllPackages connection factory option. There is documentation for this already on the ActiveMQ site.
In case you want to shortcut this mechanism, you can allow all packages to be trusted by using * wildcard, like
-Dorg.apache.activemq.SERIALIZABLE_PACKAGES=*
I have a bus endpoint that processes a message, however I now want to put another message back on to the bus inside this handler.
To do this I need to get a reference to the bus.
However if I try the following:
public class ServerEndpoint: IWantToRunAtStartup
{
public static IBus Bus { get; set; }
public void Run()
{
int x = 5;
Bus = NServiceBus.Configure.With()
.DisableTimeoutManager()
.Log4Net()
.DefaultBuilder()
.XmlSerializer()
.MsmqTransport()
.IsTransactional(false)
.PurgeOnStartup(false)
.UnicastBus()
.ImpersonateSender(false)
.CreateBus()
.Start();
}
public void Stop()
{
}
}
Then I get all sort of config errors, even if I put the Unicast and Msmq Configs in the app.config.
Could anyone provide me with pointers, I'm hoping this is a fairly straightforward mistake!!
Thanks
Duncan
EDIT: This is on the server. The thing that is confusing me is that the bus gets configured on the web app using the above code, in the global.asax App_Start() method. But when trying to do this in the ServerEndpoint (the actual 'bus' dll, run inside the host) this doesn't work.
You use Dependency Injection for that, see http://support.nservicebus.com/customer/portal/articles/862398-how-do-i-get-a-reference-to-ibus-in-my-message-handler-
Thanks for all the feedback - I was trying to run before I could walk.
By the looks of things, to send a message to another endpoint, I need to set up a different assembly (ServiceBus.Host).
The Bus is created automatically using DI, so this wasn't the problem after all.
I watched the excellent Pluralsight videos by Andreas Ohlund (http://pluralsight.com/training/Courses/TableOfContents/nservicebus) and followed the examples he built here (See BusStop - Billing Take 2)
I am trying to setup NServiceBus Sagas using NHibernate persistence, but I think I have something configured incorrectly because I'm getting an error connecting to a service at 127.0.0.1:8080. I am able to get my saga to handle the command message, but after a few seconds the error message below appears in the console window and then the same command is fired again causing the handler in the saga to be invoked again. This happens repeatedly as long as I allow the application to run. I can tell NHibernate is connecting to my database because it creates a table for the saga data, however nothing is ever persisted in that table.
I think there is an error persisting the saga data, and my guess is that it may be trying to use the default RavenDb saga persistence but I'm not sure why this would be.
The error message I receive is the following:
WARN
NServiceBus.Unicast.Transport.Transactional.TransactionalTransport
[(null)] <(null)> - Failed raising 'transportmessage received' event
for message with ID=3753b476-7501-4fd8-90d0-b10aee95a578\22314
System.Net.WebException: Unable to connect to the remote server --->
System.Net.Sockets.SocketException: No connection could be made
because the target machine actively refused it 127.0.0.1:8080 at
System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot,
SocketAddress socketAddress) at
System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP) at
System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure,
Socket s4, Socket s6, Socket& socket, IPAddress& address,
ConnectSocketState state, IAsyncResult asyncResult,Exception&
exception) --- End of inner exception stack trace --- at
NServiceBus.Unicast.UnicastBus.HandleTransportMessage(IBuilder
childBuilder, TransportMessage msg) at
NServiceBus.Unicast.UnicastBus.TransportMessageReceived(Object sender,
TransportMessageReceivedEventArgs e) at
System.EventHandler`1.Invoke(Object sender, TEventArgs e) at
NServiceBus.Unicast.Transport.Transactional.TransactionalTransport.OnTransportMessageReceived(TransportMessage
msg)
A sample of the saga I am trying to use is (nothing fancy here, same thing happens whether or not I actually do something in the Handle method):
public class ItemSaga : Saga<ItemData>, IAmStartedByMessages<CreateItemCommand>
{
public void Handle(CreateItemCommand message)
{
}
}
public class ItemData : ISagaEntity
{
public Guid Id { get; set; }
public string Originator { get; set; }
public string OriginalMessageId { get; set; }
}
My endpoint configuration looks like this:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Publisher, IWantCustomInitialization
{
public void Init()
{
var container = new UnityContainer();
container.AddNewExtension<Domain.UnityExtension>();
Configure.With()
.UnityBuilder(container)
.JsonSerializer()
.Log4Net()
.MsmqSubscriptionStorage()
.MsmqTransport()
.PurgeOnStartup(true)
.UnicastBus()
.ImpersonateSender(false)
.DisableTimeoutManager()
.NHibernateSagaPersister()
.CreateBus()
.Start(() => Configure.Instance.ForInstallationOn<NServiceBus.Installation.Environments.Windows>().Install());
}
}
And my app.config looks like this:
<MessageForwardingInCaseOfFaultConfig ErrorQueue="error"/>
<MsmqTransportConfig NumberOfWorkerThreads="1" MaxRetries="5"/>
<NHibernateSagaPersisterConfig UpdateSchema="true">
<NHibernateProperties>
<add Key="connection.provider" Value="NHibernate.Connection.DriverConnectionProvider"/>
<add Key="connection.driver_class" Value="NHibernate.Driver.Sql2008ClientDriver"/>
<add Key="connection.connection_string" Value="Data Source=(localdb)\v11.0;Integrated Security=True;AttachDbFileName=|DataDirectory|\App_Data\EventStore.mdf"/>
<add Key="dialect" Value="NHibernate.Dialect.MsSql2012Dialect"/>
</NHibernateProperties>
</NHibernateSagaPersisterConfig>
<connectionStrings>
<add name="EventStore" connectionString="Data Source=(localdb)\v11.0;Integrated Security=True;AttachDbFileName=|DataDirectory|\App_Data\EventStore.mdf"
providerName="System.Data.SqlClient" />
</connectionStrings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="NHibernate" publicKeyToken="aa95f207798dfdb4" />
<bindingRedirect oldVersion="0.0.0.0-3.3.0.4000" newVersion="3.3.1.4000" />
</dependentAssembly>
</assemblyBinding>
</runtime>
Just a couple of notes:
This is from a sample app that I am using to test this functionality. It uses a local database file attached to localdb, however my full application using SQL Server 2012 is exhibiting the same behavior. I also had to add a dependenteAssembly entry for NHibernate because the NServiceBus.NHibernate NuGet package currently binds to an older assembly version (as of this posting).
As you can see, I am also using Unity as my IOC, but I have replicated this with a project using Ninject as well. I am using EventStore for my domain storage which is working great. I have command handlers that handle the command and publish events through EventStore to be handled by other processes. However, I have tried disabling all of those leaving me with just my Saga as a command handler and I still get the same error.
Does anyone have any ideas of what I may be doing wrong?
I have found a workaround to my problem. It seems to be an issue with using the built-in NServiceBus profiles. I was not specifying a profile in the command line arguments of the host, so by default it was loading the NServiceBus.Production profile. The Production profile, by default, uses RavenDB for all persistence.
Looking at the NServiceBus source on GitHub, the Production Profile Handler contains the following in the ProfileActivated method:
Configure.Instance.RavenPersistence();
if (!Configure.Instance.Configurer.HasComponent<ISagaPersister>())
Configure.Instance.RavenSagaPersister();
if (!Configure.Instance.Configurer.HasComponent<IManageMessageFailures>())
Configure.Instance.MessageForwardingInCaseOfFault();
if (Config is AsA_Publisher && !Configure.Instance.Configurer.HasComponent<ISubscriptionStorage>())
Configure.Instance.RavenSubscriptionStorage();
A couple of things to note here:
The profile will always call RavenPersistence() on the
Configure instance. I have not dug into the inner workings of that
method to see if it will actually bypass configuring Raven if other
persistence is already defined, but it will always run this method.
When I attach to the NServiceBus source and debug through
this code, in the second line HasComponent returns
false causing the RavenSagaPersister configuration to be run. This
happens even if I have NHibernateSagaPerister is defined in the endpoint
configuration.
I'm not sure if this behavior is by design, a bug, or misconfiguration on my part. However my workaround was to create my own profile. I had to move the NHibernate configuration calls from my endpoint config to my new profile, but once I did that I was able to use NHibernate persistence without errors.
My custom profile looks like the following (I borrowed the logging handler from the Production profile's logging handler):
public class MyProfile : IProfile
{
}
internal class MyProfileProfileHandler : IHandleProfile<MyProfile>, IWantTheEndpointConfig
{
void IHandleProfile.ProfileActivated()
{
Configure.Instance.NHibernateUnitOfWork();
Configure.Instance.NHibernateSagaPersister();
Configure.Instance.DBSubcriptionStorage();
Configure.Instance.UseNHibernateTimeoutPersister();
}
public IConfigureThisEndpoint Config { get; set; }
}
public class MyProfileLoggingHandler : IConfigureLoggingForProfile<MyProfile>
{
void IConfigureLogging.Configure(IConfigureThisEndpoint specifier)
{
SetLoggingLibrary.Log4Net<RollingFileAppender>(null,
a =>
{
a.CountDirection = 1;
a.DatePattern = "yyyy-MM-dd";
a.RollingStyle = RollingFileAppender.RollingMode.Composite;
a.MaxFileSize = 1024 * 1024;
a.MaxSizeRollBackups = 10;
a.LockingModel = new FileAppender.MinimalLock();
a.StaticLogFileName = true;
a.File = "logfile";
a.AppendToFile = true;
});
if (GetStdHandle(STD_OUTPUT_HANDLE) == IntPtr.Zero)
return;
SetLoggingLibrary.Log4Net<ColoredConsoleAppender>(null,
a =>
{
LiteLoggingHandler.PrepareColors(a);
a.Threshold = Level.Info;
}
);
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
const int STD_OUTPUT_HANDLE = -11;
}
A final note, I also had to set all of the properties of my saga data object as virtual, per standard NHibernate practice. This became very apparent once the system was actually using NHibernate.
public class ItemData : ISagaEntity
{
public virtual Guid Id { get; set; }
public virtual string Originator { get; set; }
public virtual string OriginalMessageId { get; set; }
}
This is a long explanation, but hopefully it'll help someone else out down the road. If anyone has suggestions on a better way to accomplish this, or the correct way to use profiles, please let me know!
After adding section for SQL Database to handle subscriptions, My subscriber config looks like this
;initial catalog=NServiceBus;Integrated Security=SSPI"/>
I changed the endpoint class as follows
class EndpointConfig : IConfigureThisEndpoint, AsA_Server , IWantCustomInitialization
{
public void Init()
{
NServiceBus.Configure.With()
.Log4Net()
.DefaultBuilder()
.XmlSerializer()
.UnicastBus()
.ImpersonateSender(false)
.DBSubcriptionStorage();
}
}
When I fire up the application, where subscribers automatically subscribe, I don't see any entries in the subscription DB. Also I don't see any error reported by the application... Anything I am missing in the config file...
Appreciate any help...
When using the builtin roles like As_aServer the role config takes precedence. So in your case the db sub.storage will only be used if you use As_aPublisher + run in the "production" profile.
After changing the Subscriber2 project in the PubSub sample, I am getting this error when a message is received by this subscriber:
ERROR
NServiceBus.Unicast.Transport.Msmq.MsmqTransport
[(null)] <(null)> - Could not extract
message data.
System.TypeLoadException: Could not
handle type 'MyMessages.EventMessage'.
I changed the EndpointConfig.cs file to this:
using NServiceBus;
namespace Subscriber2
{
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization
{
public void Init()
{
Configure.With(new[] { typeof(EventMessageHandler), typeof(NServiceBus.Unicast.Transport.CompletionMessage) })
.DefaultBuilder()
.XmlSerializer()
.UnicastBus()
.DoNotAutoSubscribe();
}
}
}
Does anyone know why this doesn't work?
You did not specify your message type in the list. If you use this overload of With() you will have to supply all types. I would recommend pointing to a specific assembly instead and letting NSB scan it for the correct types. Alternatively you could do nothing and let it scan the bin directory.