Confused about the use of #Remote in an EAR - dependency-injection

Using NetBeans, I have successfully run the shopping-cart example presented in the Java EE 6 tutorial on the Oracle website. It's an EAR with two modules: an EJB module and an application client module. I have cut short some details of the code in order to focus on the confusions I am facing. Firstly, below is the code.
The remote interface in the EJB module
package cart.ejb;
import cart.util.BookException;
import java.util.List;
import javax.ejb.Remote;
#Remote
public interface Cart {
public void initialize(String person) throws BookException;
public void initialize(
String person,
String id) throws BookException;
public void addBook(String title);
public void removeBook(String title) throws BookException;
public List<String> getContents();
public void remove();
}
The stateful session bean in the EJB module
package cart.ejb;
import cart.util.BookException;
import cart.util.IdVerifier;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Remove;
import javax.ejb.Stateful;
#Stateful
public class CartBean implements Cart {
List<String> contents;
String customerId;
String customerName;
public void initialize(String person) throws BookException {
.................
}
public void initialize(
String person,
String id) throws BookException {
.....................
}
public void addBook(String title) {
contents.add(title);
}
public void removeBook(String title) throws BookException {
.................
}
public List<String> getContents() {
return contents;
}
#Remove()
public void remove() {
contents = null;
}
}
The client in the application client module
package cart.client;
import java.util.Iterator;
import java.util.List;
import javax.ejb.EJB;
import cart.ejb.Cart;
import cart.util.BookException;
public class CartClient {
#EJB
private static Cart cart;
public CartClient(String[] args) {
}
public static void main(String[] args) {
CartClient client = new CartClient(args);
client.doTest();
}
public void doTest() {
..................
}
}
Now my confusions begin!!
Confusion-1: The tutorial says it is a remote client. But it is not! It is packaged as a module within the same EAR as the EJB module. Wouldn't #Local be more appropriate?
Confusion-2: If glassfish does consider it a remote communication between the client and the session bean, will the client's container supply a fake instance of the session bean (i.e. proxy) representing the actual instance of the session bean in the EJB container, just like in a "real" remote case? I mean, does remote mean remote, not matter what?
Confusion-3: I am thinking about creating a client in a non-EE environment and then getting it to communicate with the bean from outside that EAR, to get a taste of "real" remote. So, if I launch Eclipse and create a Java SE 7 client program by copying contents from the client in EAR, are these the changes I have to make?
Replace dependency injection
#EJB
private static Cart cart;
with JNDI
private static Cart cart = (Cart) InitialContext.lookup("java:global/cart/cart-ejb/CartBean/Cart");
and add the Cart interface's source code in the Java Standard Edition client project.
Confusion-4: I am unable to find the location of that EAR file. On NetBeans, I can see under cart there are two jar files. But, where is the EAR file? I deployed the project by directly opening it from C:\glassfish-4.1.1\docs\javaee-tutorial\examples\ejb\cart with NetBeans.

#Local would be enough yes, apparently they were lazy with the demonstration and chose to package it all in one. Regardless, your deployment unit is the scope of you #Local interface, so 2 different EARS in the same container could not access each-others #Local interfaces
Yes and no: the outside behavior will be completely identical to a real remote case (with serialization and proxying of objects), but how this is really handled behind the scenes depends on the container implementation. To my knowledge most containers will leverage the fact that even though it's #Remote it is located in the same JVM so for example they will not make an actual remote socket connection.
3.
You need the remote interfaces of your beans
Configure glassfish to allow remote calls on a specific port with specific credentials
Do a JNDI lookup against this setup

Related

Dropwizard and Guice: injecting Environment

I am currently building a Dropwizard + Guice + Jersey-based application where the database access is being handled by JDBI for the time being.
What I am trying to achieve is to have your typical enterprise architecture, where Resources access Service classes accessing a DAO class that in turn accesses the database. It would be nice to get all this wired up in a proper DI way, although I guess I can build my object graph in the run() method of the application if all else fails.
So, I'm running into this problem that has been mentioned here before: Getting a DBIFactory requires both the Environment and the Configuration, which somehow need to be available at the time when Guice does its injection magic and not at run()-time.
Being a Dropwizard and Guice noob, what I've managed to put together so far is that I need a Provider for my DAO objects, something to the tune of
public class UserDAOProvider implements Provider<UserDAO> {
#Inject
Environment environment;
#Inject
Configuration configuration;
#Override
public UserDAO get() {
final DBIFactory factory = new DBIFactory();
final (MyConfiguration) config = (MyConfiguration) configuration;
DBI jdbi = null;
try {
jdbi = factory.build(environment, config.getDataSourceFactory(),
"mysql");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return jdbi.onDemand(UserDAO.class);
}
}
Registering this as a singleton provider should let me then inject the UserDAO into my Services.
Now, how do we actually get the environment injected into the Provider? Currently I am stuck at Guice complaining about not finding a suitable constructor for the Environment, so it is trying to instantiate it and not grab it from Dropwizard itself.
It seems like this is doable; there is the dropwizard-guice package whose DropWizardEnvironmentModule is, I think, what I need. But I feel like I'm just missing some piece of the puzzle here for an understanding of how to put things together. I've not managed to find a complete working example so far...
I had the same issue as OP but using Hibernate rather than JDBI. My simple solution is applicable to JDBI, though - just switch DBIFactory for SessionFactory.
First add an injection provider for a singleton SessionFactory in your Guice module:
public class MyModule extends AbstractModule {
private SessionFactory sessionFactory;
#Override
protected void configure() {
}
#Provides
SessionFactory providesSessionFactory() {
if (sessionFactory == null) {
throw new ProvisionException("The Hibernate session factory has not yet been set. This is likely caused by forgetting to call setSessionFactory during Application.run()");
}
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
You need to set the singleton SessionFactory from your application's run() method. In your case, using JDBI, this is where you would create and configure your DBIFactory before handing it over to the Guice module:
public void run(MyConfiguration configuration, Environment environment) {
myModule.setSessionFactory(hibernateBundle.getSessionFactory());
...
}
Now SessionFactory can be injected wherever it is needed. I now use implicit binding for my DAO classes by just annotating the constructor with #Inject and injecting the SessionFactory singleton. I don't explicitly create providers for DAO classes:
#Singleton
public class WidgetDAO extends AbstractDAO<App> {
#Inject
public WidgetDAO(SessionFactory factory) {
super(factory);
}
public Optional<Widget> findById(Long id) {
return Optional.fromNullable(get(id));
}
...
}
Now I can inject my DAO singleton instances into resources:
#Path("/widgets")
#Produces(MediaType.APPLICATION_JSON)
public class WidgetsResource {
private final WidgetDAO widgetDAO;
#Inject
public WidgetsResource(WidgetDAO widgetDAO) {
this.widgetDAO = widgetDAO;
}
...
}
Note that this approach follows the Guice recommendation of injecting direct dependencies only. Don't try to inject Envrionment and Configuration just so that you can create a DBI factory - inject the prebuilt DBI factory itself.
This is how I use Guice with Dropwizard. Inside your run() method add the line
Guice.createInjector(new ConsoleModule());
You cannot inject Environ
Create the class ConsoleModule
public class ConsoleModule extends AbstractModule {
//configuration and env variable declaration
public ConsoleModule(ConsoleConfiguration consoleConfig, Environment env)
{
this.consoleConfig = consoleConfig;
this.env= env;
}
protected void configure()
{
//You should not inject Configuration and Environment in your provider since you are mixing
//dropwizard framework stuff with Guice.Neverthless you will have to bind them in the below order
bind(Configuration.class).toInstance(consoleConfig.class);
bind(Environment.class).toInstance(env.class);
bind(UserDAO.class).toProvider(UserDAOProvider.class).in(Singleton.class);
}
}
We have the same configuration (dw-jdbi-guice) and also an abstract 'base' Application class which complicates things even more.
Since a lot of things happen during run method, and many things depend on the configuration objects we ended up creating the injector in the run method. But since we need objects from bootsrap also (e.g. ObjectMapper), we ended up having a List<Module> field in the Application class. Not the prettiest solution but can handle variety of scenarios.

How to force an embedded Grizzly web application context to start

I use an embedded Grizzly web server to host RESTful web-services with Jersey. This is all working correctly.
My question is how to force the web application context to eagerly initialise when I start the server rather than waiting for the first incoming client request. This is a minor problem, but one I would like to solve.
I start the embedded server like this:
public final class TestApplication {
public TestApplication() throws Exception {
HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(
"http://0.0.0.0:8888",
new ResourceConfig()
.registerInstances(
new TestBinder(),
)
.registerClasses(
JacksonJsonProvider.class,
)
.packages(
AbstractResource.class.getPackage().getName()
),
true
);
}
}
The "TestBinder" configures the dependency injection that I need and that class looks like this:
final class TestBinder extends AbstractBinder {
#Override
protected void configure() {
bind(CatalogManager.class).to(CatalogManager.class).in(Singleton.class);
}
}
Finally, "CatalogManager" is a singleton that is used to pre-load and cache all of the static data that my application exposes via the RESTful web-services.
The essence of "CatalogManager" is this:
public final class CatalogManager {
#PostConstruct
public void initialise() {
// Load and cache a large application data-set here...
}
}
So the problem is that the dependency injection and consequently the #PostConstruct method do not run when the server starts up, instead it waits until the first application request and the first user of my application gets a long delay.

Jersey/Jersey-spring #Autowire not working anymore when introducing AspectJ and advice not executed

Has anyone managed to get Jersey Working with AspectJ (From Spring) ?
In my example I have a jersey class in java/groovy:
#Component
#Path("/resource")
class Resource{
#Autowired
ResourceAccess resourceAccess
#GET
#Produces(MediaType.APPLICATION_JSON)
public String getResource(#QueryParam("name") String name){
def res= resourceAccess.getResource(name)
return res
}
...
}
It works just fine, the resourceAccess is injected by Spring and /resource?name=test returns me the resource with the name test
BUT when I want to introduce AspectJ (AOP) in the game the resourceAccess object is not injected anymore and my Advice is not even executed.
I added in applicationContext.xml and created my aspect:
#Aspect
#Component
public class MyAspect{
static final Logger logger = LoggerFactory.getLogger(MyAspect.class);
#Before("execution(* com.test.Resource.getResource(..))")
public void logBefore(JoinPoint joinPoint) {
logger.debug("logBefore() is running!");
}
}
Remark: if I change the pointcut in the advice to target something else it is working fine again.
Is anyone able to help me on that issue?

Looking for a dropwizard example [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 3 years ago.
Improve this question
Looking for a dropwizard example I found:
https://github.com/codahale/dropwizard/tree/master/dropwizard-example
But I am interested in a more complete example with at least:
a 1:n relationship like customer - account
a html gui represenation at least with forms
full crud support for xml
2 out of three would be a start and would earn "accepted" by me.
Take a look at some of my Dropwzard projects
In particular the MultiBit Merchant projects (Admin, Store and Platform) will provide you with a wealth of demonstration code that shows how to get stuff done in Dropwizard. There is also an example of OpenID with Dropwizard that should provide a good launch point for a new application.
They are all FOSS under the MIT license.
Wolfgang,
here is an example Dropwizard application where Authentication, Configuration and database access using Hibernate are used.
The application is discussed in several tutorials:
First Steps
Authentication, Configuration and HTTPS
Connecting to a Database using Hibernate
Connecting to external REST Web-services using Jersey Client
And here is another example, where one can store bookmarks for authenticated users and access data via REST API.
Good luck.
That looks like a nice example as well: https://github.com/spinscale/dropwizard-blog-sample
I wrote an example in my Dropwizard XML Bundle project:
https://github.com/yunspace/dropwizard-xml/tree/master/dropwizard-xml-example
It's probably the closest to what you are looking for. It has:
1:N relationship between Pirates and Ships, stored in a H2 db.
Full CRUD support for XML using custom JacksonMessageBodyProvider with validation.
Adding HTML gui via Freemarker or Mustache templates should be pretty trivial and is covered in the standard docs.
A good example who want dropwizard with authentication.
Dropwizard: Authentication, Configuration and HTTPS
https://dzone.com/articles/getting-started-dropwizard-0
You can try this project from Github.
Dropwizard: CRUD operation, HTML views, Healthcheck
https://github.com/HoldInArms/dropwizard-mssql-crud-example
follow below step.
Add dependencies in pom file
<dependencies>
<dependency>
<groupId>com.yammer.dropwizard</groupId>
<artifactId>dropwizard-core</artifactId>
<version>0.6.2</version>
</dependency>
Create configuration class
import com.yammer.dropwizard.config.Configuration;
public class BlogConfiguration extends Configuration{
}
Create Service class
import com.yammer.dropwizard.Service;
import com.yammer.dropwizard.config.Bootstrap;
import com.yammer.dropwizard.config.Environment;
public class BlogService extends Service<BlogConfiguration> {
public static void main(String[] args) throws Exception {
new BlogService().run(new String[] { "server",
"C:\\LocalEnv\\Workspace\\dropwizarddemo\\configuration.yml" });
}
#Override
public void initialize(Bootstrap<BlogConfiguration> bootstrap) {
bootstrap.setName("blog");
}
#Override
public void run(BlogConfiguration configuration,
Environment environment) throws Exception {
environment.addResource(new IndexResource());
}
}
Note: put below configuration.yml file in current directory
# HTTP-specific options.
http:
# The port on which the HTTP server listens for service requests.
port: 8079
# The port on which the HTTP server listens for administrative
# requests.
adminPort: 8179
# Maximum number of threads.
maxThreads: 100
# Minimum number of thread to keep alive.
minThreads: 10
4. Write Index resources.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.yammer.metrics.annotation.Timed;
#Path("/")
public class IndexResource {
#GET
#Produces(value = MediaType.APPLICATION_JSON)
#Timed
public List<Blog> index() {
return Arrays.asList(new Blog("for Java Developers",
"http://stackoverflow.com/questions/13345693/looking-for-a-dropwizard-
example”));
}
#Path("/service")
#GET
#Produces(value = MediaType.APPLICATION_JSON)
#Timed
public List<Users> users() {
List<Users> list = new ArrayList<Users>();
list.add(new Users(25,"Sambhu","SA"));
list.add(new Users(35,"Amit","VP"));
list.add(new Users(45,"Sanket","AVP"));
return list;
}
}
Write POJO for Blog and Users like
public class Users {
Integer id;
String name;
String designation;
public Users(Integer id, String name, String desination){
this.id=id;
this.name=name;
this.designation=desination;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
#Override
public String toString() {
return "Users [id=" + id + ", name=" + name + ", designation="
+ designation + "]";
}
Run BlogService which will start the Jetty server and hit the localhost with port such as
http://localhost:8079/

Inject a stateless EJB with #Inject into CDI Weld ManagedBean (JSF 1.2 EJB Application on jboss 6 AS)

Currently I am trying to inject a stateless EJB into a CDI managed controller on Jboss 6 AS Final. The controller is managed in the context an accessible from the JSF pages. If I inject the stateless bean with #EJB it is working. If I inject the stateless EJB with #Inject I get the following Exception:
My controller:
#Named("TestController")
public class TestController {
#Inject
private TestManagerLocal myTestManager;
...
}
}
My stateless bean:
#SuppressWarnings("unchecked")
#Stateless
public class TestManagerBean implements TestManagerLocal {
#PersistenceContext
private EntityManager em;
...
}
The Interface of the Bean is annotated with #Local.
If I try to call myTestManager I get the following exception:
WELD-000079 Could not find the EJB in JNDI: class
de.crud.org$jboss$weld$bean-jboss$classloader:id="vfs:$$$usr$local$jboss$server$default$deploy$test$ear"-SessionBean-TestManagerBean_$$_WeldProxy
THX a lot.
For those not having the luxury to change an ear to a war, I've found the following workaround:
Create an EJB in the war
Inject that EJB with the EJBs from the EJB module
Add CDI producer methods
Qualify #Inject with the qualifier for those producer methods:
Code:
// This bean is defined in the WEB module
#Stateless
public class EJBFactory {
#EJB
protected UserDAO userDAO;
// ~X other EJBs injected here
#Produces #EJBBean
public UserDAO getUserDAO() {
return userDAO;
}
// ~X other producer methods here
}
Now EJBs from anywhere in the EAR can be injected with:
// This bean is also defined in the web module
#RequestScoped
public class MyBean {
#Inject #EJBBean
private UserDAO userDAO; // injection works
public void test() {
userDao.getByID(...); // works
}
}
EJBBean is a simple standard qualifier annotation. For completeness, here it is:
#Qualifier
#Retention(RUNTIME)
#Target({TYPE, METHOD, FIELD, PARAMETER})
public #interface EJBBean {
}
The problem was, that I built and deployed my application as an ear. Weld is working when I deploy my application as an war including all EJBs.
Currently there are various problems arising from the fact that WARs in EAR-Deployments don't share the same classloader. See https://issues.jboss.org/browse/JBAS-8683 for the ongoing discussion in the JBoss-AS JIRA (and vote it up :-) )
UPDATE I found this information on how to disable separate classloaders, option 1 worked for me, but be extremely careful with this. The separation of classloaders hasn't been introduced for no reason, so apparently there are new problems on the road ahead...

Resources