netbeans 7-8, inject of remote ejb - java

Hi, I have an EJB project called "service-ejb" with this:
#Stateless
#Remote(ServiceRemote.class)
public class Services implements ServiceLocal, ServiceRemote {
[...business code...]
}
the I have the local interface, in the same project:
#Local
public interface ServiceLocal { }
and the remote interface, in a class library project called "service-lib":
#Remote
public interface ServiceRemote {
public boolean checkIfOk();
}
I can deploy it without problem, alone or in a java EE application. The point is that I don't understand how to tell NetBeans that I wish to call that beans from another application. For example I have another java EE project with a war component, where inside a servlet I wrote:
#EJB
private ServiceRemote serviceTest;
but of course it will fail compiling, so I tried with:
InitialContext ic = new InitialContext();
ServiceRemote serviceTest = (ServiceRemote) ic.lookup("ServiceRemote");
with no luck... Where in NetBeans I can tell it to use the "service-lib" as a reference? I don't want it to be added as library and then deployed with the ear, I only want NetBeans to compile correctly the code.
Sorry if the question sound silly, but I've read the documentation and I don't understant what I'm missing...
--- edit ---
I'll try to be more clear. "service-ejb" reference "service-lib", so I've deployed "service-ejb" to glassfish. Correctly, I have:
glassfish_applications_directory $ find -name "service*"
./__internal/service-ejb
./__internal/service-ejb/service-ejb.jar
./service-ejb
./service-ejb/com/tecytal/components/email/beans/Service.class
./service-ejb/com/tecytal/components/email/interfaces/local/ServiceLocal.class
./service-ejb/service-lib.jar
Then I open a java EE project, let's call it "myEngine" with a war module "myEngine-war". I've tried to add to "myEngine-war" a reference to "service-lib", of course, and in this case it compile well. The point is that I can do everything, tell to netbeans NOT to package the "service-lib" with the war, but when I deploy "myEngine" I get:
glassfish_applications_directory $ find -name "service*"
./myEngine/lib/service-lib.jar
./__internal/service-ejb
./__internal/service-ejb/service-ejb.jar
./service-ejb
./service-ejb/com/tecytal/components/email/beans/Service.class
./service-ejb/com/tecytal/components/email/interfaces/local/ServiceLocal.class
./service-ejb/service-lib.jar
I DON'T want to have TWO service-lib.jar in my server, one in the service-ejb and one in myEngine, I don't understand how I can use a remote ebj in netbeans telling to him NOT TO deploy the same lib 3214899213 times :)

I recommend to add the remote service interface and all classes it references (including exceptions) in a separate jar. Then in the other 2 projects declare a dependcy to this jar.
I don't want it to be added as library and then deployed with the ear
I recommed to add only the service-lib contain the interface etc as a library and deploy it with the ear, not the whole service-ejb containing the implementation.

Related

Is it possible to have EJBs in domain1/lib using GlassFish?

I use GlassFish 4 web profile and I have the following interface and class.
#Local
public interface SomeService {
...
}
#Singleton
public class SomeServiceBean implements SomeService {
...
}
When I put interface and class in .war archive (that is in domain1/autodeplay) everything works fine. However, when I put interface and class in separate .jar archive (that is in domain1/lib) then deploying war application I get:
java.lang.RuntimeException: Cannot resolve reference Local ejb-ref name=com.temp.MyServlet/someService,Local 3.x interface =com.temp.SomeService,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session
at com.sun.enterprise.deployment.util.ComponentValidator.accept(ComponentValidator.java:374) ~[dol.jar:na]
at com.sun.enterprise.deployment.util.DefaultDOLVisitor.accept(DefaultDOLVisitor.java:78) ~[dol.jar:na]
at com.sun.enterprise.deployment.util.ComponentValidator.accept(ComponentValidator.java:123) ~[dol.jar:na]
at com.sun.enterprise.deployment.util.ApplicationValidator.accept(ApplicationValidator.java:152) ~[dol.jar:n
...
I don't use any xml descriptors. So, is it possible to have EJBs in domain1/lib and if yes, how to make EJB container find them? P.S. I tried in GF 4 full - result is the same.
EJBs cannot be added as a library to GlassFish, libraries are just added to the classpath and any annotations on them are ignored and they do not go through the EJB container. If you do want your EJBs as a seperate JAR, they can be deployed just like a WAR or EAR file.
In the Glassfish reference manual for the add-library command it says that it "adds the library to the class loader directory", while for the deploy command it says that "Applications can be...EJB modules".
Also by looking at the source code for Glassfish it can be worked out that all libraries are simply added to the Classloader either at launch (See here and here) or if in applibs then when the application is deployed (See here).

Moved EJB to library, now EJB is not found

I have an EJB X implementing interface IX; I have a web service Z deploying in WebSphere; one of its classes declares the following:
#EJB
IX ix;
When X and IX were in the same source tree as the application, this worked fine. I had it as #Singleton and #Startup, though I've sinced changed it to #Stateful.
The application has a jar it shares with another web service, and this 2nd web service can also make use of X. So I want to move X to a jar (or whatever) used by each web service.
There is a jar currently used by both web services, so I moved X, IX and another dependent class to the source tree for that jar. I compiled the jar and exported it, overwriting the jar previously used. I've opened that and verified that the three new classes are in it.
When I run the app in the server (RAD/eclipse) I get an error message:
com.ibm.ejs.container.EJBNotFoundException: EJB with interface IX not present in application Z.
As stated above, I have this declared as #EJB in a class in the application, in a place that works when IX and its supporting classes are in the same source tree.
The RAD/eclipse project for the jar file did not originally have an EJB facet, so I added that; I recompiled and etc., get the same error. I can add things to ejb-jar.xml if needed, though I thought that's what the Annotations were for. But maybe there's something the annotations don't do, or that I need to add something for, now that the bean is in a different jar.
I figure I've missed something about configuring or declaring this. Is this enough information to tell me what it is?
EJB X must be in EJB jar, not utility jar for annotations to work. Put only interface IX in utility jar, and make all other projects - EJB, WS1 and WS2 - dependent on that jar (add jar to EAR/lib for example). Pack all projects in EAR.

How do I create a non-EJB super simple web-service .war for Java in Eclipse?

I have been attempting to create a super simple web-service (non-SOAP wsdl Server) within Eclipse Java EE (Juno) using Java 1.6. I want the web-service war to be as simple as possible, as in this simple (first reply in the thread).
IOW, I want the war file to just have the class I have defined (which includes the #WebService and #WebMethod annotations) and possibly a web.xml file which can then be deployed in Eclipse Java EE to the JBoss 6.0 server I have set up.
I must be missing some simple step somewhere. Each time I have tried, I either cannot get the web-service to deploy, or Eclipse wants to auto-generate and add a huge number of useless classes to the deployment.
I have Eclipse Java EE set up and I created a File -> New-> Dynamic Web Project and call it ProjectHelloService. I then create a single class in the project under Java Resources/src in its own package, ws.simple. The class looks like this:
package ws.simple;
import javax.jws.WebMethod;
import javax.jws.WebService;
#WebService
public class HelloService
{
#WebMethod
public String sayHello(String name)
{
return "Hello, " + name;
}
}
I then start up the JBoss server and "Add" the project to JBoss. I see the "...deploy, ctxPath=/ProjectHelloService" message indicating that my project has deployed. However, when I go to the default JBoss page -> JBoss Web Services Console -> View a list of deployed services, I see "There are currently no endpoints deployed ". When I dig around and try to see what was deployed in JBoss's server/default folder, I cannot find anything in the deploy folder.
Again, I must be missing some step somewhere. For example, I don't see a .war (or even .jar) file being generated, in Eclipse nor in the JBoss deploy folder. However, I am not deeply versed in the nuances of how Eclipse works with JBoss 6.0, so I might be missing some configuration subtlety here.
Is there something simple I can do to get a super stupid simple .war file to deploy to the Eclipse contained JBoss 6.0 so that I can see my web-service? And since JBoss is able to do all the auto-file generation automatically from the annotations in the .war file, I don't want Eclipse to do all the extra file stub generation crap. That's CORBA old school style, and makes for a much less manageable project (at least for the area I am working in right now).
And I don't suppose there is some way that I can have the above in Eclipse while having the convenience of the Netbeans approach to creating and managing Java web-services. If there is, I sure would like to know what it is.
Thank you for any guidance and/or assistance you can over here.

Spring Dependency Injection and Plugin Jar

I have web application running with a default impl of a backend service. One should be able to implement the interface and drop the jar into the plugins folder (which is not in the apps classpath). Once the server is restarted, the idea is to load the new jar into the classloader, and have it take part in dependency injection. I am using Spring DI using #Autowired. The new plugin service impl will have #Primary annotation. So given two impls of the interface, the primary should be loaded.
I got the jar loaded into the classloader and can invoke the impl manually. But I haven't been able to get to to participate in the Dependency Injection, and have it replace the default impl.
Here's a simplified example:
#Controller
public class MyController {
#Autowired
Service service;
}
//default.jar
#Service
DefaultService implements Service {
public void print() {
System.out.println("printing DefaultService.print()");
}
}
//plugin.jar not in classpath yet
#Service
#Primary
MyNewService implements Service {
public void print() {
System.out.println("printing MyNewService.print()");
}
}
//For lack of better place, I loaded the plugin jar from the ContextListener
public class PluginContextLoaderListener extends org.springframework.web.context.ContextLoaderListener {
#Override
protected void customizeContext(ServletContext servletContext,
ConfigurableWebApplicationContext wac) {
System.out.println("Init Plugin");
PluginManager pluginManager = PluginManagerFactory.createPluginManager("plugins");
pluginManager.init();
//Prints the MyNewService.print() method
Service service = (Service) pluginManager.getService("service");
service.print();
}
}
<listener>
<listener-class>com.plugin.PluginContextLoaderListener</listener-class>
</listener>
Even after I have loaded the jar into the classloader, DefaultService is still being injected as service. Any idea how I get the plugin jar to participate into the spring's DI lifecycle?
Edited:
To put it simply, I have a war file that has a few plugin jars in a plugins directory inside the war. Based on a value from a configuration file that the app looks at, when the app is started, I want to load that particular plugin jar and run the application with it. That way, I can distribute the war to anyone, and they can choose which plugin to run based on a config value without having to to repackage everything. This is the problem I am trying to solve.
It seems like all You need is to create the Spring ApplicationContext properly. I think it's possible without classpath mingling. What matters most are the locations of the Spring configuration files within the classpath. So put all Your plugin jar's into WEB-INF/lib and read on.
Let's start with the core module. We'll make it to create it's ApplicationContext from files located at classpath*:META-INF/spring/*-corecontext.xml.
Now we'll make all plugins to have their config files elsewhere. I.e. 'myplugin1' will have its config location like this: classpath*:META-INF/spring/*-myplugin1context.xml. And anotherplugin will have the configs at classpath*:META-INF/spring/*-anotherplugincontext.xml.
What You see is a convension. You can also use subdirectiries if You like:
core: classpath*:META-INF/spring/core/*.xml
myplugin1: classpath*:META-INF/spring/myplugin1/*.xml
anotherplugin: classpath*:META-INF/spring/anotherplugin/*.xml
What matters is that the locations have to be disjoint.
All that remains is to pass the right locations to the ApplicationContext creator. For web applications the right place for this would be to extend the ContextLoaderListener and override the method customizeContext(ServletContext, ConfigurableWebApplicationContext).
All that remains is to read Your config file (its location can be passed as servlet init parameter). Than You need to construct the list of config locations:
String locationPrefix = "classpath*:META-INF/spring/";
String locationSiffix = "/*.xml";
List<String> configLocations = new ArrayList<String>();
configLocations.add(locationPrefix + "core" + locationSiffix);
List<String> pluginsTurnedOn = getPluginsTurnedOnFromConfiguration();
for (String pluginName : pluginsTurnedOn) {
configLocations.add(locationPrefix + pluginName + locationSiffix);
}
applicationContext.setConfigLocations(configLocations.toArray(new String[configLocations.size()]));
This way You can easily manage what is and what is not loaded into Spring ApplicationContext.
Update:
To make it work there's one more hidden assumption I made that I'm about to explain now. The base package of the core module and each plugin should also be disjoint. That is i.e.:
com.mycompany.myapp.core
com.mycompany.myapp.myplugin1
com.mycompany.myapp.anotherplugin
This way each module can use <context:componet-scan /> (on equivalent in JavaConfig) easily to add classpath scanning for it's own classes only. The core module should not contain any package scanning of any plugin packages. The plugins should extend configuration of ApplicationContext to add their own packages to classpath scanning.
If you restart the server, I see no reason why you can't just add the JAR to the WEB-INF/lib and have it in the CLASSPATH. All the complication of a custom class loader and context listener goes away, because you treat it just like any other class under Spring's control.
If you do it this way because you don't want to open or modify a WAR, why not put it in the server /lib directory? Let the server class loader pick it up. This makes all plugin classes available to all deployed apps.
The answer depends on how important the separate /plugin directory is. If it's key to the solution, and you can't add the JAR to the server's /lib directory, then that's that. I've got nothing. But I think it'd be worthwhile to at least revisit the solution you have to make sure that it's the only way to accomplish what you want.

How to extend/customize a WAR with another project

We have the following scenario with our project:
A core web application packaged as a
war file (call it Core project).
The need to "customize" or "extend" the core app
per customer (call it Customer project). This mostly includes
new bean definitions (we're using
Spring), ie. replacing service
implementations in the core.war with
customer-specific implementations.
We want to develop the Core and Customer projects independently
When the Customer project is developed, we need to be able to run/debug it in Eclipse (on Tomcat) with the Core project as a dependency
When the Customer project is built, the resulting war file "includes" the core and customer projects. So this .war is the customer-specific version of the application
I'm looking for suggestions as to the best way to do this in terms of tooling and project configuration.
We're using Ant currently, but would like to avoid getting buried in more ant. Has anyone done this with Maven?
I've seen a lot of posts on how to build a web application that depends on a java application, but nothing on a web application depending on another web app.
Thanks!
Sounds like Maven WAR overlay does what you want.
In Eclipse there is a "native" WTP way to do this. It mainly using linked folders and a little hack in .settings/org.eclipse.wst.common.component file. You can read the article about it at http://www.informit.com/articles/article.aspx?p=759232&seqNum=3 the chapter called "Dividing a Web Module into Multiple Projects". The problem with this is that the linked folder must be relative to some path variable can be defined in Window/Preferences/General/Workspace/Linked Resources tab. Otherwise the linked folder definition (can be found in .project file in project root) will contain workstation specific path. The path variable practicly should be the workspace root. This solution works great with WTP, deploy and everything else works like it should.
The second solution is to use ant for it. Forget it. You will deeply regret it.
The third solution is to use maven for it. You can forget the comfort of WTP publishing if you dont do some tricks. Use war overlays like others suggested. Be sure to install both m2eclipse, m2eclipse extras. There is an extension plugin released recently, that can help you. Described at this blog. I did not try it, but looks ok. Anyway Maven have nothing to do with linked folders, so I think even the first solution and this maven overlay can live together if necessary.
As for headless builds you can use HeadlessEclipse for the first solution. It is dead (by me) now, but still works :). If you use the maven overlay + eclipse stuff, headless builds are covered by maven.
This is little bit more involved but at a high-level we do it as below. We have the core platform ui divided to multiple war modules based on the features (login-ui,catalog-mgmt-ui etc). Each of these core modules are customizable by the customer facing team.
We merge all of these modules during build time into 1 single war module. The merge rules are based on maven's assembly plugin.
You usually start from the Java source code. WARs don't include the Java source code, just the compiled classes under WEB-INF/classes or JARs under WEB-INF/libs.
What I would do is use Maven and start a brand new empty webapp project with it: http://maven.apache.org/guides/mini/guide-webapp.html
After you have the new empty project structure, copy the Java source code to it (src/main/java) and fill out the dependencies list in pom.xml.
Once you've done all this you can use mvn clean package to create a standard WAR file that you can deploy to Tomcat.
You might want to look into designing your core app with pluggable features based on interfaces.
For example say your core app has some concept of a User object and needs to provide support for common user based tasks. Create a UserStore interface;
public interface UserStore
{
public User validateUser(String username, String password) throws InvalidUserException;
public User getUser(String username);
public void addUser(User user);
public void deleteUser(User user);
public void updateUser(User user);
public List<User> listUsers();
}
You can then code your core app (logon logic, registration logic etc) against this interface. You might want to provide a default implementation of this interface in your core app, such as a DatabaseUserStore which would effectively be a DAO.
You then define the UserStore as a Spring bean and inject it where needed;
<bean id="userStore" class="com.mycorp.auth.DatabaseUserStore">
<constructor-arg ref="usersDataSource"/>
</bean>
This allows you to customise or extend the core app depending on specific customer's needs. If a customer wants to integrate the core app with their Active Directory server you write a LDAPUserStore class that implements your UserStore interface using LDAP. Configure it as a Spring bean and package the custom class as a dependant jar.
What you are left with is a core app which everyone uses, and a set of customer specific extensions that you can provide and sell seperately; heck, you can even have the customer write their own extensions.

Categories