This issue is very common. I have read some articles but can't find the problem. I want to create a simple HelloWorld program in EJB 3.0, eclipse luna, jboss 7.1.1 Final.
Here is my bean:
package com.tcs.HelloWorldPack;
import javax.ejb.Stateless;
/**
* Session Bean implementation class HelloWorld
*/
#Stateless(mappedName="HelloWorldBean")
public class HelloWorld implements HelloWorldRemote {
/**
* Default constructor.
*/
public HelloWorld() {
// TODO Auto-generated constructor stub
}
#Override
public void displayMsg() {
// TODO Auto-generated method stub
System.out.println("Hello World!!");
}
}
Here is my remote interface:
package com.tcs.HelloWorldPack;
import javax.ejb.Local;
//import javax.ejb.Remote;
import javax.ejb.Remote;
#Remote
public interface HelloWorldRemote {
void displayMsg();
}
Here is my client which is running in the same machine:
package com.tcs.HelloWorldClient;
import java.util.Hashtable;
import java.util.Properties;
import com.tcs.HelloWorldPack.*;
import javax.ejb.EJB;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class HelloWorldClient {
public static void main(String[] args) throws NamingException {
final Hashtable jndiProperties = new Hashtable();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
jndiProperties.put(javax.naming.Context.SECURITY_PRINCIPAL, "myUser");
jndiProperties.put(javax.naming.Context.SECURITY_CREDENTIALS, "myPass");
// jndiProperties.put(javax.naming.Context.PROVIDER_URL, "jnp://localhost:1099");
// jndiProperties.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
jndiProperties.put("jboss.naming.client.ejb.context", true);
final Context context = new InitialContext(jndiProperties);
final String appName= "HeloWorldEJBEAR";
final String moduleName= "";
final String distinctName ="";
final String beanName = "HeloWorld";
final String viewClassName = "com.tcs.HelloWorldPack.HelloWorldRemote";
HelloWorldRemote hello = (HelloWorldRemote) context.lookup("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName);
hello.displayMsg();
}
}
This is my jboss-ejb-client.properties file:
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port = 4447
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.default.username=myUser
remote.connection.default.password=myPass
I have put the properties file in the classpath also.But this is happening when I am trying to run it:
Exception in thread "main" java.lang.IllegalStateException: No EJB receiver available for handling [appName:HeloWorldEJBEAR,modulename:,distinctname:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext#413ded77
at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:584)
at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:119)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:181)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:136)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:121)
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:104)
at com.sun.proxy.$Proxy0.displayMsg(Unknown Source)
at com.tcs.HelloWorldClient.HelloWorldClient.main(HelloWorldClient.java:71)
Jan 08, 2015 3:34:44 PM org.jboss.ejb.client.remoting.ChannelAssociation$ResponseReceiver handleEnd
INFO: Channel Channel ID de8d2aa6 (outbound) of Remoting connection 44477156 to localhost/127.0.0.1:4447 can no longer process messages
I have also uploaded my directory structure. I am new to the EJB concept. Please help me to find where is the problem. Thanks in advance.
Your module name is an empty String, but the module name can't be an empty string in the JNDI name.
Look here
you have to set the name of your ejb module .jar, without the .jar suffix.
final String moduleName = "HeloWorldEJB";
Then it should work.
As you are out to do a simple example lets keeep it simple [KISS],Most of your code is correct the catch is the client, I have simplified the client code, added my comments in client hope its self explanatory.And.... Added on EJB #javax.ejb.Stateless(name = "HelloWorldEJB") //This is portable No Vendor locked in. Alternative is mappedName [removed from your code #Stateless(mappedName="HelloWorldBean") p]which i believe is more weblogic and glassfish centric.
Ensure you have client.jar in your class path. this is the only jar you will have to add aftr you have created the EJB project in intelija or eclipse or any other ide.
I have deployed the EJB's in glassfish container once ear deployed successfully, run the client.
Apart from the below code you wont need any other configurations. This code is portable and should work on most containers however Surprises is fun do run as is and let me know .....
Once the below works for you you can add other jndi properties as per your project requirement and move on.....
==============================
The Remote
package com.au.ejbs;
import javax.ejb.Remote;
#Remote
public interface HelloWorldI {
String displayMessage(String message);
}
=================================
2. The Impl
package com.au.ejbs;
import javax.ejb.Remote;
#javax.ejb.Stateless(name = "HelloWorldEJB")
public class HelloWorld implements HelloWorldI {
#Override
public String displayMessage(String message) {
// TODO Auto-generated method stub
return "Returning from Remote" + message;
}
}
======================================
3. The client
package com.au.clients;
import com.au.ejbs.HelloWorldI;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class HelloWorldT {
public static void main(String[] args) throws NamingException {
Context context = new InitialContext();
HelloWorldI helloWorldI = (HelloWorldI)context.lookup("java:global/ejb3_2_ear_exploded/ejb/HelloWorldEJB");
//portable syntax java:global/[ ear name]/[module name normally the jar name in my case ejb.jar within the ear, ejb3_2_ear_exploded]/name in ....javax.ejb.Stateless(name = "HelloWorldEJB")/
System.out.println( "output " + helloWorldI.displayMessage("From Client with luv...."));
}
}
===================
4. output
output Returning from RemoteFrom Client with luv....
Related
I am learning about EJB and I would like to get the following code working but so far no success.
Here's my EJB project code:
#Stateless
public class CalcBean implements ICalcRemote {
private static final long serialVersionUID = 5571798968598315142L;
#Override
public int add(int a, int b) {
return a + b;
}
}
package com.ejb.test.pckg;
import javax.ejb.Remote;
#Remote
public interface ICalcRemote extends ICalculator {
}
package com.ejb.test.pckg;
import java.io.Serializable;
public interface ICalculator extends Serializable {
public int add(int a, int b);
}
I run glassfish-4.1.1 in Eclipse Neon.
When I deploy the EJB project, I can see the following in the log:
2017-02-24T21:18:09.036-0400|Info: Portable JNDI names for EJB CalcBean: [java:global/EJBDemo/CalcBean, java:global/EJBDemo/CalcBean!com.ejb.test.pckg.ICalcRemote]
2017-02-24T21:18:09.036-0400|Info: Glassfish-specific (Non-portable) JNDI names for EJB CalcBean: [com.ejb.test.pckg.ICalcRemote#com.ejb.test.pckg.ICalcRemote, com.ejb.test.pckg.ICalcRemote]
This is my client code:
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import com.ejb.test.pckg.ICalcRemote;
public class Main {
public static void main(String[] args) {
try {
Properties props = new Properties();
props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
//
props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
Context ctx = new InitialContext();
ICalcRemote calc = (ICalcRemote) ctx.lookup("java:global/EJBDemo/CalcBean!com.ejb.test.pckg.ICalcRemote");
System.out.println(calc.add(5, 7));
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* (non-Java-doc)
*
* #see java.lang.Object#Object()
*/
public Main() {
super();
}
}
But I am having no luck. Any suggestions how to get this working?
Thank you!
EDIT:
This is my main (client) which includes info from the EJBDemo deployment log:
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import com.ejb.test.pckg.ICalcRemote;
public class Main {
public static void main(String[] args) {
try {
Properties props = new Properties();
props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
//
// props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
// props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
/*
* THIS IS from Glassfish log of EJBDemo deployment
*
* 2017-02-25T20:41:47.100-0400|Info: Portable JNDI names for EJB CalcBean: [java:global/EJBDemo/CalcBean,
* java:global/EJBDemo/CalcBean!com.ejb.test.pckg.ICalcRemote] 2017-02-25T20:41:47.100-0400|Info: Glassfish-specific (Non-portable) JNDI names for EJB CalcBean:
* [com.ejb.test.pckg.ICalcRemote#com.ejb.test.pckg.ICalcRemote, com.ejb.test.pckg.ICalcRemote]
*
*
*/
Context ctx = new InitialContext();
ICalcRemote calc = (ICalcRemote) ctx.lookup("java:global/EJBDemo/CalcBean!com.ejb.test.pckg.ICalcRemote");
System.out.println(calc.add(5, 7));
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* (non-Java-doc)
*
* #see java.lang.Object#Object()
*/
public Main() {
super();
}
}
I finally got things working! Since it's been quite a process despite reading many posts related to this issue. Here are the details of my configuration. Hopefully, this will be useful to somebody.
OS: win 10
IDE: Eclipse Neon
App server: Glassfish 4.1.1
JDK: 1.8.0_111
I need to mention this article which eventually led me to the answer:
http://mavicode.com/2014/08/a-standalone-client-for-ejbs-running-on-glassfish-4/
So, thanks and kudos.
First, create the EJB Demo project:
package com.ejb.test.pckg;
import java.io.Serializable;
public interface ICalculator extends Serializable {
public int add(int a, int b);
}
package com.ejb.test.pckg;
import javax.ejb.Remote;
#Remote
public interface ICalcRemote extends ICalculator {
}
package com.ejb.test.pckg;
import javax.ejb.Stateless;
// #Stateless(mappedName = "chester")
#Stateless
public class CalcBean implements ICalcRemote {
private static final long serialVersionUID = 5571798968598315142L;
#Override
public int add(int a, int b) {
return a + b;
}
}
Deploy it on the server (run as > run on the server) > check the log to see the JDNI info. It should look like something like this:
2017-02-25T20:41:47.100-0400|Info: Portable JNDI names for EJB
CalcBean: [java:global/EJBDemo/CalcBean,
java:global/EJBDemo/CalcBean!com.ejb.test.pckg.ICalcRemote]
2017-02-25T20:41:47.100-0400|Info: Glassfish-specific (Non-portable)
JNDI names for EJB CalcBean:
[com.ejb.test.pckg.ICalcRemote#com.ejb.test.pckg.ICalcRemote,
com.ejb.test.pckg.ICalcRemote]
After that, create Application Client Project. Main.java will be created automatically. This is my main:
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import com.ejb.test.pckg.ICalcRemote;
public class Main {
public static void main(String[] args) {
try {
Properties props = new Properties();
props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
Context ctx = new InitialContext();
ICalcRemote calc = (ICalcRemote) ctx.lookup("java:global/EJBDemo/CalcBean!com.ejb.test.pckg.ICalcRemote");
System.out.println(calc.add(5, 43));
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* (non-Java-doc)
*
* #see java.lang.Object#Object()
*/
public Main() {
super();
}
}
At this point, my project looks like this:
And here comes the key part. Add a new external library from the Glassfish lib directory. !!! IMPORTANT: Don't just copy and paste to the path! The .jar apparently uses/references other classes in other GF jars. So just add it to the build path as an external jar instead of copy/paste.
You should be set now. Run the Main as a Java application.
This is what I get.
I'm creating a simple client-server Java EE application with EJB, using IntelliJ IDEA 2016 and WildFly 10.
I've created a new Java EE Project EJB_final_test and added two modules:
Java module EJB_test_client
EJB module EJB_test_server
Then I set artifact as Java EE Application Archive which creates an EJBTestEAR.ear file for EJB_test_server module.
I've deployed this EAR file on WildFly server. Server runs well and it successfully deploys the artifact on start up.
Here is my jboss-ejb-client.properties file:
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port=8180
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT=false
Here is my code for only class ClientTest in EJB_test_client module:
package test;
import facade.TestFacadeBeanRemote;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.util.Properties;
public class ClientTest {
public static void main(String[] args) throws Exception {
Properties jndiProperties = new Properties();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
Context ctx = new InitialContext(jndiProperties);
TestFacadeBeanRemote remote = (TestFacadeBeanRemote) ctx.lookup("ejb:EJBTestEAR/EJB_test_server//TestFacadeBean!facade.TestFacadeBeanRemote");
System.out.println(remote.tstPlus("Hello", "World"));
}
}
Here is code for classes TextExecutiveBean, TestFacadeBean, TestFacadeBeanRemote which are all in module EJB_test_server:
TestExecutiveBean class:
package executive;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
#Stateless
#LocalBean
public class TestExecutiveBean {
public String doPlusOperation(String str1, String str2) {
return str1 + " " + str2 + " " + str1;
}
}
TestFacadeBean class:
package facade;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import executive.TestExecutiveBean;
#Stateless
public class TestFacadeBean implements TestFacadeBeanRemote {
#EJB
private TestExecutiveBean test2;
public String tstPlus(String str1, String str2) {
return test2.doPlusOperation(str1, str2);
}
}
TestFacadeBeanRemote interface:
package facade;
import javax.ejb.Remote;
#Remote
public interface TestFacadeBeanRemote {
public String tstPlus(String str1, String str2);
}
When I'm trying to run ClientTest main method, which tries to communicate with server for finding tstPlus() method in EJBTestEAR, I'm getting the following exception:
Exception in thread "main" java.lang.IllegalStateException:
EJBCLIENT000025: No EJB receiver available for handling
[appName:EJBTestEAR, moduleName:EJB_test_server, distinctName:]
combination for invocation context
org.jboss.ejb.client.EJBClientInvocationContext#184f6be2 at
org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:798)
at
org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:128)
at
org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186)
at
org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:255)
at
org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:200)
at
org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183)
at
org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146)
at com.sun.proxy.$Proxy0.tstPlus(Unknown Source) at
test.ClientTest.main(ClientTest.java:20) at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) at
com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Please, how can I fix this error? Am I doing something wrong? Is configuration of my artifact which I deploy on the server right?
I am trying to deploy a webservice on my localhost, but it doesn't seem to produce the "Endpoint".
I don't know how I messed it up :(
I am using apache cxf 2.7.1 and glassfish 3.1. I even attempted to add ear libraries.
Here is my build path:
and my project explorer looks like this:
I have annotations on both my webservice and webservice interface, as shown below:
Code for webservice interface (I removed the other some parts to make the code shorter)
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import no.solarsoft.venus2.webservice.exception.WebServiceException;
import no.solarsoft.venus2.webservice.queryoptions.ParticipantQuery;
import no.solarsoft.venus2.webservice.queryoptions.ParticipantQueryParameterKey;
import no.solarsoft.venus2.webservice.queryoptions.QueryParameter;
#WebService()
public interface WebServiceVenus2Interface {
/**
* FETCHING DATA FROM DATABASE
*
*/
#WebMethod
public void Foo(ParticipantQueryParameterKey pqpk);
#WebMethod
public String test();
#WebMethod
public String sayHello(String string) throws WebServiceException;
The code for my web service:
import javax.annotation.Resource;
import javax.jws.WebParam;
import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
import no.solarsoft.venus2.datamanager.CRUDOperation;
import no.solarsoft.venus2.datamanager.DataManager;
import no.solarsoft.venus2.entities.GradeScale;
import no.solarsoft.venus2.enums.ImageType;
import no.solarsoft.venus2.exception.DataAccessException;
import no.solarsoft.venus2.exception.InstanceNotFoundException;
import no.solarsoft.venus2.service.EmailService;
import no.solarsoft.venus2.webservice.exception.ParameterValidationException;
import no.solarsoft.venus2.webservice.exception.WebServiceException;
import no.solarsoft.venus2.webservice.exception.WebServiceFaultBean;
import no.solarsoft.venus2.webservice.queryoptions.ParticipantQuery;
import no.solarsoft.venus2.webservice.queryoptions.ParticipantQueryParameterKey;
import no.solarsoft.venus2.webservice.queryoptions.QueryParameter;
// #Stateless()
#javax.jws.WebService(endpointInterface = "no.solarsoft.venus2.webservice.WebServiceVenus2Interface", serviceName = "WebServiceVenus2Service")
public class WebServiceVenus2 implements WebServiceVenus2Interface {
private DataManager dataManager = DataManager.getInstance();
private static final Logger log = Logger.getAnonymousLogger();
#Resource
WebServiceContext wsContext;
#Override
public void Foo(ParticipantQueryParameterKey pqpk) {}
private void logEntered(String login) {
log.info(MessageFormat.format("{0}: ''{1}'' entered web service method ''{2}()''",
WebServiceVenus2.class.getSimpleName(), login, getMethodName()));
}
private String getClientIp() {
MessageContext mc = wsContext.getMessageContext();
HttpServletRequest req = (HttpServletRequest) mc.get(MessageContext.SERVLET_REQUEST);
return req.getRemoteAddr();
}
/**
* Get the method name for a depth in call stack. <br />
* Utility function
*
* #param depth
* depth in the call stack (0 means current method, 1 means call method, ...)
* #return method name
*/
public static String getMethodName() {
final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
return ste[3].getMethodName(); // Thank you Tom Tresansky
}
/**
* FETCHING DATA FROM DATABASE
*/
#Override
public String test() {
String ip = getClientIp();
logEntered(ip);
return "WebService test succeded! Client IP: " + ip;
}
#Override
public String sayHello(String string) throws WebServiceException {
logEntered(null);
if (string == null || string.isEmpty()) {
log.severe("Throwing excetion...");
throw new WebServiceException("String can not be empty or NULL!", new WebServiceFaultBean());
}
log.exiting(WebServiceVenus2.class.getName(), WebServiceVenus2.getMethodName());
return "Hello " + string + "!";
}
and here is my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app
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-app_3_0.xsd"
version="3.0">
</web-app>
I hope someone can help me. Thanks
I loaded this code nearly verbatim to a dynamic web module in eclipse and deployed to Glassfish4. When deployed (using eclipse "add to server") the WSDL is available at http://localhost:8181/Venus2WebService/WebServiceVenus2Service?wsdl
and the web service endpoint is http://localhost:8181/Venus2WebService/WebServiceVenus2Service
The only jars I included from CXF (not shown in your post) are, from reading WHICH_JARS readme within CXF binary distribution lib dir:
asm-3.3.1.jar
commons-logging-1.1.1.jar
cxf-2.7.17.jar
geronimo-javamail_1.4_spec-1.7.1.jar
geronimo-jaxws_2.2_spec-1.1.jar
jaxb-api-2.2.6.jar
jaxb-impl-2.2.6.jar
neethi-3.0.3.jar
stax2-api-3.1.4.jar
wsdl4j-1.6.3.jar
xmlschema-core-2.1.0.jar
I got the endpoint URL from watching the eclipse console for the server:
2015-09-09T21:45:40.683-0400|Info: Webservice Endpoint deployed WebServiceVenus2
listening at address at http://oc-mbp01.local:8181/Venus2WebService/WebServiceVenus2Service.
Classpath (all in WEB-INF/lib for me):
I am developing OSGi Mongodb bundle I have also added the following dependencies
com.mongodb
org.apache.felix.fileinstal
org.amdatu.mongo
org.apache.felix.configadmin
and all the dependency managers but in gogo console I get the following error message
org.amdatu.mongo
org.osgi.service.cm.ManagedServiceFactory(service.pid=org.amdatu.mongo) registered
org.osgi.service.log.LogService service optional unavailable
[11] agenda.mongodb.mongo_gfs
agenda.mongo.inter.AgendaMongo() unregistered
org.amdatu.mongo.MongoDBService service required unavailable
the main problem is MongoDBService is not available I must require this service for solving this problem I have read the book according to them
From a development perspective, everything seems fine, but when you
run the appliā cation, it will complain that the MongoDBService is
unavailable. You can figure this out with the dmcommand in the shell.
We did however set up MongoDB on our system and deployed the necessary
dependencies in our runtime. Still, the MongoDBService was unable to
start. How come? This is because the MongoDBService needs some
mandatory configuration in order to know to what database to connect
to. The Amdatu MongoDB Serviceuses the Managed Service Factory pattern
(see Chapter 4), and in order to bootstrap it, we need to supply a
configuration file. In order to supply the configuration file, we need
to create a new folder in our agendaproject. Create a new folder
called load. This is the default name that the runtime will look for
in order to spot configuration files. Next, add an empty text file and
call it something like org.amdatu.mongo-demo.xml. The configuration
file needs at least the following information: dbName=demo
I have also apply this but its still unavailable.
This is interface:
package agenda.mongo.inter;
import java.io.InputStream;
public interface AgendaMongo {
public String store_in_db();
public InputStream getData(Object file_id);
}
This is the implementation for Mongodb:
package agenda.mongodb.gridfs;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import org.amdatu.mongo.MongoDBService;
import org.bson.types.ObjectId;
import agenda.mongo.inter.AgendaMongo;
import com.mongodb.DB;
import com.mongodb.DBCursor;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSInputFile;
public class Gridfs_Mongodb implements AgendaMongo{
GridFSInputFile gfsinput=null;
private volatile MongoDBService mongoservice;
public String store_in_db() {
/*try {
GridFS gfsHandler;
gfsHandler = new GridFS(mongoservice.getDB(), "rest_data");// database
File uri = new File("f:\\get1.jpg"); // name and
gfsinput = gfsHandler.createFile(uri);
gfsinput.saveChunks(1000);
gfsinput.setFilename("new file");
gfsinput.save();
//System.out.println(gfsinput.getId());
//save_filepath("file",gfsinput.getId());
Object get_id = gfsinput.getId();//get_filename();
//System.out.println(getData(get_id));
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
//System.out.println("Exception");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
//System.out.println("Exception");
e.printStackTrace();
}*/
System.out.println("DB:" + mongoservice.getDB());
return mongoservice.getDB()+"";
}
/*
* Retrieving the file
*/
public InputStream getData(Object file_id) {
GridFS gfsPhoto = new GridFS(mongoservice.getDB(), "rest_data");
GridFSDBFile dataOutput = gfsPhoto.findOne((ObjectId) file_id);
DBCursor cursor = gfsPhoto.getFileList();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
System.out.println(dataOutput);
return dataOutput.getInputStream();
}
void start(){
System.out.println("hello");
System.out.println(store_in_db());
}
}
Here I was just trying to get database name because every thing can be done after that but I t was returning me NULL because MongoDBService is Unavailable.
At this is Activator class
package agenda.mongodb.gridfs;
import org.amdatu.mongo.MongoDBService;
import org.apache.felix.dm.DependencyActivatorBase;
import org.apache.felix.dm.DependencyManager;
import org.osgi.framework.BundleContext;
import agenda.mongo.inter.AgendaMongo;
public class Activator extends DependencyActivatorBase {
#Override
public void init(BundleContext arg0, DependencyManager manager)
throws Exception {
manager.add(createComponent()
.setInterface(AgendaMongo.class.getName(), null)
.setImplementation(Gridfs_Mongodb.class)
.add(createServiceDependency()
.setService(MongoDBService.class)
.setRequired(true)));
}
#Override
public void destroy(BundleContext arg0, DependencyManager arg1)
throws Exception {
// TODO Auto-generated method stub
}
}
The Interface package is an exported package and the implementation package is private.
The configuration file should have a .cfg extension (not .xml).
I have this Apache Felix activator which gets data source service:
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Properties;
import org.DX_57.osgi.SH_27.api.SessionHandle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.ServiceTracker;
public class SessionHandleApp implements BundleActivator {
public static final String DSNAME = "jdbc/Oracle";
public ServiceTracker st;
#Override
public void start(final BundleContext bc) throws Exception {
debug("Activator started");
Filter filter = bc.createFilter("(&" + "(" + Constants.OBJECTCLASS
+ "=" + DataSource.class.getName() + ")" + "(jndi-name="
+ DSNAME + ")" + ")");
st = new ServiceTracker(bc, filter, null) {
#Override
public Object addingService(ServiceReference reference) {
DataSource ds = (DataSource) bc.getService(reference);
try {
debug(ds.getConnection().toString());
SessionHandle sh = new SessionHandleImpl();
sh.setDataSource(ds);
ServiceRegistration registerService = bc.registerService(SessionHandle.class.getName(), sh, new Properties());
} catch (SQLException e) {
}
return super.addingService(reference);
}
#Override
public void removedService(ServiceReference reference,
Object service) {
super.removedService(reference, service);
}
};
st.open();
}
public void stop(BundleContext bc) throws Exception {
boolean ungetService = bc.ungetService(bc.getServiceReference(SessionHandle.class.getName()));
st.close();
}
private void debug(String msg) {
System.out.println("JDBCBundleActivator: " + msg);
}
}
This solution works but legacy aproach with using a database driver classname to configure JDBC does not work well in OSGi.
How I must write a bundle with an activator that initializes the datasource and offers it as a service?
I think you are confused. The above code is not using JDBC driver. It is using JDBC datasource as a service. In GlassFish, the easiest way to create a DataSource service is to use GlassFish administration operation like "asadmin create-jdbc-resource with a JNDI name." Then GlassFish automatically registers it as a DataSource OSGi service with a registration property jndi-name=YourSuppliedJndiName.
You may check Gemini DBAccess project, it exports a DataSourceFactory as an OSGi Service, so you can just use it.