I am implementing a IdentityServer3 and want to use a custom IUserService to check against our user table in our database.
Our server handles more than one database (or "tenants"), so the database context is always different per HttpRequest.
var factory = new IdentityServerServiceFactory();
factory.UserService = new Registration<IUserService>(resolver => new MyUserService(resolver.Resolve<IDatabaseInstance>()));
So i want to use a dependency registation per HTTP-request.
I think this is the desired setting:
IdentityServer3.Core.Configuration.RegistrationMode.InstancePerHttpRequest
But how can I use this?
The neccessary database is not known on boot-time in the StartUp-class.
I know the database within the ApiController. So I would like to requester the IDatabaseInstance there.
Can I do this? How can I do this?
Is there an example?
This is not helping, because it covers only simple scenarios...
https://github.com/IdentityServer/IdentityServer3.Samples/tree/master/source/DependencyInjection
Related
After see this documentation I'm not sure if to use a simple context, as I has done other times, or if it is better to use dataSources to handle the database.
DataSource is the correct way to comunicate with the database or it is better use it only to comunicate with a REST API?
Basically, does it have any advantage to use dataSources vs context in this case?
I think it's better to go with DataSource (as the name suggests) and it might be easy to add a caching layer on top of it. You can create a DBDataSource class extending the DataSource class since Apollo doesn't provide any DBDataSource class.
DataSource class is a generic Apollo data source class whereas RESTDataSource class that is responsible for fetching data from a REST API.
So to fetch data from rest APIs it's better to go with RESTDataSource.
Build a custom data source
Apollo doesn't have support for a SQL data source yet (although we'd love to help guide you if you're interested in contributing), so we will need to create a custom data source for our database by extending the generic Apollo data source class. You can create your own with the apollo-datasource package.
Here are some of the core concepts for creating your own data source:
The initialize method: You'll need to implement this method if you want to pass in any configuration options to your class. Here, we're using this method to access our graph API's context.
this.context: A graph API's context is an object that's shared among every resolver in a GraphQL request. We're going to explain this in more detail in the next section. Right now, all you need to know is that the context is useful for storing user information.
Caching: While the REST data source comes with its own built-in cache, the generic data source does not. You can use our cache primitives to build your own, however!
I generally keep resolvers very thin, pass the incoming args to dataSources and they make models and loaders communicate. Most of the logic and validations are in models. You may of course make your own rules like "don't call another dataSource inside a dataSource. Pass their outpus to make them communicate through resolvers" etc. This is only an example of course. Not a strict rule I follow.
There may be better solutions and actually for simple things, using models directly is much more straightforward. But dataSources help you keep things organised and if you want to add caching etc, you can create a BaseDataSource, put all the logic in that and just extend it with other dataSources.
If you look at the documentation that your pointed out. You add data Sources when initializing Apollo Server like this :
const server = new ApolloServer({
typeDefs,
dataSources: () => ({
launchAPI: new LaunchAPI(),
userAPI: new UserAPI({ store })
})
});
and it is because of this dataSources becomes the part of context. If you remember you do the de-structuring of context to expose dataSources as shown here
module.exports = {
Query: {
launches: (_, __, { dataSources }) =>
dataSources.launchAPI.getAllLaunches(),
launch: (_, { id }, { dataSources }) =>
dataSources.launchAPI.getLaunchById({ launchId: id }),
me: (_, __, { dataSources }) => dataSources.userAPI.findOrCreateUser()
}
};
If you want to access the instance of a dataSource such as UserAPI or LaunchAPI, you will have to do that with dataSources.userAPI
I am trying to understand the idea of spring beans and why I should use them. If I create a bean and use it to print something out like this.
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Account acc = (Account)context.getBean("account");
acc.printAccName();
Why not just create an object of that class like this
Account acc2 = new Account();
acc.printAccName();
I have been watching some video's and did some reading but I did not get an answer why it is better.
Usually what you inject is business logic or services which typically is what changes in a system.
You are trying to inject a domain object Account these objects are not subject to change so it is okay to create the object via new. Perhaps, this is what it is confusing you.
The idea, is to let the container handle the instantiation of your logic or services that change regularly so you can swap them easily without having to open the client classes, because these might be already in production, tested and a developer could potentially introduce new bugs and break things. One way to avoid this is to follow a principle called Open-Closed principle. Then you code to abstractions so you can easily inject concrete implementations via dependency injection.
Imagine the following escenario. For a bookstore, you have different implementations of how to save a book into a database e.g. using JDBC BookServiceJDBCImpl, or using an ORM BookServiceHibernateImpl etc..
// Create & get the Spring container, where you configure your implementations
// e.g. bookServiceJDBC, or bookServiceHibernate
ApplicationContext container = new ClassPathXmlApplicationContext("spring-config.xml");
// the container loads the appropriate bean say bookServiceHibernate
BookService bookService = (BookService) container.getBean("bookService");
//Create a new book this is a domain object usually you use new
Book newBook = new Book("1234", "Spring in Action","Rod Johnson");
//Now save the book using the implementation defined in the
//container
bookService.registerNewBook(newBook);
This is how part of the container file may look like, in here you define the concrete implementation:
<bean id="bookService" class="service.BookServiceHibernateImpl"/>
By letting the container handle this you could inject different implementations without having to touch the client class or even knowing which implementation will be passed.
Check this Dependency Injection blog post it explains a way to achieve it using Spring.
Bare in mind that in Spring you can use java annotations or xml, and that there are different ways to inject dependencies e.g. via get/set, constructors etc this is just an illustrative example of the general DI concept. The design is up to the developer.
Another reason why you would use beans is to aid testing.
We also extract the RestTemplate into a #Bean to make it easier to
test (it can be mocked more easily that way). Link
I implemented Dynamic DataSource Routing using Spring Boot (JavaConfig) to add and switch new DataSources in runtime.
I implemented AbstractRoutingDataSource and I need access to all resolvedDataSources that is a private property. How can I do it?
I actually don't know why that field has not been made protected to let implementing classes access the data sources set. Regarding your questions two options come into my mind.
Option 1:
Copy the code of AbstractRoutingDataSource into a class of your own. Then you can expose the resolvedDataSources simply by a getter. This should work as long as the configuration relies on the interface AbstractDataSource and not AbstractRoutingDataSource.
Option 2
Pick the brute force way by accessing the field via Reflection API
I need add membership reboot (RavenDb) into the project that use IOC Simple Injector
Ninject implementation
var config = MembershipRebootConfig.Create();
kernel.Bind<MembershipRebootConfiguration<HierarchicalUserAccount>>().ToConstant(config);
kernel.Bind<UserAccountService<HierarchicalUserAccount>>().ToSelf(); kernel.Bind<AuthenticationService<HierarchicalUserAccount().To<SamAuthenticationService<HierarchicalUserAccount>>();
kernel.Bind<IUserAccountRepository<HierarchicalUserAccount>>().ToMethod(ctx => new BrockAllen.MembershipReboot.RavenDb.RavenUserAccountRepository("RavenDb"));
kernel.Bind<IUserAccountQuery>().ToMethod(ctx => new BrockAllen.MembershipReboot.RavenDb.RavenUserAccountRepository("RavenDb"));
Simple Injector implementation
container.Register(MembershipRebootConfig.Create);
container.Register<UserAccountService<HierarchicalUserAccount>>();
container.Register<AuthenticationService<HierarchicalUserAccount>, SamAuthenticationService<HierarchicalUserAccount>>();
container.Register<IUserAccountRepository<HierarchicalUserAccount>>(() => new RavenUserAccountRepository("RavenDb"), Lifestyle.Singleton);
container.Register<IUserAccountQuery>(() => new RavenUserAccountRepository("RavenDb"));
On row
container.Register<UserAccountService<HierarchicalUserAccount>>();
I have an error
For the container to be able to create UserAccountService, it should contain exactly one public constructor, but it has 2.
Parameter name: TConcrete
Thanks for your help.
Simple Injector forces you to let your components to have one single public constructor, because having multiple injection constructors is an anti-pattern.
In case the UserAccountService is part of your code base, you should remove the constructor that should not be used for auto-wiring.
In case the UserAccountService is part of a reusable library, you should prevent using your container's auto-wiring capabilities in that case as described here. In that case you should fallback to wiring the type yourself and let your code call into the proper constructor, for instance:
container.Register<UserAccountService<HierarchicalUserAccount>>(() =>
new UserAccountService<HierarchicalUserAccount>(
container.GetInstance<MembershipRebootConfiguration<HierarchicalUserAccount>>(),
container.GetInstance<IUserAccountRepository<HierarchicalUserAccount>>()));
I'm just going to include here how I converted the Ninject configuration to Simple Injector for the Single Tenant sample in the MembershipReboot repository (which I cloned). I thought that might be beneficial for anyone who was searching for how to go about this, as it may save them some time.
Firstly, the configuration in the Single Tenant sample's NinjectWebCommon class is:
var config = MembershipRebootConfig.Create();
kernel.Bind<MembershipRebootConfiguration>().ToConstant(config);
kernel.Bind<DefaultMembershipRebootDatabase>().ToSelf();
kernel.Bind<UserAccountService>().ToSelf();
kernel.Bind<AuthenticationService>().To<SamAuthenticationService>();
kernel.Bind<IUserAccountQuery>().To<DefaultUserAccountRepository>().InRequestScope();
kernel.Bind<IUserAccountRepository>().To<DefaultUserAccountRepository>().InRequestScope();
Now, I'll set out the whole SimpleInjectorInitializer class, which started with the one which was added to the project via the SimpleInjector.MVC3 Nuget package, and follow up with comments:
public static class SimpleInjectorInitializer
{
/// <summary>Initialize the container and register it as MVC3 Dependency Resolver.</summary>
public static void Initialize()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
InitializeContainer(container);
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
private static void InitializeContainer(Container container)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<DefaultMembershipRebootDatabase, BrockAllen.MembershipReboot.Ef.Migrations.Configuration>());
var config = MembershipRebootConfig.Create();
container.Register(() => config, Lifestyle.Singleton);
container.Register(() => new DefaultMembershipRebootDatabase(), Lifestyle.Scoped);
container.Register<IUserAccountQuery, DefaultUserAccountRepository>(Lifestyle.Scoped); // per request scope. See DefaultScopedLifestyle setting of container above.
container.Register<IUserAccountRepository, DefaultUserAccountRepository>(Lifestyle.Scoped);
container.Register(() => new UserAccountService(container.GetInstance<MembershipRebootConfiguration>(), container.GetInstance<IUserAccountRepository>()));
container.Register<AuthenticationService, SamAuthenticationService>();
var iUserAccountQueryRegistration = container.GetRegistration(typeof(IUserAccountQuery)).Registration;
var iUserAccountRepositoryRegistration = container.GetRegistration(typeof(IUserAccountRepository)).Registration;
iUserAccountQueryRegistration.SuppressDiagnosticWarning(DiagnosticType.TornLifestyle, "Intend for separate Objects");
iUserAccountRepositoryRegistration.SuppressDiagnosticWarning(DiagnosticType.TornLifestyle, "Intend for separate Objects");
}
}
Scoping the config to a Singleton with a factory func is pretty much the same as Ninject's ToConstant.
DefaultMembershipRebootDatabase is the obvious departure, but I honestly don't think it matters whether MR's DefaultMembershipRebootDatabase is scoped a transient or per web request. It calls SaveChanges every time an operation is performed e.g. Registering a user. It does not use larger, per request-bound tansactions. So, using the same DefaultMembershipRebootDatabase context later in the same request is no going to cause any weird MR issues.
HOWEVER, some thought will need to given to what happens if you want to create a Domain User during the same operation as you create a MR UserAccount. (A Domain User may contain more information beyond password stuff, like first and last names, DOB etc.). Tying an MR UserAccount to a Domain User (with additional user info such a name, address etc.) is a common use case. So what happens if the creation of the Domain User fails after creation of the MR UserAccount succeeded? I don't know. Perhaps as part of the rollback, you delete the MR user. But the registration email will already have been sent. So, these are the issues that you face here.
As you can see, in the Simple Tenant sample, Brock registers both IUserAccountRepository and IUserAccountQuery to DefaultUserAccountRepository. This is obviously by design and so we have to do that as well, if we want to use MR's UserAccountService and AuthenticationService. Thus, we need to suppress the Diagnostic warnings which would otherwise prevent the Container from Verifying.
Hope that all helps and by all means let me know if there are problems with my registrations.
Cheers
Is there a way in spring wherein we can read the fields of a bean from the DB table and create a complete bean class - with getters and setters on server startup????
I require this to make my application completely configurable...as in if I have to add a new field in future , all I would require would be adding a field in the db and the bean setters and getters would be available to me.
Thanks
You could try approaches for dynamically registering beans . You could use the BeanDefinitionBuilder for this purpose . See a sample here . But as #Darren says , It's not a wise idea to creak a bean via DB lookup .
1: Improve your accept-rate
2: You might benefit from something like an ORM approach (Hibernate or JPA). Another slightly different approach that might suite you is the Active Record pattern as implemented in, forinstance, ActiveJDBC.
Spring does not, in itself, offer anything like what you are after, but using spring-jpa together with Hibernate might get you a bit closer towards your goal. If, OTOH, you want auto-generated code you could also look at something like Spring-Roo
You might want to think about this a little more. Even if you made your fields totally configurable, you will still have to write the code that accesses them. And given that you are going to have to write code anyway, might as well keep everything in code. It's much simpler that way.