HelloWorld EJB dependency injection - maven

I cannot get #EJB dependency injection to work. I use Linux and Maven as a build tool.
For the source code, IDE and app server I like to use the alternatives that makes it as simple as possible. I gave it a try with Glassfish 3.1.2.2, NetBeans 7.2 but no luck. I haven't done any configuration in Glassfish.
Here is some example source code, but any code that works will be helpful. Also any ideas about how to debug these kind of problems will be appreciated. It seems like every beginner is having them...
LinkResource.java
package se.xyz.webapp;
import javax.ejb.EJB;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import se.xyz.server.LinkService;
#Path("links/{username}")
public class LinkResource {
#EJB
LinkService service;
#GET
#Produces("text/plain")
public String link(#PathParam("username") #DefaultValue("NoName") String name ) {
return service.store(name); // Always nullpointer exception here!
}
}
LinkServiceImpl.java
package se.xyz.server;
import javax.ejb.Stateless;
#Stateless
public class LinkServiceImpl implements LinkService {
public String store(String name)
{
return "From eJB";
}
}
LinkService.java
package se.xyz.server;
import javax.ejb.Local;
#Local
public interface LinkService {
public String store(String name);
}
The webapp is showing but the variable service is always null. It's not so important to get this code to work, but just if I could get any DI to work. In a distant future I like to persist too, however I would like to do it manually instead of getting a huge working app from an architype. My goal is to understand what I'm doing... Any help would be appreciated.

The problem is that the class in which you are trying to inject is a JAX-RS resource.
JAX-RS resources are a bit of an oversight in Java EE where it concerns the alignment of managed bean types. When Java EE 6 was created it just happened to be that JAX-RS (and JSF 2) finished early, while CDI and the overarching "managed bean" concept finished late.
JAX-RS is a container managed type of bean, but unfortunately not of the official "managed bean" variety, and it thus does not support #EJB directly.
You can make it a CDI managed bean and then use #Inject instead of #EJB.

If you want to inject a reference to your LinkService EJB into the LinkResource resource, then your LinkResource must be a managed component, in other words a stateless session bean. If you add a #Stateless annotation in your LinkResource class, you should be fine.

Context and Dependency injection needs to be enabled per project. In netbeans right click your project and choose New > Other
Under categories select Contexts and Dependency injection then select beans.xml under File types.
Then click Next and then Finish.
Or you can manually create the beans.xml file in Web Pages/WEB-INF folder. Contents should be:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

Related

Odd Spring Boot #Autowired error on a repository NOT due to wrong project structure or missing annotations

I'm asking this question with a risk of having it marked as duplicate, but I honestly don't think it is, so here it goes.
I'm having trouble running a basic Spring Boot application. The error I'm getting is this:
Parameter 0 of constructor in com.example.demo.service.EventService required a bean of type 'com.example.demo.dao.EventRepository' that could not be found.
Now this seems like a pretty common error (and question on SO) that should point the developer to check the following issues:
Most commonly the project structure is wrong (or let's say 'custom') and the bean is not getting scanned because of hierarchy [Questions: this, this, this, this and probably many more]. Solution should be to place the SpringBootApplication in the top package and all the components in its sub-packages so it could scan everything properly or to custom-define the packages that need to be scanned.
The bean was not defined, i.e. there's a missing annotation of type #Service, #Repository etc. so the bean is not being created.
Another reason might be using two different ways of defining beans (as posted here). I'm using purely annotation-style defining, so I think I should be good here.
Also, this question has an answer mentioning to exclude the autoconfiguration of JPA repositories from application.properties file, but I don't have this configuration set.
There were also a couple of questions/answers mentioning issues with dependencies and pom.xml file which fixed this problem, but my pom.xml is a pretty basic file created from Spring Initializr, so again, I don't think this is the solution.
The error message also says:
Consider defining a bean of type 'com.example.demo.dao.EventRepository' in your configuration.
The 'missing bean' is this repository:
package com.example.demo.dao;
import com.example.demo.entity.Event;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface EventRepository extends JpaRepository<Event, Integer> {
}
You can see it has #Repository annotation (although I've created repositories without this annotation before and it worked fine so I don't think this is required, but I added it now just in case this was the issue), it extends JpaRepository so it should be a valid repository and it's inside com.example.demo.dao package.
The class that's autowiring this is a service:
package com.example.demo.service;
import com.example.demo.dao.EventRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class EventService {
EventRepository eventRepository;
#Autowired
public EventService(EventRepository eventRepository) {
this.eventRepository = eventRepository;
}
}
I'll also provide the main application so you can see its package is com.example.demo which is a parent package for both the service and the repository:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
I've also tried rebuilding the project and the infamous "closing and reopening" of IntelliJ, because it was known for sometimes acting stupid in my experience and this would solve it, but not this time.
Also as a side note, I've successfully created these kinds of projects before, so I'm really not sure what's the issue right now.
Am I missing something obvious here? What else can I check?
EDIT:
Here's the entity class as well (generated by an IDE tool):
package com.example.demo.entity;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Objects;
#Entity
public class Event {
private int id;
private String name;
private Timestamp dateFrom;
private Timestamp dateTo;
// getters & setters abstracted
}
Turns out it was an issue with pom.xml after all.
I've added the JPA dependency later and accidentally added the wrong one. My pom.xml had
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
instead of
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Apparently the IDE tool used for generating entities from tables was missing javax.persistence so it added that jar manually through lib folder. Everything looked fine to IntelliJ, but something was messed between dependencies.
Anyway, I changed the dependency in pom.xml and removed the extra jar added. Now everything works fine.

Plugin System in Spring Boot for modular applications

I looking for dynamically loading jar in spring boot after compiling, for example I will put jars in some folder and when spring boot is started, all jars from this folder will be injected into spring boot app. I don't know how can I do this with spring boot, and if You know can help me with this, with some example.
I need this jars to have #Service, #Controller as this will be module (plugin), with adding capabilities to my spring boot app.
Is possible to do this with spring boot, and if it is possible, please provide me with some sample code.
Thanks in advance.
UPDATE:
I found something https://www.youtube.com/watch?v=F-sw2pFdcDw https://code.google.com/p/jspf/
UPDATE 2: I can't get #Controller bean from plugin jar registered in Spring Boot
Have a look at FlexiCore, an open-source framework that brings modularity to spring boot utilizing plugins(jars) loaded at runtime See wizzdi and FlexiCore.
for example FlexiCore allows you to create a project ( compiled into a seperate jar from your main application) that contains a spring bean as follows:
#Component
#Extension
public class HelloWorldService implements ServicePlugin{
public String hello() {
return "Hello World!";
}
}
it will be automatically be loaded once placed inside the designated plugins folder, it basically allows a full support for most(all) of spring boot features , so for example you can add a RestController bean to your jar as well , FlexiCore will automatically load that bean allowing you to call the controller as if it was in your main application jar:
#RestController
#Extension
public class TestEntityController implements Plugin {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#Autowired
private TestEntityService testEntityService;
#PostMapping("/createTestEntity")
public TestEntity createTestEntity(#RequestParam(name="name", required=false, defaultValue="Stranger") String name) {
return testEntityService.createTestEntity(name);
}
#GetMapping("{id}")
public TestEntity getTestEntity(#PathVariable("id")String id) {
return testEntityService.getTestEntity(id);
}
}
Disclaimer: I am the CTO of wizzdi, the company powering FlexiCore.
One option is definitely to just use broad #ComponentScan. If you add new jar to classpath the annotated classes from that jar will get discovered via #ComponentScan, #Controllers will get mapped etc.
The XML equivalent here would be placing xml configuration files somewhere to your classpath (META-INF folder being obvious choice) and import them all using wildcard. The idea is the same. If the plugin jar file is on classpath you will get the xml file imported and the beans (controllers, ...) will get loaded.
There are drawbacks to this approach like the modules not being isolated but its definitely option for simpler applications.
You can find a sample spring boot web project here.
By dynamically loading jars I assume you want to add dependencies to your project. For this you can update pom.xml of the sample project and put your dependencies here.

#Provider AND Registration in Application(ResourceConfig) requirement for custom MessageBodyWriter/Reader?

Is there a requirement that a custom MessageBodyWriter and MessageBodyReader must not only be annotated by #Provider annotation AND also be included in the Application configuration through Application or ResourceConfig. If yes, why?
My train of thought was that, if classes are annotated with #Provider then the JAX-RS runtime by default loads such classes as it's runtime component. Declaring the same class inside the Application makes is a redundant exercise. It appears my train of thought is wrong, but I am looking for some kind of explanation on how and why this has been designed this way(ie both annotation and Application configuration).
I can understand that some form of Application configuration would be required on the Jersey Client side, but am not very confident about that either.
For instance, the JavaMarshaller class below has been annotated with #Provider
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.Provider;
#Provider
#Produces("application/example-java")
#Consumes("application/example-java")
public class JavaMarshaller implements MessageBodyReader, MessageBodyWriter {
.......
Now in the Application class is it required to do as below?
#ApplicationPath("services")
public class ShoppingApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> classes = new HashSet<Class<?>>();
public ShoppingApplication() {
classes.add(JavaMarshaller.class);
}
.........
Typically, the registration of classes dynamically is a feature of application servers. Since your'e deploying to tomcat, Jersey will likely expect that you're listing your providers and resources in your Application class.
If you were deploying to a full app server, like WildFly or GlassFish, you wouldn't need to do this.

Registering Spring beans without Component Scanning

I have MySimpleController and I need to extract this controller to a common library.
package xxx.mypackage;
#Controller
class MySimpleController{}
This library has a different package name, yyy.newpackage which is different than previous xxx.mypackage. Because of this, It is not suitable for component scanning.
Here is the question: Is there a way to register this controller without component scanning? I just want to include my jar and expecting my controller properly. I have seen some definitions in META-INF folder but could not be sure that this is the correct way.
Create configuration for whole 3rd party library
#Configuration
public class CustomConfig {
#Bean
public MySimpleController mySimpleController(){
return new MySimpleController();
}
}
and import this configuration without scanning
#Import(CustomConfig.class)
My sample is in JavaConfig, but this apply to xml configuration too.
add this controller as a bean with the new package in your applicationCOntext. By doing so, it would be the only bean loaded through the xml config whereas everything else is through your component scan.
<beans>
<bean name="myBean" class="yy.MySimpleController"/>
</beans>

JSF(MVC Framework) with Spring Dependency Injection Issue (Exception at Bean Creation)

i am using jsf2.0 as MVC framework and Spring just for Dependency Injection. i made it work but there is little problem when Spring Creating bean. Means on My JSFBean (ManagedBean) i have to use #Component Annotation of Spring otherwise i am not able to make it work. and because of that when my ManagedBean have some code in Constructor Spring is throwing Exception. It is working Perfect without Constructor CODE. Please comment if you need anything else.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myBean' defined in file [C:\Documents and Settings\KshiS\My Documents\NetBeansProjects\Sp_Js_1\build\web\WEB-INF\classes\com\ksh\excel\MyBean.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.ksh.excel.MyBean]: Constructor threw exception; nested exception is java.lang.NullPointerException
My JSF Bean code is
package com.ksh.excel;
import java.util.ArrayList;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* #author KshiS
*/
#ManagedBean
#ViewScoped
public class MyBean {
#Autowired
private Userdao userdao;
ArrayList<String> arrayList = new ArrayList<String>();
public MyBean()
{
Object object = FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("Userid");
if(object != null)
{
arrayList.add("Session Value");
}
else
{
arrayList.add("Temp Value");
}
}
public void print()
{
System.out.println(userdao.print());
}
}
How to Resolve it. ? OR Is there any possibility to Make it work without #Component Annotation on ManagedBean. ?
One More Important Question that I dont want use Spring As DI rather then i want use J2EE6 Dependency Injection. But also there is One problem That i have to use pure j2EE server like glassFish or JBOSS. Is it possible to use it in Tomcat. ? i know tomcat is not pure j2ee Server But i just want to use DI.
You need to post your full stacktrace here.
While your bean won't be injected using #AutoWired because your managed bean is not a spring managed bean (you need #ManagedProperty), that is not your primary problem.
The root cause is a failure in your bean's constructor. My guess would be that the following line is responsible for the NPE.
Object object = FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("Userid");
FacesContext.getCurrentInstance().getExternalContext().getSessionMap() will only return a non-null SessionMap if there's a valid HttpSession. Your chained method call assumes that this will always be the case, and it appears that's not true here.
After you fix that code, you can then use #ManagedProperty to inject the spring bean into your JSF bean (you don't need Spring MVC here.)
Related reading:
JSF 2 inject Spring bean/service with #ManagedProperty and no xml
#ManagedProperty in a Spring managed bean is null
For the first problem try adding an #Lazy annotation to your JSF bean. That will delay the creation of the object till it is required. That will resolve the problem with the exception on startup - but I think it will not fix the issue. When used with JSF the object created by spring will not be used.
Take a look at the example in this article to do it correctly - using a spring variable resolver.
http://www.mkyong.com/jsf2/jsf-2-0-spring-integration-example/
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"
version="2.1">
<application>
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
</faces-config>
On the second question - you can loook at TomEE. This article also has some details on using CDI in tomcat directly.

Resources