Is there an elegant way to use Services across or between OSGi containers?
Is it even possible?
For instance, lets say I have a service interface on my local machine. What methodologies/technologies can I use to get that service interface accessible through a remote OSGi container's BundleContext?
There is a RFC called Remote Services (formerly Distributed OSGi) that does exactly what you are trying to achieve. The RFC is almost completed, and there are already 2 implementations provided respectively by Apache CXF and Eclipse ECF.
Both the implementations allows to do transparent remoting of an OSGi service. You just have to define the OSGi service as usual, and add some configuration parameters to make it a remote service.
Check:
http://cxf.apache.org/distributed-osgi.html
It is possible, but there are no libraries (afaik) that will do this for you. I've rolled my own for my current job. OSGi runtime on client and server, RMI is the transport. I've had to make HEAVY use of Proxy objects.
Register a service in the server's OSGi runtime (Equinox). I have a listener that watches all services looking for a property/attribute indicating this service should be exported (made remote), something like "remotable=true". It's easy to filter using the ServiceTracker. Over RMI I instruct the client to create a Proxy object with the service interface. All calls to this proxy object are generically send back over RMI (a call like execService serviceid, method name, var args params) and then invoked on the REAL service.
I've left out some of the low level details, but you can probably sort it out. If you can stray away from RMI, you may want to look into Riena (there may even be a way to write an RMI transport for Riena, I just haven't bothered to try)
It's not very clear what you are trying to achieve. You have got a service, you can access it using RMI, and you need to available as an OSGi service?
I guess you could write an interface to you local machine service. You could then write a bundle that connectes to that service and exposes that interface in the OSGi service registry. Then, your main bundle could locate that service using the interface name or service name.
It shouldn't be too much work to get an RMI connection to your local service. Maybe some config options to establish the initial connection. It might be important to write a facade for your service before you publish it in OSGi, in order to achieve some form of decoupling, and perhaps to hide the fact that it is an RMI service.
But then maybe I completely misunderstood you and all this is useless.
As well as CXF above, there's also Eclipse ECF, which is a collection of communication frameworks and provies an early implementation of the OSGi 4.2 remote services (aka distributed OSGi). It works by registering a local service to which your client binds in the VM, then creates a proxy on the remote machine, and using a technology of your choice (RMI, WebServices etc.) can remote the calls.
Obviously this uses by-value method invocation syntax (which your service needs to know about) but other than that, any comms errors are RuntimeException.
It certainly is possibly. Check out https://docs.paremus.com//display/NIM20/Home which includes an OSGi RSA implementation that includes a high performance RMI distribution provider.
Check the chapter "Remote Services" in the OSGi specification version 4.2.
It defines a standard way for distributing services between several OSGi containers.
The brand new version 4.3 of the OSGi spec has even more detailed support for this - see chapter 6 Remote Services and 112 Remote Service Admin Service.
Related
I have spent some time on investigating what Endpoint.publish can and cannot do, and it appears that you very quickly enter undocumented territory.
In case you build a simple stand alone application which expose one or more #WebService annotated classes with Endpoint.publish and you then run into a situation where you cannot use Endpoint.publish any more (for any reason) what is then the simplest migration path?
I know that you can create a WAR with sun-jaxws.xml and optionally Metro jars which you can then deploy to an embedded web server (like Jetty or Winstone) but I like the simple "take THIS class and expose it at THIS url" API of Endpoint.publish() without any XML or full containers.
Is there a good way to do this?
It's been said that you can an instance of com.sun.net.httpserver.HttpServer to customize the HTTP behavior of the endpoint. It's always a good idea to be cautious of com.sun APIs but it might be appropriate depending your situation. There's an HttpsServer subclass that can be used to provide SSL, for example.
The process seems to be:
Use HttpServer.create(new InetSocketAddress(listenPortNumber), waitQueueDepth) to create a server instance.
Use server.createContext("/path") to create a context that will host the endpoint.
Create an endpoint with Endpoint.create(new RpcLitEndpoint()). It's not clear where RpcLitEndpoint is defined or whether it's strictly required; it may be part of Metro JAX-WS.
Call endpoint.publish(context) to associate the endpoint with the HttpServer (or HttpsServer) instance.
When done, use endpoint.stop and server.stop to shut down.
There's also a blog entry on blogs.oracle.com describing the creation of custom network transports. It didn't have enough detail for me to get a great understanding from a quick scan, but maybe you can get more out of it.
Case:
Developing a standalone java client which will run on different locations on multiple user desktops.
Application server(Oracle Weblogic) will be running at centralized location in different place.
Now I want to access/call EJB (Session Bean) running on central server from client.
As client and server are on different location and not connected via Intranet or LAN only medium of connection is internet.
My question is how can I call EJB's in server directly from client without using a servlet/JSP layer in between?
EJB was devised for remote access , why a servlet dependency?
I have read that RMI-IIOP can be used to make this type of connection but I am unable to use RMI-IIOP over internet!
What is the best architecture/solution for this type of remote communication?
Remember that the EJB is a consise unit of buisness logic, they are protocol agnostic. Exposing it to the caller is the job of the application server. RMI-IIOP/CORBA is just the default.
The internet routing issue with IIOP is similar to many protocols, it is not that they don't route over the internet, it is that they do not have an easy proxy / reverse proxy feature built in. Hence has issues going through a DMZ. Compared to HTTP which has support for reverse proxy, or SMTP allows for relaying. The firewall port is typically closed as well, You would not normally put an application server in a DMZ.
To solve the problem of giving direct access to business logic to an external network, i typically change protocols to something designed for external network communications. For example, annotate (or deployment descriptor) the EJBs with the #WebMethod and the become available as SOAP services automatically, or use the #PATH (etc.) to expose them as HTTP/JSON/XML services.
CORBA type protocols have out-of-the-box features for security, XA transactions and are very high performance. I usually use this for enterprise level component oriented systems internally. (each EJB component is essentially used as a microservice) While for external integration, especially where the caller does not need to pre-know the interface contract, I typically go with a SOAP or HTTP/JSON/XML endpoints for the EJB.
There is no servlet dependency. There is a custom client/protocol dependency that's app server specific. Each server has their own way of setting up the connection, manifested through configuring JNDI for the proper providers and protocol handlers.
Why won't RMI-IIOP work over the internet? The only potential issue I can see there is security, I don't know if there's an encrypted version of RMI-IIOP or not, but other than that, it's a perfectly routable protocol.
You may run in to port and firewall issues, but that's not the protocols fault. If you want to run RMI-IIOP over port 80 (http's port), then that's fine (obviously it won't be http, nor work with http proxies, but again, that's not the protocols issue).
Weblogic also has (had?) their own protocol, T3? I think it was? Can you use that?
I think the key is why you don't think you can run RMI-IIOP "over the internet", and trying to solve that problem, not necessarily what protocol to use.
The RMI/IIOP is the default provided by the application server. By configuration / annotation SOAP or HTTP/XML/JSON can be used instead. (Although these protocols have some trade-off with security, transactions, etc.)
Well EJB doesn't have at all a dependency on the servlet. They can be called directly using RMI/IIOP.
The only problem you have to face is the network structure, i mean RMI/IIOP uses some ports that usually aren't open in company Firewall and it could be quite difficult to open them.
So usually it is better to make an HTTP request because almost all firewall accepts this kind of request.
So if you are in an intranet (client and server in the same intranet) you can use RMI/IIOP but if your client and server are placed in different networks with internet connection then i suggest to you to use HTTP.
You could use Webservices and "export" your EJB as a web service.
If you don't want to use Webservices then you could implement as extrema-ratio a servlet that receives HTTP request and calls the EJB. It depends on the type of object you have to return to the client.
If it is a simple string or something not too complex then you could even use a Servlet but if they are objects then the Servelt solution isn't the right choice.
Webmethods Integration Server can integrate systems and orchestrate different web services from external systems on the network.
My question is: Is it possible to create Java code running in Webmethods Integration Server, and expose it as a web service? Therefore, having Webmethods host the web service.
yes that's possible. You can use a Java service inside IS to code your logic. You have to define an interface for this service (a doctype). After this is done, you create a webservice provider that calls your service.
This applies to IS from version 7 upwards.
Absolutely, that's one of the core purposes of the platform.
To expose any service (flow, java, adapter service etc) you need to create a web service connector (of type "Provider") and then drag the services you want to expose onto it. You can then point to the WSDL it generates.
The approach of webMethods to have everything as a service means that any code you write on the Integration Server can be added to one of these providers and thus invoked as a web service.
You can also proxy other web services (e.g. the wrap and layer approach) by building a web service connector (Provider) using an existing WSDL. What it will then do is mimic the existing WSDL and allow you to provide an implementation of it.
I have a stand-alone, Swing application that uses Hibernate for its persistence layer. I need to extend this to a three-tier system, so that there will be multiple instances of the Swing application and a central server. The client is a stock trading platform, so it will contain a lot of business logic. The server will be responsible for mostly persistence operations and some business logic.
What would be the best way to implement the server for my needs? EJB3 or Spring? What is the best practice for Swing applications to interact with a server? I don't want to go with RMI since not only is it becoming obsolete but also there is no guarantee that the clients and the server will be on the same network.
If the client is a Java client, I don't see the point of using web services (and thus having the overhead of the object to XML serialization) and I would go for EJB 3.x.
For me, the major benefits (beyond performance and scalability) that you get with a good container are fault-tolerance and fail-over (both on the server side and client side, especially with Stateless Session Beans if they are idempotent). For a stock trading platform, this matters.
Also note that using EJB3 doesn't necessarily exclude using Spring for the glue (on the client side and/or the server side).
And if the need to expose your services as web services should arise (e.g. for another non Java client), just annotate them with JAX-WS annotations.
I don't want to go with RMI since not
only is it becoming obsolete
This isn't true at all. As long as Java is around, you'll have RMI.
And what do you think EJBs are using to communicate? It's RMI.
but also there is no guarantee that
the clients and the server will be on
the same network.
Personally, I'd prefer Spring. You can expose your service layer using web services or HTTP remoting.
Go with Spring and RMI. If your client and server are both Java it is the best solution with best performance and productivity.
Note that EJBs don't necessarily use RMI as the transport protocol. OpenEJB for example uses its own custom protocol. We get about 7300 TPS over the wire which is pretty good. There is a Spring integration as well so if you wanted, you could build the server with Spring and inject Spring beans into EJBs and vice versa:
http://openejb.apache.org/3.0/spring.html
I'd like to implement a little test to check connectivity to J2EE services over RMI. It needs to be generic, so that I could just give it a property file with the following properties set in it:
java.naming.factory.initial=oracle.j2ee.rmi.RMIInitialContextFactory
java.naming.security.principal=user
java.naming.security.credentials=pass
java.naming.provider.url=ormi://hostname:port/application
Checking the port is not sufficient, because other applications could be successfully deployed on the server. I can't assume that all applications in our environment have a default service with default method (like a ping method), which would make it much easier.
Is there a standard test I could perform using the java.naming.provider.url?
I settled for a method which isn't quite as generic as I would like, but which works.
Because all services are deployed on an Oracle OAS, I can execute opmnctl to get the status of the container and all applications. Not pretty, but it does the job.