I am very new to hybris e-commerce software and trying to learn with the help of wiki documents provided with it.
I see use of 'tenant' scope quite frequently. I know about other scopes like 'singleton', 'prototype' etc. But I am not very clear with the tenant scope.
appreciate if someone have a good understanding about this scope, and explain in simple terms.
Thanks.
The core-spring.xml file of the core extension adds a special scope named tenant to the global ApplicationContext. The tenant scope makes sure that the bean is instantiated individually for each individual tenant of the hybris, whereas singleton would create only one instance for all tenants to use.
If you reference tenant-specific classes like services or DAOs inside your implementation, you have to use the tenant scope instead of the default Spring singleton scope. In case of doubt, use tenant instead of singleton.
<bean id="myExtension.myBean" class="de.hybris.platform.myExtension.myClass" scope="tenant" />
Since version 5.0 of hybris Commerce Suite, tenant scope is no longer in use.
Check this for more details...
Hybris has 2 tenants by default- master tenant and junit tenant. You can create more tenants as required.
Each tenant has its own set of data...say item types.
When a bean is defined in a tenant scope, it means that, that bean would be instantiated once for each tenant. And the same bean object would be used throughout the tenant.
hybris can be run in a Multi-Tenant mode which multiple individual sets of data are maintained on one single hybris installation.
When a bean is defined with a tenant scope, it will only be instantiated individually for each tenant; whereas singleton would create only one instance for all tenants to use.
Related
I'm trying to understand Dependency Injection in .NET Core. Can someone point me to where services added with AddScoped (in Startup.cs) are store at?
Is it the HttpContext variable?
Services configured in the IServiceCollection aren't really "stored" at least not in any lookup table that the application should be referencing directly!
Adding an service using AddScoped, AddTransient or AddSingleton simply tells the framework how to produce a service within a scope. The framework will manage producing the service from the defintion when constructing managed components via Dependency Injection, or it will use a cached version when one already exists for that scope.
For AddScoped, the framework will be using some sort of cache keyed by a request/connection id, but all you have to do is write a transient or scoped component (such as a Controller) and declare an instance of your scoped service as a dependency in the constructor.
I'm currently writing a service in Go where I need to deal with multiple tenants. I have settled on using the one database, shared-tables approach using a 'tenant_id' decriminator for tenant separation.
The service is structured like this:
gRPC server -> gRPC Handlers -
\_ Managers (SQL)
/
HTTP/JSON server -> Handlers -
Two servers, one gRPC (administration) and one HTTP/JSON (public API), each running in their own go-routine and with their own respective handlers that can make use of the functionality of the different managers. The managers (lets call one 'inventory-manager'), all lives in different root-level packages. These are as far as I understand it my domain entities.
In this regard I have some questions:
I cannot find any ORM for Go that supports multiple tenants out there. Is writing my own on top of perhaps the sqlx package a valid option?
Other services in the future will require multi-tenant support too, so I guess I would have to create some library/package anyway.
Today, I resolve the tenants by using a ResolveTenantBySubdomain middleware for the public API server. I then place the resolved tenant id in a context value that is sent with the call to the manager. Inside the different methods in the manager, I get the tenant id from the context value. This is then used with every SQL query/exec calls or returns a error if missing or invalid tenant id. Should I even use context for this purpose?
Resolving the tenant on the gRPC server, I believe I have to use the UnaryInterceptor function for middleware handling. Since the gRPC
API interface will only be accessed by other backend services, i guess resolving by subdomain is unneccessary here. But how should I embed the tenant id? In the header?
Really hope I'm asking the right questions.
Regards, Karl.
I cannot find any ORM for Go that supports multiple tenants out there. Is writing my own on top of perhaps the sqlx package a valid option?
ORMs in Go are a controversial topic! Some Go users love them, others hate them and prefer to write SQL manually. This is a matter of personal preference. Asking for specific library recommendations is off-topic here, and in any event, I don't know of any multi-tenant ORM libraries – but there's nothing to prevent you using a wrapper of sqlx (I work daily on a system which does exactly this).
Other services in the future will require multi-tenant support too, so I guess I would have to create some library/package anyway.
It would make sense to abstract this behavior from those internal services in a way which suits your programming and interface schemas, but there's no further details here to answer more concretely.
Today, I resolve the tenants by using a ResolveTenantBySubdomain middleware for the public API server. I then place the resolved tenant id in a context value that is sent with the call to the manager. Inside the different methods in the manager, I get the tenant id from the context value. This is then used with every SQL query/exec calls or returns a error if missing or invalid tenant id. Should I even use context for this purpose?
context.Context is mostly about cancellation, not request propagation. While your use is acceptable according to the documentation for the WithValue function, it's widely considered a bad code smell to use the context package as currently implemented to pass values. Rather than use implicit behavior, which lacks type safety and many other properties, why not be explicit in the function signature of your downstream data layers by passing the tenant ID to the relevant function calls?
Resolving the tenant on the gRPC server, I believe I have to use the UnaryInterceptor function for middleware handling. Since the gRPC API interface will only be accessed by other backend services, i guess resolving by subdomain is unneccessary here. But how should I embed the tenant id? In the header? [sic]
The gRPC library is not opinionated about your design choice. You can use a header value (to pass the tenant ID as an "ambient" parameter to the request) or explicitly add a tenant ID parameter to each remote method invocation which requires it.
Note that passing a tenant ID between your services in this way creates external trust between them – if service A makes a request of service B and annotates it with a tenant ID, you assume service A has performed the necessary access control checks to verify a user of that tenant is indeed making the request. There is nothing in this simple model to prevent a rogue service C asking service B for information about some arbitrary tenant ID. An alternative implementation would implement a more complex trust-nobody policy whereby each service is provided with sufficient access control information to make its own policy decision as to whether a particular request scoped to a particular tenant should be fulfilled.
I am new to Castle Windsor and Fluent NHibernate (AutoMapping).
I am currently working on multi Tenant application and have following requirement.
Master Database to store tenant information
Database per tenant
I have integrated the persistence facility using castle Windsor and I am able to access the Master Database. I am getting stuck where in I want to get the connection info for the tenant from the master Db, pass this information to the persistence facility again to build new session. So, eventually can have access to master db and tenant specific Db.
Can any one guide me how can I proceed on this.
In short:
On user log in, I want to validate the user and identify its tenant Database connection string from master db and use this info to build new session for tenant specific db operations.
I would create 2 derived classes from ISession: IMasterSession and ITenantSession.
This allows you to easily refer to either database from your controllers or view models.
You will need to make two registrations for ISessionFactory 1 for your master database and 1 for your tenant database. Name these so that you can refer to these.
Now register IMasterSession as follows:
Component.For<ISession>().PerWebRequest().Named("masterSession").UsingFactoryMethod((k, m) =>
{
var masterFactory = k.Resolve<ISessionFactory>("masterSessionFactory");
return masterFactory.OpenSession();
}),
Component.For<object>().Forward<IMasterSession>().Proxy.MixIns(registration =>
registration.Component("masterSession"))
The session factories must be registered with lifestyle singleton, since you will only need one in your application. The lifetime of your session will depend on the kind of application you are making, probably PerWebRequest.
There might be a better way to do this, and I would love to hear that.
The approach for the tenant database should similar. However you would either need to use the overload of OpenSession that takes a IDBConnection or Implement a custom connection provider. You can find more about that here
I hope this helps.
Kind regards,
Marwijn.
We are developing a multi-tenant application using NHibernate where all tenants share the same database.
One option we considered was to use a tenant specific prefix for our database objects (I believe this the same approach taken by Orchard).
This would at least give us some kind of recovery model for tenant data and would mean we wouldn't have to include a tenantid filter on most of our queries.
So my question - has anyone employed this strategy? If so, how did you go about it.
Specifically, can we use the same SessionFactory for all tenants and can we use NHibernate to generate a new set of tables for a "new" tenant at runtime (is it safe to do so).
Thanks
Ben
[Update]
This was a worthwhile investigation but ultimately we decided that a shared schema was more suitable for our needs. Schema per tenant clearly offers better separation of tenant data but makes maintenance more difficult. Since our tenants are only storing small amounts of data, the thought of having 10 tables * 1K tenants is a little off-putting.
There are a couple of points of customization / extension that you may want to consider.
I don't think that you will be able to share the same session factory across tenants. I think that the simplest thing to do may be to update the mappings based on the tenant associated with the session factory.
public class EntitytMap:ClassMap<Entity>
{
public EntitytMap()
{
Table("TableName");
Schema(Session.TenantName);
Id(p => p.Id, "Id").GeneratedBy.Identity();
If you want to have each tenant in their own schema, this should work. If you want to keep the schema the same but have a prefix on the table, you could change to:
public class EntityMap:ClassMap<Entity>
{
public EntityMap()
{
Table(Session.TenantPrefix + "TableName");
Schema("SCHEMA");
Id(p => p.Id, "Id").GeneratedBy.Identity();
You can also try providing your own ConnectionProvider. Derive a class from NHibernate.Connection.DriverConnectionProvider and reference your own copy in the nhibernate configuration file instead of:
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
use
<property name="connection.provider">My.Project.DAL.NHibernate.CustomConnectionProvider, My.Project.DAL</property>
When the GetConnection provider is called, you can specify your own connection string based on the tenent.
can we use NHibernate to generate a new set of tables for a "new" tenant
at runtime (is it safe to do so)
I'd suggest that you wouldn't want to grant your web application the level of permissions required to perform these DDL tasks. I'd leave the web app with the minimum level of permissions for normal DML operations and have a background service operating as a 'Provisioning Service'. Its role would be schema modifications for the new tenant, and it is also a good place to put any other tenant provisioning tasks such as creating new folders, configuring IIS etc. All these tasks take time too and are best not done in a single web request. The background database can update a provisioning table, updating it with information about its progress until its complete and the web ui moves to the next step.
I know that the session is used for the database in Hibernate, but what is the task of the session in database?
Does anyone know about this?
Update:
Apologies, my links are to Java APIs (must have missed the nhibernate tag). Regardless, there will be more than one type of session for .NET also.
There will typically be more than one type of session:
The HttpSession is a server-side object:
Provides a way to identify a user
across more than one page request or
visit to a Web site and to store
information about that user.
The hibernate Session is also a server-side object:
The lifecycle of a Session is bounded
by the beginning and end of a logical
transaction. (Long transactions might
span several database transactions.)
The main function of the Session is to
offer create, read and delete
operations for instances of mapped
entity classes.
The session is server side, if by server side you mean as in the web application or client/server application sense.
It is an implementation of the Unit of Work pattern, and does stuff like keeping track of which entities that have been changed, caching of entities and making sure that a specific entity is represented by only one actual instance in the scope of the session.
The NHibernate docs describe ISession like this:
A single-threaded, short-lived object
representing a conversation between
the application and the persistent
store. Wraps an ADO.NET connection.
Factory for ITransaction. Holds a
mandatory (first-level) cache of
persistent objects, used when
navigating the object graph or looking
up objects by identifier.