iI'm playing around with the Charts and CDI add-ons for Vaadin at the moment and am trying to inject a mock data source into a Chart class. The data source is a singleton bean that has already had a reference injected into the View that will be displaying the chart but I was under the impression that this shouldn't matter as singletons are application scoped.
The EJB is injected correctly into the view but when the chart class is instantiated, the injection of the data source fails and returns a null reference. I've been using the no-interface facility up until now but even if I do use an interface for the data source, this doesn't make any difference. I'm guessing that there is either a scoping issue or I'm fundamentally misusing/misunderstanding CDI. The other possibility is that I've run into a limitation to the Vaadin CDI add-on as this methodology worked without problems in JSF2.2.
If anyone has any ideas or pointers I'd be really grateful as it's pretty frustrating. Granted this is a quick and dirty implementation but it is a prototype; refactoring to separate concerns (data provision vs building UI components) may well sort the issue but I'd like to understand what's happening here first.
EJB:
#Startup
#Singleton
public class MockDataProvider implements Serializable {
private static final long serialVersionUID = -4789949304830373309L;
private Random rand = new Random();
private Collection<Person> people = new ArrayList<Person>();
private Collection<Address> addresses = new ArrayList<Address>();
private Collection<Evnt> evnts = new ArrayList<Evnt>();
private Collection<TicketType> tickets = new ArrayList<TicketType>();
/**
* Initialize the data for the application
*/
public MockDataProvider() {
}
#PostConstruct
private void init() {
loadAddressData();
loadTicketData();
loadEventData();
loadPersonData();
}
View implementation (injection successful here):
#CDIView(DashboardView.VIEW_ID)
public class DashboardView extends AbstractMVPView implements IDashboardView {
public final static String VIEW_ID = "dashboard";
#Inject
#CDILogger
private Logger logger;
#EJB
MockDataProvider dataProvider;
#Inject
EventsPerMonthChart eventsPerMonthChart;
private Table eventsTable;
private Table peopleTable;
public DashboardView() {
}
Chart class (implemented by DashboardView - EJB injection fails so a null pointer exception is thrown by dataProvider.getEvntCollection.
#Dependent
public class EventsPerMonthChart extends Chart {
#EJB
MockDataProvider dataProvider;
public EventsPerMonthChart() {
super(ChartType.PIE);
setCaption("Events per month");
getConfiguration().setTitle("");
getConfiguration().getChart().setType(ChartType.PIE);
setWidth("100%");
setHeight("90%");
DataSeries series = new DataSeries();
ArrayList<Evnt> events = (ArrayList) dataProvider.getEvntCollection();
OK - it looks like the problem was down to ignorance on my part as I did not understand the contexts where EJB injection is permitted.
The EJB (MockDataProvider) is instantiated by the container and injected into the DashboardView class which, as it was annotated with #CDIView, is also managed by the container. Hence, everything works fine. However, the Chart object was not container managed (despite my misguided addition of #Dependent to try and get the container to "notice" it) - injection into POJOs is not permitted but appears to fail silently which only added to my confusion.
Granted, the code structure is pretty appalling (close coupling, highly dependant and no separation of concerns) and this shoddy approach to prototyping has been responsible for creating the issue. Passing the Charts object the data directly or a via reference to the EJB via a constructor call works without problems.
Good job your learn from your mistakes. At the rate I'm making them, I'm going to be a genius!
Related
I have a pretty standard MVC setup with Spring Data JPA Repositories for my DAO layer, a Service layer that handles Transactional concerns and implements business logic, and a view layer that has some lovely REST-based JSON endpoints.
My question is around wholesale adoption of Java 8 Streams into this lovely architecture: If all of my DAOs return Streams, my Services return those same Streams (but do the Transactional work), and my Views act on and process those Streams, then by the time my Views begin working on the Model objects inside my Streams, the transaction created by the Service layer will have been closed. If the underlying data store hasn't yet materialized all of my model objects (it is a Stream after all, as lazy as possible) then my Views will get errors trying to access new results outside of a transaction. Previously this wasn't a problem because I would fully materialize results into a List - but now we're in the brave new world of Streams.
So, what is the best way to handle this? Fully materialize the results inside of the Service layer as a List and hand them back? Have the View layer hand the Service layer a completion block so further processing can be done inside of a transaction?
Thanks for the help!
In thinking through this, I decided to try the completion block solution I mentioned in my question. All of my service methods now have as their final parameter a results transformer that takes the Stream of Model objects and transforms it into whatever resulting type is needed/requested by the View layer. I'm pleased to report it works like a charm and has some nice side-effects.
Here's my Service base class:
public class ReadOnlyServiceImpl<MODEL extends AbstractSyncableEntity, DAO extends AbstractSyncableDAO<MODEL>> implements ReadOnlyService<MODEL> {
#Autowired
protected DAO entityDAO;
protected <S> S resultsTransformer(Supplier<Stream<MODEL>> resultsSupplier, Function<Stream<MODEL>, S> resultsTransform) {
try (Stream<MODEL> results = resultsSupplier.get()) {
return resultsTransform.apply(results);
}
}
#Override
#Transactional(readOnly = true)
public <S> S getAll(Function<Stream<MODEL>, S> resultsTransform) {
return resultsTransformer(entityDAO::findAll, resultsTransform);
}
}
The resultsTransformer method here is a gentle reminder for subclasses to not forget about the try-with-resources pattern.
And here is an example Controller calling in to the service base class:
public abstract class AbstractReadOnlyController<MODEL extends AbstractSyncableEntity,
DTO extends AbstractSyncableDTOV2,
SERVICE extends ReadOnlyService<MODEL>>
{
#Autowired
protected SERVICE entityService;
protected Function<MODEL, DTO> modelToDTO;
protected AbstractReadOnlyController(Function<MODEL, DTO> modelToDTO) {
this.modelToDTO = modelToDTO;
}
protected List<DTO> modelStreamToDTOList(Stream<MODEL> s) {
return s.map(modelToDTO).collect(Collectors.toList());
}
// Read All
protected List<DTO> getAll(Optional<String> lastUpdate)
{
if (!lastUpdate.isPresent()) {
return entityService.getAll(this::modelStreamToDTOList);
} else {
Date since = new TimeUtility(lastUpdate.get()).getTime();
return entityService.getAllUpdatedSince(since, this::modelStreamToDTOList);
}
}
}
I think it's a pretty neat use of generics to have the Controllers dictate the return type of the Services via the Java 8 lambda's. While it's strange for me to see the Controller directly returning the result of a Service call, I do appreciate how tight and expressive this code is.
I'd say this is a net positive for attempting a wholesale switch to Java 8 Streams. Hopefully this helps someone with a similar question down the road.
I have a following problem. I have defined an interface:
#Local
public interface ProductTypeLister {
Collection<ListElement> getList();
}
Also, I have defined an implementation for this thing:
#Stateless(name = "ProductTypeLister")
#Local(ProductTypeLister.class)
public class ProductTypeListerImpl implements ProductTypeLister {
#Override
public Collection<ListElement> getList() {
// Implementation code
}
}
And now I want to use it via annotation:
public class ListProductTypeAction extends ActionHandler {
#EJB
protected ProductTypeLister lister;
#Override
public String execute(HttpServletRequest request) throws ServletException {
request.setAttribute("list", lister.getList());
return "listPage.jsp";
}
}
But I get the NullPointerException, since lister is not filled. Now, the problem is, that ActionHandler is not a derivative of HttpServlet and is not executed by the container itself. Instead, we are using FrontController patter - i.e. there is one servlet that handles all the incoming messages and creates required handlers via a simple construction. And therefore the EJB annotated fields are not filled automatically. However, I can fill this specific case in the following manner:
public ListProductTypeAction() throws NamingException {
InitialContext context = new InitialContext();
lister = (ProductTypeLister) context.lookup("<PATH>/ProductTypeLister");
}
In that case everything works fine, but this means I have to do for every handler the specified lookup with JNDI help, but all I want is to get it with annotation help. Therefore, the main servlet needs the following method:
private void fillHandler(ActionHandler handler) {
// Fill #EJB annotated fields
}
But how can I fill it? Of course, I can manually run through every field and check if it's annotated EJB and fill it using JNDI based on the interface unqualified name. But is there a way to do this using the libraries I already have? After all, Glassfish is supposed to fill those fields during the deployment phase. How can I make him do that for a non-servlet class?
J2EE tutorial
Dependency injection is the simplest way of obtaining an enterprise bean reference. Clients that run within a Java EE server-managed environment,
JavaServer Faces web applications, JAX-RS web services, other
enterprise beans, or Java EE application clients, support dependency
injection using the javax.ejb.EJB annotation.
Applications that run outside a Java EE server-managed environment,
such as Java SE applications, must perform an explicit lookup. JNDI
supports a global syntax for identifying Java EE components to
simplify this explicit lookup.
So even if your class is inside a J2EE container, but its lifecycle is not managed by container, you are out of luck, you have to do it manually.
Looking around StackOverflow, I see this answer to a similar problem - according to the Twitter4J documentation, TwitterStream#addListener takes a callback function. I have naively written my class as follows:
#Stateless
#LocalBean
public class TwitterListenerThread implements Runnable {
private TwitterStream twitterStream;
public TwitterListenerThread(){}
#EJB private TwitterDispatcher dispatcher;
#Override
public void run() {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
.setJSONStoreEnabled(true)
.setOAuthConsumerKey(Properties.getProperty("twitter_OAuthConsumerKey"))
.setOAuthConsumerSecret(Properties.getProperty("twitter_OAuthConsumerSecret"))
.setOAuthAccessToken(Properties.getProperty("twitter_OAuthAccessToken"))
.setOAuthAccessTokenSecret(Properties.getProperty("twitter_OAuthAccessTokenSecret"));
twitterStream = new TwitterStreamFactory(cb.build()).getInstance();
UserStreamListener listener = new UserStreamListener() {
#Override
public void onStatus(Status status) {
dispatcher.dispatch(status);
}
// Standard code
};
twitterStream.addListener(listener);
// Listen for all user activity
String user = Properties.getProperty("twitter-userid");
String[] users = {user};
twitterStream.user(users);
}
}
Now, on my colleague's PC this soon fails with an attempt to invoke when container is undeployed on the dispatcher.dispatch(status); line. I understand the reason as being due to the Twitter4J threading model not playing well with the JavaEE EJB model, but I cannot work out what to do based on the answer presented in the linked answer - how would I use a Message-Driven Bean to listen in to the Twitter stream?
After a little thinking, I worked out that the solution offered was to write a separate application that used just Java SE code to feed, using non-annotated code, a JMS queue with tweets, and then in my main application use a Message-Driven Bean to listen to the queue.
However, I was not satisfied with that work-around, so I searched a little more, and found Issue TFJ-285, Allow for alternative implementations of Dispatcher classes:
Now it is possible to introduce your own dispatcher implementation.
It can be Quartz based, it can be MDB based, and it can be EJB-timer based.
By default, Twitter4J still uses traditional and transient thread based dispatcher.
Implement a class implementing twtitter4j.internal.async.Dispatcher interface
put the class in the classpath
set -Dtwitter4j.async.dispatcherImpl to locate your dispatcher implementation
This is the default implementation on GitHub, so one could replace the:
private final ExecutorService executorService;
with a:
private final ManagedExecutorService executorService;
And, in theory, Bob's your uncle. If I ever get this working, I shall post the code here.
I am learning asp.net mvc3. one example I found online is to show me how to use IOC.
public class HomeController : Controller
{
private IHelloService _service;
public HomeController():this(new HelloService())
{}
public HomeController(IHelloService service)
{
_service = service;
}
}
there are two constructors in this example. I understand the second one. the first one I understand what that for, but to me, it seems like extra code, you will never need it.
can someone please explain to me whats the point to add the first constructor.
public HomeController():this(new HelloService())
{}
When the MVC Framework instantiates a controller, it uses the default (parameter-less) constructor.
By default, you are injecting a concrete IHelloService implementation. This will be used when a user navigates to the action.
Unit Tests would use the overload and pass in the mock IHelloService implementation rather than calling the default constructor.
It can be useful if you don't use a dependency injection framework that injects this for you. In this way you never have to manually inject the object, the object will handle that by itself.
The second constructor is, of course, useful to inject custom objects when unit testing.
Normally one would need to do this:
IFoo foo = new Foo();
IBar bar = new Bar(foo);
When your constructor creates a default object you can just do this:
IBar bar = new Bar();
Bar will then create a Foo and inject it into itself.
I have a doubt,.... How would you create a Singleton class in Flex...
Is there any convention like the class name should eb Singleton or it should extend any other class.
How many Singleton class can a project have?
Can anyone say the real time usage of a Singleton class?
I am planning to keep my components label texts in a Singleton class... Is it a good approach.
Can of worms asking about singletons!
There are a few different options about creating singletons mainly due to AS3 not having private constructors. Here's the pattern we use.
package com.foo.bar {
public class Blah {
private static var instance : Blah;
public function Blah( enforcer : SingletonEnforcer ) {}
public static function getInstance() : Blah {
if (!instance) {
instance = new Blah( new SingletonEnforcer() );
}
return instance;
}
...
}
}
class SingletonEnforcer{}
Note that the SingletonEnforcer class is internal so can only be used by the Blah class (effectively). No-one can directly instantiate the class, they have to go through the getInstance() function.
hope I'm not hitting dead horses here :)
(edit: ahh, I'm just repeating phils link)
Gregors singleton implementation does not protect against invoking the constructor with a null value, as in:
var b:Blah = new Blah(null);
You will still have only 1 instance, but invoking the constructor is still possible with the consequences that follows.
If you absolutely must enforce the singleton, the constructor should make sure that the enforcer parameter isn't null.
public function Blah( enforcer : SingletonEnforcer ) {
if(!enforcer){
throw new Error("whoops!");
}
}
You should also be concerned about ApplicationDomain when loading swf files. External swf files that uses the same definitions, may have multiple singleton instances (1 in each separate applicationdomain) if you do not specify that the swf file must be loaded into the existing applicationdomain.
This means that Blah.getInstance() in AAA.swf is not the same instance as Blah.getinstance() in BBB.swf, if AAA.swf loads BBB.swf without a LoaderContext instance that tells the plugin to load BBB.swf into the same ApplicationDomain as AAA.swf
First you can reference a previous question to find out how to create a singleton class. You can find more info from a Yakov Fain presentation as well.
Second question, your project can technology have as may singleton class as you see fit but it will only create 1 instance of each. For example, in the cairngorm architecture you have 3 main singletons: controller, service and model. The number of actual class can very depending on your project.
Finally, A real world solutions would be. You have 2 components that need to talk to each other but you don't want them to know the other exists. Meaning sometimes the components are there and sometimes they are not...so you need them to be loosely coupled. you can uses singletons to pass the data from one component to the other with out "talking" to them directly.
Using singletons is a good approach if you need to pass data around your application from component to component and would like to decouple them from each other.
package com.foo.bar
{
public class MySingleton
{
private static var _instance:MySingleton = new MySingleton;
private var _myName:String;
public static function get instance():MySingleton
{
return _instance;
}
public function set myName(value:String):void
{
_myName = value;
}
public function get myName():String
{
return _myName;
}
}
}
Notice the absence of a constructor here.
Hello you could check out the following of a Flex Singleton Class example on http://www.how-to-code.com/flex/flex-design-patterns/flex-singleton-class.html