Win a copy of Terraform in Action this week in the Cloud forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • Rob Spoor
  • Bear Bibeault
Saloon Keepers:
  • Jesse Silverman
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
Bartenders:
  • Piet Souris
  • Al Hobbs
  • salvin francis

Dependency injection

 
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am trying to find out where the actual source code is for @Inject in java / jakarta.  I have searched Google, Github etc.
I have searched @Inject,  jakarta.inject.Inject.  I just want to study what makes it work in the actual source code.
Can someone point me to the source, thanks.
 
Sheriff
Posts: 16719
278
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Is this what you're looking for? https://github.com/javax-inject/javax-inject/blob/master/src/javax/inject/Inject.java

I googled for "@Inject annotation source code" and it was the first link offered.
 
Sheriff
Posts: 22512
122
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Junilu, I don't think that's what Jim is after. Although he says he wants the source of @Inject, he also wants to know how it works in the background.

Jim, there are two parts to every JEE (now Jakarta EE) spec: the API itself, and an implementation. Each spec has been setup in such a way that anyone can basically implement it. For instance, JAX-RS is implemented by both Jersey and RESTEasy, and JPA by Hibernate and EclipseLink (and there are bound to be more implementations for both specs).

For CDI, the reference implementation is Weld, so that's worth taking a look at. I don't know if this is the actual implementation that's being used in the JEE container you're using, you'd have to check out its documentation.
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for answers, I will look over weld.  Here is what I have:



It works great.  But I would like similar but with new keyword:



I am trying to figure out how to pass a class name to a method as string or class if possible,
and return a new instance but using the "new" keyword.
 
Master Rancher
Posts: 4062
56
  • Likes 3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, I don't think that's going to be possible in Java.  Well, there's at least one way, by calling a java compiler from within the runtime execution... but that's way more complicated than what you have now.   Why does it matter whether or not the "new" keyword is used?
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@Mike Simmons I am sure you are correct, I will just use the one that works.

I just wanted to see if there was a way. Thank you so much for answering.
 
Marshal
Posts: 26915
82
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The compiler can (of course) only compile code which is present at compile time. So for code which creates a new instance of a class, the compiler can only work with a class name which is already known at compile time.

But there are reasons why one would want to create a new instance of a class whose name isn't known until run time. One of them is that @Inject annotation which you asked about, and there are lots more. And so Java includes code in its standard API which can take a String which contains the name of a class and create an instance of that class -- because people need to do that.

And so that's the way which you wanted to see if it existed. It wasn't what you originally thought, but that's the way to do it.
 
Saloon Keeper
Posts: 24595
168
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The "new" operator in Java is just a semantic shorthand for SomeClass.newInstance().

Injection is not quite as simple as it looks, though and even moreso for systems where injected objects can have constructor arguments. In addition to an annotation processor to actually do the injection, there has to be some sort of factory and you can pretty much bet that something like BeanUtils will be used to handle the necessary introspections.

Rather than dig through the JEE sources, maybe you should look at the source code for the Spring Framework. Spring has an independent bean factory which is part of a larger ecosystem that starts with annotation processors and before it's done has encompassed ORM systems, process schedulers and much more. But it's very modular, so you don't have to wade through (for example) specialized code for Hibernate JPA to understand the core system.
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I can't believe it, but after at least 75 + stackoverflow and stackexchange searches I found a way to pass a class to get a new instance (not string).



Thank you so much for everyone who replied and helped.  Looking through weld also helped.
 
Paul Clapham
Marshal
Posts: 26915
82
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Really? I mean, reflection is a fairly standard part of Java so you shouldn't have had to ask that many times. Here's a tutorial about it: https://docs.oracle.com/javase/tutorial/reflect/

Edit: Also, for those of us who never heard of it, could you explain what "weld" is? Obviously Google isn't helpful for that word.
 
Tim Holloway
Saloon Keeper
Posts: 24595
168
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:Really? I mean, reflection is a fairly standard part of Java so you shouldn't have had to ask that many times. Here's a tutorial about it: https://docs.oracle.com/javase/tutorial/reflect/

Edit: Also, for those of us who never heard of it, could you explain what "weld" is? Obviously Google isn't helpful for that word.



I believe its original name was JBoss Weld, and it was a product offering from JBoss Red Hat IBM. It is the reference implementation of JSR-299 (CDI).

JSR-299 should be implemented and available in current full-stack JEE servers, with Weld being the specific implementation for JBoss Wildfly and doubtless others, just as many of the Apache/jakarta libraries (including BeanUtils) are used to provide services for JEE implementations.

Speaking of BeanUtils, if you're looking to do heavy-duty introspection, you should become familiar with it. It simplifies and supports common introspection functions above and beyond the "brute force" services that the core JDK provides. BeanUtils provides underpinnings for injects (both Weld and Spring, I think) and for things like the JEE Unified Expression Language subsystem used by JSPs and JavaServer Faces (among others).

Note that Tomcat does NOT (unless recently changed) support CDI natively - it's not a full-stack JEE server. So to get CDI functionality you probably have to include a Weld jar in your Tomcat webapp WAR just as you have to include a JSF implementation JAR (such as mojarra) if you want to use JSF in a Tomcat webapp.
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I do use @Inject in tomee.  I was experimenting with custom DI for tomcat.  
Mostly I used as reference:  https://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html
I had figured how to pass class name, but now I understand how to avoid Class.forName.

I now can do:



and



Of course I could also just:



But like I said I wanted to just see what other ways to inject a class.  Years ago all I did was
use "new".  In tomee I actually have:



A lot of "modern" java/jakarta and spring programmers I know use Payara, Glassfish, etc.  But prior to learning
that tomcat did not support CDI I always used it.  But now I have both.  I just am used of tomcat / tomee and
I tried Glassfish once, but said no at the time.

Thanks again.  Any other DI (custom) ideas please let me know.
 
Rob Spoor
Sheriff
Posts: 22512
122
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
My suggestion: don't do it. There's a big difference between existing DI frameworks and your getInstance method - frameworks support sharing instances. If I inject a field of the same type in two different classes, the same object will get injected if that is specified to be a singleton or application scoped.
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@Rob Spoor I don't understand the sentence:

If I inject a field of the same type in two different classes, the same object will get injected if that is specified to be a singleton or application scoped.



I don't pass parameters to constructor, I pass to setter and the use getter.

Like the pagination class partial code:



Then



And usage:



Are you saying if I passed to constructor instead it wouldn't work?
 
Rob Spoor
Sheriff
Posts: 22512
122
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What I'm trying to say is probably better explained with an example.
The fields at // 1 and // 2 refer to the same instance.

If I use your getInstance method that doesn't work the same:
Both calls to getInstance result in a new instance.
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@Rob Spoor

In your example, whether I use @Inject, MyManager manager = new MyManager(); or getDeclaredConstructor().newInstance();
will all work the exact same.

Let's say MyManager is a class that does pagination. If Bob and Joe is on same application logged in:

Bob in Dallas, TX is paginating through accounting receivables through MyClass1.
Joe in Houston is paginating through accounts payable through MyClass2.

No matter the "new instance " technique used the paginator should work.

In fact new MyManager(); will always work.

I am sorry if I don't understand your reply.  getDeclaredConstructor().newInstance(); is from Oracle documentation.

https://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html

If I am wrong please explain, but remember I use getters and setters, I don't pass arguments to constructor.
Even in my OwnerBean class:



I use a setter / getter:



And if I did have a class with parameters passed to constructor, I'd have separate class to load it or use
new keyword passing the parameters in parenthesis.  Tomcat I am talking, Tomee I can use @inject.
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Also I use a static method, but not a singleton class.
 
Rob Spoor
Sheriff
Posts: 22512
122
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jim Whitaker wrote:@Rob Spoor

In your example, whether I use @Inject, MyManager manager = new MyManager(); or getDeclaredConstructor().newInstance();
will all work the exact same.


Not quite. Because class MyManager is annotated with @ApplicationScoped, the same instance is used no matter where it's injected using @Inject. That's not the case with new MyManager() or getDeclaredConstructor().newInstance(), which always create a new instance.
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@Rob Spoor so does that mean the other two methods, not @inject is better to use?

Also, wouldn't an injected class be disposed of after each request cycle. Meaning when a user goes from page 2 to page 3 all happens all over again, a new class injection takes place.

And even if using @inject, surely multiple users could still do pagination, correct?  Otherwise java would not work for web applications if just one user could use a class at a time, I am sure FedEx, Amazon, etc has many users at a time.

I am kind of new to @Inject, since all I have used in the past is Tomcat.  

I guess I am most confused on the number of instances you mentioned. Surely Enterprise programmers uses the @inject in their code in a web application.  Therefore they expect there will be many users.
 
Tim Holloway
Saloon Keeper
Posts: 24595
168
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You don't inject a Class, you inject a Class Instance.

The class instance is constructed by a factory and then injected into the target bean. The lifetime of a target bean is determined in JEE by its scope (Application, Session, View - JSF only, Request, or Page - JSP only, I think). Destroying a target bean does not itself pre-suppose the destruction of the objects (class instances) that were injected into it. They must obey their own scope rules, independent of the scope of bean(s) that they were injected into.
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@Tim Holloway. Yes of course I've meant a new instance.

But still which injection and scope is the best for a paginator witn many users online? Just using paginator as an example.

But remember I use setters / getter, not passing parameters to constructor.

 
Tim Holloway
Saloon Keeper
Posts: 24595
168
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, Your Mileage May Vary, but as it happens, I'm busy cobbling up something very like that this very day based on my previous practices.

My preferred architecture here is Java ServerFaces (JSF) at the presentation tier, a persistent services tier for working with sets of related table data, then a DAO tier to handle the CRUD and finder functions for individual tables (Java Persistence Architecture).

Each user has a session (ViewScoped) UI Model object (JSF backing bean). It presents the data that will be displayed in a View. The View has a JSF dataTable for the data rows and the Model has a corresponding DataModel object that represents the rows in the current View. A JSF DataModel contains both the Collection or Array that makes up the rows, plus cursor informaion used to render and identify rows when they're selected.

The row set wrapped by the DataModel is populated from a persistence service object that was injected into the JSF backing bean (UI Model). The persistence service object is a long-term object which in turn has the necessary DAOs injected into it.

The persistence service can provide me with a method that will retrieve rows from the underlying database via its DAOs. Whether that data consists of all possible rows, or just a slice big enough to back the currently-displayed datatable page is up to me.

Since the backing bean is View Scoped, every user has their own instance separate from all the others, but all of them have the same service instance injected into them, since the service and DAO beans are singletons. They're also stateless so it doesn't matter how many users are attaching them. So everything's nice and tidy and I know exactly where to go when something needs work.

I will note one caveat: I've never been called upon to run JSF at large scale and since it is a complex framework, I can't vouch for its practicality in such situations. But there are other frameworks which map equally well to such strategies, including ReST-based systems.
 
Paul Clapham
Marshal
Posts: 26915
82
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jim Whitaker wrote:But still which injection and scope is the best for a paginator witn many users online? Just using paginator as an example.



The question boils down to, is the paginator thread-safe? If it is then many clients can share the same paginator. Otherwise no, each user needs their own.

But you're going to ask, what does "thread-safe" mean? It means that one client can use the paginator without affecting what a second client, in a different thread running concurrently, sees in the paginator. If the first client changes the state of the paginator then the second client will see that change in state, not made by the second client, so that means it isn't thread-safe.

Now you're going to ask, what is the "state" of an object? Well, local variables are stored in the stack of each client, so they aren't part of the state of the object. Different clients have their own copies. But instance variables are stored in the heap, so both clients see the same thing when they look at an instance variable. In other words, the state of an object consists of its instance variables and all of the objects they refer to. If your object has instance variables then it likely isn't thread-safe; the only way for it to be thread-safe is if the instance variables (and all of the objects they refer to directly and indirectly) are never changed. (I'm not discussing static variables here because you shouldn't have them.)

So that's a crude introduction to thread-safeness. You should aim to only inject thread-safe objects, that way the framework only needs to create one. What that means in the context of your framework, I don't know.
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@Paul Clapham the pagination is of course request scoped.  Also Weld uses static methods.  Are you saying by getting a class instance like:



If I am paginating say accounts receivable in Dallas TX (just example), and you are paginating accounts payable in Houston TX, and I click page 3, suddenly you will see the data I am paginating?

All because getInstance is a static method?  Can you please explain.  
 
Tim Holloway
Saloon Keeper
Posts: 24595
168
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:The question boils down to, is the paginator thread-safe?



Not in my world it isn't. The persistency objects, as I said, are stateless. And each user has their own page context, so they don't  have thread conflicts.

The only multi-user consideration would be that the data retrieval mechansism be transactional so that other (perhaps external) users don't alter the rows while pages are being fetched. And by external, I don't mean just threads, I mean possibly other apps using the same database from other machines.

Also, in a web application, it is absolutely NOT permissible to retain an open database connection between user requests or users. So the only time that such an issue would arise would be if you were to make your "paginator" be a global shared object. Which is something I definitely don't recommend for several reasons. Starting with the fact that we'll assume that not all users will be on the same page at the same time. Well actually, starting with "global shared object", really.
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I just don't get the problem with static methods, to me they are the best way to return things,
even a Guice example uses static:



But if I don't use static, how then should I return the instance?
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Saw no way to edit:  I am seeing static all over yet being told not to use static.  It confuses me, as I always liked static methods for helper type classes such as pagination.  

But this is the first time I have experimented with some custom dependency injection, due to Tomcat and @Inject not working.

I have always in past just used new class(), should I just continue to use the new keyword to inject an instance?
 
Tim Holloway
Saloon Keeper
Posts: 24595
168
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think you may be having a problem with the concept of Inversion of Control (IoC), also known as "good things happen to those who wait".

IoC depends on an external framework to wire components together like TinkerToys™. To support this mechanism you need an injector and a factory/warehouse.

Having a factory means never having to say "new". The factory acts like a hashmap, linking bean names and bean instances. If you attempt to reference a bean by name and no instance exists, the factory will manufacture one. Which is why no-argument constructors are so useful. If the factory already holds a copy of the named bean (in its "warehouse") then a reference to that bean will be returned. Either way you end up with a bean reference that the injector can used to set the corresponding target bean property value.

Perhaps less commonly mentioned is that the factory is normally going to be referencing singleton objects. That is, the exact same bean reference will be returned for all requests. The bean doesn't have to do all those "singleton things" because the factory already knows that there should be one and only one. Some factories can also serve multiple bean instances, but that is comparatively rare. And incidentally in JEE you cannot inject a bean of shorter life (scope) into a bean of longer life.

The differences between singleton beans and actual static methods may seem small, but they do make a difference.
 
Paul Clapham
Marshal
Posts: 26915
82
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jim Whitaker wrote:If I am paginating say accounts receivable in Dallas TX (just example), and you are paginating accounts payable in Houston TX, and I click page 3, suddenly you will see the data I am paginating?

All because getInstance is a static method?  Can you please explain.  



It doesn't look to me like getInstance is a method of the thing you're going to inject.
 
Tim Holloway
Saloon Keeper
Posts: 24595
168
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
getInstance is a method for manually-managed singleton objects and of necessity it must be static because to invoke an instance method you must already have an instance.

The real problem is that the paginator as described here is a single instance being shared by multiple users who are in multiple states (forget thread problems, this is the sin of global sharing).

And it's why I have the page information in per-user objects and not in the database retrieval subsystem. I can share the same database services with all users because its the user who knows where in the database they are and not the retrieval subsystem.
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Okay I can rename it to getMyPager for example.  I take it from what you are saying that getInstance is a java reserved word.

But still if static methods are not to be used for getting an instance of the paginator class, then why is there this:

https://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html

Which demonstrates the use of getDeclaredConstructor which I am using.  I am not using a singleton class.
I am now confused why Oracle even bothered to have that documentation.

I can't see why I would need Weld or Guice to inject the same paginator class I am injecting with getDeclaredConstructor().newInstance();
It's injected in a servlet which uses the paginator, called via:



Then:


On jsp page:


Which is bootstrap type styled pagination links.

But I need to use something like Weld or Guice if more than one user is paginating data?
 
Tim Holloway
Saloon Keeper
Posts: 24595
168
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
No, getInstance is not a Java reserved word. Neither is newInstance, although it is the name of an instance method of class java.lang.Class.

The page you referenced is for using the Java reflection services. You don't need to/shouldn't do that because the Weld Inject mechanism is doing it automatically.

All you need is the @Inject annotation. Weld will do the rest automatically.
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@Tim Holloway but I don't use Weld.  I use the Oracle example.  Are you saying to use the paginator class for more than one person I need Weld?
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In Weld source code they also use getDeclaredConstructor.
 
Paul Clapham
Marshal
Posts: 26915
82
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I don't get where all of these questions are coming from. Are you trying to write your own IoC framework?
 
Tim Holloway
Saloon Keeper
Posts: 24595
168
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If by "Oracle example", you mean the URL you just referenced, forget you ever saw it. It's not something you should be anywhere near.

Weld is the reference implementation of the CDI mechanism for JEE and it's probably either already a part of your JEE server or it's something you manually have to supply to get CDI functionality if you're using a partial-stack server like Tomcat or jetty (and that includes Spring Boot!).

If you are running in a CDI-supportive environment, the @Inject annotation is all that's needed to glue two objects together. No user code, no arcane functions, nothing else.

The whole question of paging could take up another, and very different thread without getting into injection at all.
 
Paul Clapham
Marshal
Posts: 26915
82
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jim Whitaker wrote:I just don't get the problem with static methods, to me they are the best way to return things,
even a Guice example uses static:



But if I don't use static, how then should I return the instance?



Let's review what "static" means. This example uses a static variable, which means that all instances of the CreditCardProcessorFactory class will use the same variable. This in turn means that there can only be one instance of a CreditCardProcessor object, at least as far as this code is concerned. If you have two CreditCardProcessorFactory objects, they will both refer to that single CreditCardProcessor object.

So let's assume that the design for that example is that there should only be one CreditCardProcessor object... wait a minute, the design embedded in that code is incoherent. If somebody calls setInstance() and passes in a CreditCardProcessor instance, then that instance will be returned by all future calls to getInstance(). But if nobody ever calls setInstance() then getInstance() will return a new instance of SquareCreditCardProcessor every time. So which is it? Single instance for everybody to use, or a new instance every time somebody asks for one?

Let's fix that code so that the idea is to have a single instance for everybody to use:



This code will store a single instance of CreditCardProcessor and return that instance any time somebody asks for it. That implies that two users can be using that single instance at the same time, so it should be designed to allow for that to happen in a consistent way.

But there's another way to force a single instance to be repeatedly dispensed: just create one CreditCardProcessorFactory. That way you don't need to declare anything static inside the CreditCardProcessorFactory class: one object of that class using a CreditCardProcessor instance variable will automatically control just one CreditCardProcessor object. So:



I'm still not happy with that code -- it's possible for a thread to call setInstance(X) and then not get X back when calling getInstance() because some other thread called setInstance(Y) in between those two calls, but that's a side issue which isn't related to the "static" issue.
 
Tim Holloway
Saloon Keeper
Posts: 24595
168
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:
I'm still not happy with that code -- it's possible for a thread to call setInstance(X) and then not get X back when calling getInstance() because some other thread called setInstance(Y) in between those two calls, but that's a side issue which isn't related to the "static" issue.



Which, children, is why the synchronized keyword exists.

But this is just a variant of the old Singleton Bean pattern. Or actually a bastard mashup of Singleton and Factory. A Factory like CDI uses doesn't have a "getInstance" because it can manufacture more than one type of bean. It's more likely to have a "getBean" method where you can either indicate what kind of bean you want by classname or by a label reference to a class definition (for example, the "@Named" annotation).
 
Jim Whitaker
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Just one more question then.  If Weld and @Inject is now neccessary,
How did code such as:


Ever work before @Inject came along?  Am I not to use new just @Inject?
 
Paul Clapham
Marshal
Posts: 26915
82
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jim Whitaker wrote:Ever work before @Inject came along?  Am I not to use new just @Inject?



It's like, do you want to call a plumber or do you want to install the sink yourself? If you call a plumber then you have a professional and you shouldn't tell them how to do their job, just rely on them to do it and end up with a working sink.
 
reply
    Bookmark Topic Watch Topic
  • New Topic