I'm trying to expose a web service method via JAX-WS annotations. Many examples I've seen reference the EndPoint.publish() method to quickly stand up the service in a standalone app (ex from Java Web Services: Up and Running, 1st Edition):
public class TimeServerPublisher {
public static void main(String[ ] args) {
// 1st argument is the publication URL
// 2nd argument is an SIB instance
Endpoint.publish("http://127.0.0.1:9876/ts", new TimeServerImpl());
}
}
One thing that I'm missing is how to accomplish essentially the same thing but in an existing app. Would I make a servlet to handle this? What is the proper way to publish this service in an existing WAR file?
In a container you don't have to publish like this. The container will do the publish. If you plan to use it in JBoss server try JBossWS otherwise for Tomcat or any other server Axis2 may be the better choice.
Read more from the following links.
http://jbossws.jboss.org/mediawiki/index.php?title=JBossWS
http://ws.apache.org/axis2/
This depends on what WS stack you are using.
If you are using Java 6 then that includes the JAX-WS reference implementation, then you can consult the documentation about JAX-WS RI WAR contents.
As #Jerrish and #andri coments, there are different aproaches and solutions, depending on your concerns.
The idea behind is that you don't need to set the configuration (port, etc) when will be published your web service. The best approach could be to set this via configuration files (XML, properties, etc) or using #Annotations.
For example, if you're accustomed to use frameworks like Guice or Spring, you know that is possible/recommended to start the context of your application publishing or initializing some objects, factories, datasources, etc and publishing webservices is another task that can be done in this time, because will be available when you will start your application, isn't?.
By the way, I've good experiences with CXF and another solution could be Spring Web Services another powerful solution for creating web services.
Related
I spent quite a few days now trying to figure out how to add a website in OSGi.
I hava Restlet web service running with Jetty extension to use Jetty as a connector. This feature provides different resources under multiple URLs.
But I would also like to have a small website running on the system that can be accessed by the user. I wanted to use some HTML,Javascript,CSS and provide the current data status with some graphs and pictures.
I assume since Jetty is running in the background I would be able to deploy this website on Jetty and maybe call the server resources provided by Restlet in Javascript.
Apparently nothing worked except the restlet services.
My question would be is it possible to add a WAB bundle and expect it to work(Since Jetty is running in background)? Or is there any better way to add a website in OSGi?
Or
The only option I have now is, since it is possible to return an HTML form as a representation, add all my javascript code inside the HTML form and send it as a response to GET request(Which I believe is a mess).
Everything will run in Raspberry pi so I can only have a very small footprint. I am using Equinox, Restlet 2.3.0 and Jetty 9.2.6.
I would really appreciate if someone knows a link where i could get info on getting at least a sample page running in OSGi. I have tried many with no luck.
I recommend you to have a look at how it is done in Apache Karaf (https://github.com/apache/karaf). More on Apache Karaf and WebContainers here: http://karaf.apache.org/manual/latest/users-guide/webcontainer.html
In fact, Jetty is internally used by Restlet under the hood through its connector feature. This way, it's not convenient (and not the correct approach) to register dynamically applications.
That said, Restlet is really flexible and dynamic. This means that you can dynamically handle bundles that contain Restlet applications in a similar way than WAB bundles, i.e. attach them to virtual hosts of a component.
Here is the way to implement this:
Create a bundle that makes available the Restlet component into the OSGi container. You should leverage the FrameworkListener listener to be able that all connectors, converters, and so on... are registered into the Restlet engine:
private Component component;
public void start(BundleContext bundleContext) throws Exception {
bundleContext.addFrameworkListener(new FrameworkListener() {
component = new Component();
(...)
component.start();
});
}
public void stop(BundleContext bundleContext) throws Exception {
component.stop();
}
When the component is started, you can look for bundles that are present in the container and contained Restlet applications. For each bundle of this kind, you can register a dedicated OSGi service that make available the internal Restlet application you want to register against the component.
ServiceReference[] restletAppRefs = bundleContext.getServiceReferences(
"restletApplication",
null);
if (restletAppsRefs != null) {
for (ServiceReference restletAppRef : restletAppsRefs) {
RestletApplicationService descriptor
= (RestletApplicationService) bundleContext
.getService(serviceReference);
String path = descriptor.getPath();
Application restletApplication = descriptor.getApplication();
// Register the application against the component
(...)
}
}
Registering applications against the component is
try {
VirtualHost virtualHost = getExistingVirtualHost(
component, hostDomain, hostPort);
if (virtualHost == null) {
virtualHost = new VirtualHost();
virtualHost.setHostDomain(hostDomain);
virtualHost.setHostPort(hostPort);
component.getHosts().add(virtualHost);
}
Context context = component.getContext().createChildContext();
virtualHost.setContext(context);
virtualHost.attachDefault(application);
component.updateHosts();
application.start();
} catch(Exception ex) {
(...)
}
You also need to take into account the dynamics of OSGi. I mean bundles can come and go after the start of the OSGi container itself. You can leverage
bundleContext.addServiceListener(new ServiceListener() {
public void serviceChanged(ServiceEvent event) {
if (isServiceClass(event, RestletApplicationService)) {
int type = event.getType();
if (type == ServiceEvent.REGISTERED) {
// Register the Restlet application against the component
} else if (type == ServiceEvent.UNREGISTERING) {
// Unregister the Restlet application
}
}
}
});
Hope it helps you,
Thierry
There are many options available to you - OSGi doesn't really impose many restrictions on what you can do. If you want to use OSGi's capabilities then here's a couple of ideas:
One option would be to deploy a WAB. You'll need to ensure that your framework has the necessary OSGi Services running though. Just because some bundle is using Jetty internally it doesn't follow that the necessary OSGi services are running.
The bundle org.apache.felix.http.jetty does provide the necessary services to deploy a WAB. Version 2.2.2 is 1.3MB on disk, and embeds its own copy of Jetty. Other implementations are available (e.g. Pax-Web, as used in Karaf - which also embeds Jetty)
Another option would be to use the OSGi Http service directly (again you'd need to include a bundle which implements this service (like the Felix one mentioned). A call to org.osgi.service.http.HttpService.registerResources() will serve up static content from within your bundle.
If the this additional footprint is a real concern then you might want to look at how you can get Restlet to use the OSGi http service, rather than providing it's own via embedded Jetty.
Yet another option would be to take a Jetty centric view of things. Restlet's embedded Jetty is probably not configured to serve arbitrary content from disk. You could look at either re-configuring the embedded Jetty to do this, or consider deploying Restlet to a 'standard' Jetty install. Personally, I'd try the latter.
I am learning Spring using this tutorial. I am unable to get my head around the following excerpt from it:
Spring enables developers to develop enterprise-class applications using POJOs. The benefit of using only POJOs is that you do not need an EJB container product such as an application server but you have the option of using only a robust servlet container such as Tomcat or some commercial product.
In the good old days when application servers only supported EJB 2 it was a nightmare to develop services using EJBs. Each service (e.g. a stateless session bean) required a bunch of interfaces and strange additional methods to work properly (home interface, remote interface, deployment descriptors etc).
In order to run EJBs you need an application server such as Jboss or Glassfish. In order to run servlets you simply need a servlet container such as Tomcat or Jetty which is way more lightweight than an application server.
Spring offers a way of creating simple services as plain POJOs (that can be exposed via servlets). Therefore, to be able to develop services as a POJO was simply a dream come true. Services did not need all the constraining dependencies to the EJB-interfaces and they could be deployed in a lightweight servlet container.
Then came EJB3 which greatly improved life for the Java EE developer. EJBs no longer needed the dependencies for home- and remote-interfaces (at least not via inheritence). A modern EJB 3 service is very similar to a POJO-based service. The main difference is that EJBs still require an application server to be deployed.
Spring Guru Rod Johnson released the book J2EE Development without EJBs which greatly explains how to replace your old J2EE components (such as EJBs) with more lightweight Spring Pojos - good reading!
Read below link which may help you understand meaning of benefit of using POJO :
http://www.javaexperience.com/difference-between-pojo-javabean-ejb/
Is it possible to inject a bean from a web application that deploy in another server!
I declare a scenario to myself, I have two web application that use spring framework and deploy separately in different application servers (one is TOMCAT and another one is WEBLOGIC),the first application has ServiceA and the second one has ServiceB, now I want to inject ServiceB in ServieA?
I try to do this with RMI once an another one with JMS, now I am wondering that:
Is it possible with another thing?
Is there any active project about this scenario exist?
How can share application context in spring framework, is it possible?
Thanks.
Bean is just an object in JVM. You certainly cannot use an object from one JVM in another JVM straightforward.
But you can do 2 things:
Use proxies - some objects that will have the same interface but invoke somehow to the proper server as implementation.
Use service-oriented architecture (SOA). Each server should have some limited set of beans that are responsible for their functionality. And all beans can interact with each other.
Maybe OSGI is suitable for this.
Web services, JAX-RS is the simplest. But JAX-WS provides you with the tools to automatically generate the client code.
I'm currently developing a small EJB application running on IBM Websphere Application Server 7 (Java EE 5). The app mainly consists of one MDB listening for incoming MQ messages which are transformed and stored in a DB. Currently I'm using a lot of Singleton/Factories to share configurations, mappings, datasource lookups etc. But this actually leads to some very hard to test code. The solution might be using a (simple) DI framework like guice/spring to inject the different instances. The question is: Where to place the initialization/ setup code? Where is the main entry point of the application? How can I inject instances into the MDBs?
it might be worth looking at backing off from using Guice, and trying to work with the injection mechanisms already available with Java EE 5.
Regarding finding a suitable "startup point", unfortunately the EJB specification does not define a way where you can have a bean run at startup. However, the web profile of the EE spec does have one -- you can add a WAR to your application, and set a servlet listener component:
http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletContextListener.html
You can set this to start whenever the application is loaded and started by the container (WebSphere). Watch out for classloader issues though.
Using Spring, you can do it via EJB3 interceptors, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/ejb.html#ejb-implementation-ejb3
Useful info on caveats are in the javadoc, make sure you read it: http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/ejb/interceptor/SpringBeanAutowiringInterceptor.html
OSGi employs a service-oriented architecture: Bundles register service objects, that other bundles consume. Service publishing and binding is managed by the framework. This decouples service providers from service users completely (except for the need to agree on a service interface).
Is there a way to limit (by configuration) what services are visible to what bundles ?
For example, if I have an HttpService, all bundles that feel like doing so can install servlets into it. I would like to make the HttpService not visible to selective bundles.
For extra credits: In addition to just filtering service registrations, the ability to modify registration properties. So that even if a bundle registers a Servlet with alias=/admin, I can change that to alias=/somethingelse for consumption by Pax Web Extender Whiteboard.
Is there a way to limit (by configuration) what services are visible to what bundles?
As you are aware, it is possible to filter on service properties, though this probably doesn't give the sort of control you are asking for: the services are still visible to other bundles deployed in the framework.
In SpringSource's dm Server (an open-source, modular, OSGi-based Java application server) an application can be Scoped when it is deployed. This allows you to deploy multiple applications (in separate scopes) that might include inconsistent versions of dependent bundles, while still allowing common bundles to be shared (by deploying them outside of a scopeāin the so-called global scope).
If a scoped application/bundle registers an OSGi service it is only available to the bundles in the same scope. (The services are 'scoped' as well.)
This is not magic: the server wraps the OSGi services interfaces and uses service properties 'under the covers' to perform the filtering required on-the-fly.
I think this would give you the sort of separation you are looking for.
For information about dm Server (not to be confused with Spring DM) go to the SpringSource.org dmServer page.
Steve Powell
SpringSource; dm Server Development
The upcoming R4.2 of the OSGi specification define a component called Find Hook that allows exactly to:
"inspect the returned set of service references and optionally shrink the set of returned services"
See
http://www.osgi.org/download/r4-v4.2-core-draft-20090310.pdf section 12.5
Please note that R4.2 is not final yet, still I believe the major OSGi implementations (Felix and Equinox) already have the code for this additional functionality in their trunk
Is there a way to limit (by configuration) what services are visible to what bundles ?
There is no way to do that using service properties. You could define your own service property that specifies which bundles should consume the service you are exporting, but there is no way to prevent other bundles from consuming it as well.
For extra credits: In addition to just filtering service registrations, the ability to >modify registration properties. So that even if a bundle registers a Servlet with >alias=/admin, I can change that to alias=/somethingelse for consumption by Pax Web >Extender Whiteboard.
Well... that's a tough one. You could define your own Servlet interface "MyServlet" and export your Servlets using that interface. Then, another bundle could consume those MyServlets and re-export them as Servlets with modified service properties.
Other than that ... no idea.
I haven't tried this, but seems like it may help you...
In the OSGi R4 Component Spec describes the "Configuration Admin Service" which, from a 5 minutes inspection, appears to be able to alter services dynamically.
Ultimately I think it will be up to you to control access to the services based on some agreed upon configuration values
For extra credits: In addition to just filtering service registrations, the ability to modify registration properties. So that even if a bundle registers a Servlet with alias=/admin, I can change that to alias=/somethingelse for consumption by Pax Web Extender Whiteboard.
using iPOJO you can change properties of the exposed services pretty simple. It has bunch of other features, which could be interessting to someone using OSGi a lot.
If you want to limit the visibility of services, your best bet is to enable OSGi security. It is designed to limit what services, packages and other things are visible to what bundles. You can for example only make a certain service available to a bundle that is signed by you (or use various other criteria).
The other option, already mentioned, it to use the 4.2 service hooks, which allow a sort of "do it yourself" security mechanism.
The second question, changing properties like the endpoint under which a service is registered, is something you can do via the ServiceRegistration that you get back when registering your service. Changes can be triggered by becoming a ManagedService and use ConfigurationAdmin to configure yourself.