I am new to spring and not able to understand when to instantiate the class with new operator and when by using spring container.
example i found a code
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeDao dao=(EmployeeDao)ctx.getBean("edao");
int status=dao.saveEmployee(new Employee(102,"Amit",35000));
System.out.println(status);
int status=dao.updateEmployee(new Employee(102,"Sonoo",15000));
System.out.println(status);
Employee e=new Employee();
e.setId(102);
int status=dao.deleteEmployee(e);
System.out.println(status);
}
}
i am using jdbc template. i have a doubt why we have new to instatiate employee class instead we should have used (Employee)ctx.getBean("employee"). using new operator would create dependency?
Pls help
From ProSpring book,
"Of the applications that we have built using Spring,
the only objects that are consistently not managed by Spring are domain objects. (Even though in Spring
it’s possible to have Spring manage domain objects by applying the #Component annotation to the classes
and assigning them with prototype scope, most of the time we will choose to manage domain objects
within the application.) The reason for this is that, practically, Spring does not need to be involved with
domain objects. Generally, you create many instances of your domain objects using the new() operator
and perform processing either in the service or data access layer. Although Spring also supports the
injection of new instance of domain objects every time it was requested (by using the bean scope
prototype), generally developers will not adopt this approach since typically domain objects do not take
advantage of Dependency Injection, because they generally have few dependencies outside of the DOM
itself, and they don’t require much configuration."
So, yes you could create beans of type Employee but then they wil have to be defined as prototype as be default all beans in spring are singletons. because there can be many employees and their objects, you obviously cannot have Employee as a singleton. but your concentration as to the utilization of spring features should be much more than managing domain objects.
The Spring IOC container is at the core of the Spring Framework. The container will create the objects, wire them together, configure them, and manage their complete lifecycle from creation till destruction.The IoC container gets informations/metadata either from XML or by Java annotations, or by Java code.
Yeah you can create Employee bean in your spring context xml file and make sure scope is prototype as
<bean id="employee" class="com.mycompany.Employee" scope="prototype"/>
so that on every request of Employee bean, you will get a new object Employee.
There are other scopes of beans
singleton : This scopes the bean definition to a single instance per Spring IoC container (default).
request : On every HTTP request a new bean will created and delivered.
prototype : on every request(api request) a new bean will be created.
session : This scope a bean definition to an HTTP session.
Note : It is not recomemded to create beans for database model class.because your persistent layer will take care of it.
Related
How would you configure the middleware to change the DBContext connection string based on a sub-domain of the income request?
It appears that the DBContext is set in the Startup... which looks too early to determine the HTTPRequest to resolve the connection string.
Well, this might not suit your needs entirely, but here's what I would do:
Create a DbContextFactory class. This DbContextFactory class can create instances of the DbContext and can pass in any string to the DbContext constructor. Then inject this factory and whenever you need an instance of the dbcontext, just ask the factory to return one for you. Of course you have to manage the lifetime of the created contexts yourself (i.e. using block).
Another option can be to create the DbContextFactory so that it holds an instance of a DbContext. When you ask for a context object from the factory, the factory creates a new one and also stores it in a private field, and subsequent calls return that same instance. Make the factory IDisposable and in its Dispose() method, dispose the context as well. This way you don't have to worry about managing lifetime (if you use a Scoped registration).
I want to know whether I can use object of service layer marked with #Service annotation and call one of its method in non mvc-spring class ?
Say there is a method getUsers() in service layer which calls getUsers() of Dao layer. In order to use it in contoller I have to add the #Autowired-annotation in the service layer instance. But if I want to use the class method getUsers() in non-mvc class, how can I do that?
In order to use a service, that object must be container managed. That is, this object's life cycle must be managed by Spring (creation, destruction, initialisation,...).
So to inject an instance of your service in an object, it must be a Spring bean too (Service, Component, Controller...).
So, it may be an MVC object, but it doesn't have to.
On the other hand, there is another alternative: use the annotation #Configurable.
An object with this annotation can be application managed but Spring, using byte code aspects, can inject it's dependencies. So although you create the object with a new statement, Spring instruments this call and resolve all the annotated dependencies.
Read this for more detail:
http://docs.spring.io/spring/docs/3.0.0.M3/spring-framework-reference/html/ch08s08.html
My application is using SQL Server 2012, EF6, MVC and Web API.
It's also using a repository and assorted files such as:
DatabaseFactory.cs
Disposable.cs
IDatabaseFactory.cs
IRepository.cs
IUnitOfWork.cs
RepositoryBase.cs
UnitOfWork.cs
We already use a service layer between our controllers and the repository
for some complicated business logic. We have no plans EVER to change to a different database and it has been pointed
out to me that the recent thinking is that EF6 is a repository so why build
another repository on top of it and why have all of the files I have above.
I am starting to think this is a sensible approach.
Does anyone know of any examples out there that implement EF6 without a
repository, with a service layer. My search on the web has revealed many
complex code examples that seem over complicated for no reason at all.
My problem is also when using a Service Layer then where do I put:
context = new EFDbContext()
In the controller, the service layer or both ? I read that I can do this with dependancy injection. I already use Unity as an IOC but I don't know how I can do this.
Entity Framework IS already a Unit of Work pattern implementation as well as a generic repository implementation (DbContext is the UoW and DbSet is the Generic Repository). And I agree that it's way overkill in most apps to engineer another UoW or Generic Repository on top of them (besides, GenericRepsitory is considered to be an anti-pattern by some).
A Service layer can act as a concrete repository, which has a lot of benefits of encapsulating data logic that is specific to your business needs. If using this, then there is little need to build a repository on top of it (unless you want to be able to change your backend service technology, say from WCF to WebApi or whatever..)
I would put all your data access in your service layer. Don't do data access in your controller. That's leaking your data layer into your UI layer, and that's just poor design. It violates many of the core SOLID concepts.
But you do NOT need an additional UnitOfWork, or other layers beyond that in most cases, unless your apps are very complex and intended to work in multiple environments...
Setting up Unity for ASP.NET MVC and WebAPI is quite easy if you install and add the Unity.Mvc* and Unity.WebAPI* Nuget packages to your project. (The * is a version number, like 3 or 4 or 5. Look for the appropriate versions for your project. Here are for example the links to the Unity.Mvc 5 package and to the Untity.WebAPI 5 package.)
The usage of these packages is explained in this blog post.
The building blocks are roughly like so:
You build a unity container and register all your dependencies there, especially the EF context:
private static IUnityContainer BuildContainer()
{
var container = new UnityContainer();
container.RegisterType<MyContext>(new HierarchicalLifetimeManager());
container.RegisterType<IOrderService, OrderService>();
container.RegisterType<ICustomerService, CustomerService>();
container.RegisterType<IEmailMessenger, EmailMessenger>();
// etc., etc.
return container;
}
MyContext is your derived DbContext class. Registering the context with the HierarchicalLifetimeManager is very important because it will ensure that a new context per web request will be instantiated and disposed by the container at the end of each request.
If you don't have interfaces for your services but just concrete classes you can remove the lines above that register the interfaces. If a service needs to be injected into a controller Unity will just create an instance of your concrete service class.
Once you have built the container you can register it as dependency resolver for MVC and WebAPI in Application_Start in global.asax:
protected void Application_Start()
{
var container = ...BuildContainer();
// MVC
DependencyResolver.SetResolver(
new Unity.MvcX.UnityDependencyResolver(container));
// WebAPI
GlobalConfiguration.Configuration.DependencyResolver =
new Unity.WebApiX.UnityDependencyResolver(container);
}
Once the DependencyResolvers are set the framework is able to instantiate controllers that take parameters in their constructor if the parameters can be resolved with the registered types. For example, you can create a CustomerController now that gets a CustomerService and an EmailMessenger injected:
public class CustomerController : Controller
{
private readonly ICustomerService _customerService;
private readonly IEmailMessenger _emailMessenger;
public CustomerController(
ICustomerService customerService,
IEmailMessenger emailMessenger)
{
_customerService = customerService;
_emailMessenger = emailMessenger;
}
// now you can interact with _customerService and _emailMessenger
// in your controller actions
}
The same applies to derived ApiControllers for WebAPI.
The services can take a dependency on the context instance to interact with Entity Framework, like so:
public class CustomerService // : ICustomerService
{
private readonly MyContext _myContext;
public CustomerService(MyContext myContext)
{
_myContext = myContext;
}
// now you can interact with _myContext in your service methods
}
When the MVC/WebAPI framework instantiates a controller it will inject the registered service instances and resolve their own dependencies as well, i.e. inject the registered context into the service constructor. All services you will inject into the controllers will receive the same context instance during a single request.
With this setup you usually don't need a context = new MyContext() nor a context.Dispose() as the IOC container will manage the context lifetime.
If you aren't using a repository then I assume you would have some place to write your logic/processing that your service operation would use. I would create a new instance of the Context in that logic/process class method and use its methods directly. Finally, dispose it off right after its use probably under a "using".
The processing method would eventually transform the returned/processed data into a data/message contract which the service returns to the controller.
Keep the data logic completely separate from Controller. Also keep the view model separate from data contract.
If you move ahead with this architecture, you are going to be tightly coupling the Entity Framework with either your service or your controller. The repository abstraction gives you a couple things:
1) You are able to easily swap out data access technologies in the future
2) You are able to mock out your data store, allowing you to easily unit test your data access code
You are wondering where to put your EF context. One of the benefits of using the Entity Framework is that all operations on it are enrolled into a transaction. You need to ensure that any data access code uses the same context to enjoy this benefit.
The design pattern that solves that problem is the Unit of Work pattern, which by the looks of things, you are already using. I strongly recommend continuing to use it. Otherwise, you will need to initialize your context in your controller, pass it to your service, which will need to pass it to any other service it interacts with.
Looking at the objects you have listed, it appears to be a considerate attempt to build this app with enterprise architectural best practices. While abstractions do introduce complexity, there is no doubting the benefit they provide.
I am using a custom UserDetailsService to authenticate users. This uses a PersonDao/Service object that is autowired. To autowire this object, I had to include reference to datasource, sessionfactory and annotation driven in Spring-security-context.xml. All these lines are exactly replicated in app-servlet.xml. So I was wondering if there is anyway to have theses lines in only one place and not to copy it at both the places.
Your app-servlet (Spring MVC) context is a child of the root WebApplicationContext and has access to all of the beans in the parent.
If your parent context includes spring-security-context (for example)
<import resource="spring-security-context.xml"/>
then app-servlet will have access to those beans.
See What's a smart way to organize classes in Spring 3 for component-scan? for info on how to not duplicate beans when <component-scan>ing.
i integrate a flex app in a jsf-icefaces app (in a jspx site with the ice:outputmedia-tag) and want to access the same instance of a bean from flex by remote, that jsf inject.
i already connect with blazeds to a java-bean. this bean - like all other beans - get other beans by injection of jsf, but when i access the bean by remote from flex it doesnt hold the injected beans (like localizer and accesmanager, both session scoped) and i can't connect to the jsf session (FacesContext.getCurrentInstance() is null). this is because flex create a new instance of the bean and it’s not the same current instance, that jsf inject, i think.
i can connect from flex to the database by create a new entity manager in the java bean, but that's not what i want, because it's again another entity manager...i want persist and get data over the accessmanager-bean.
i know exadel fiji and flamingo, but i couldn't work with fiji, because my jsf app include the icefaces components and then it doesn't work with richfaces which fiji needs. and flamingo work only with jboss seam and spring. is it right?
i also read about the spring-flex-integration, but the jsf application did not create with spring and i don't want to integrate spring in such a large jsf app.
yesterday i read about the FlexFactory interface. this interface i have to implement in my own Factory and set it in the service-config.xml of blazeds as a factory read this. i still implement my own factory but i only get application scoped beans over the servlet context which i get over FlexContext.getServletContext().getAttribute("Bean"); and not session scoped beans...
i hope there is a chance to connect throw flex and jsf...
thanks!
FacesContext.getCurrentInstance() is null
This will only happen when the current request is not been passed through the FacesServlet. In other words, the request URL did not match the url-pattern of the FacesServlet. It's namely the one responsible for creating the threadlocal FacesContext instance.
But you actually don't need the FacesContext here. As JSF just runs on the top of the Servlet API, you can also go low level and make use of it to grab the session scoped managed bean. JSF stores session scoped managed beans as attribues of the HttpSession with the managed bean name as key.
Thus, if you for example have a session scoped managed bean with the managed bean name myBean and you have the HttpServletRequest at your hands, then you can also access it as follows:
MyBean myBean = (MyBean) request.getSession().getAttribute("myBean");