How to store files uploaded from client machine to jboss standalone directory? - spring-mvc

I have requirement to store files uploaded (using spring mvc) from client machine to jboss standalone directory .Give step by step solution

I would give the community project called Spring Content a try. This project makes it very easy to handle files by injecting the service and controller implementations for you (so that you don't need to write them yourself).
Adding it would look something like this:
pom.xml (assuming maven. Spring boot starters also available)
<!-- Java API -->
<!-- just change this depdendency if you want to store somewhere else -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-fs</artifactId>
<version>0.8.0</version>
</dependency>
<!-- REST API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-rest</artifactId>
<version>0.8.0</version>
</dependency>
StoreConfig.java
#Configuration
#EnableFilesystemStores
#Import(RestConfiguration.class)
public class StoreConfig {
#Bean
FileSystemResourceLoader fileSystemResourceLoader() throws IOException {
return new FileSystemResourceLoader(new File("/path/to/uploaded/files").getAbsolutePath());
}
}
FileStore.java
#StoreRestResource(path="files")
public interface FileStore extends Store<String> {
}
And that's it. The FileStore is essentially a generic Spring ResourceLoader. The spring-content-fs dependency will cause Spring Content to inject a filesystem-based implementation. The spring-content-rest dependency will cause Spring Content to also inject an implementation if an #Controller that forwards HTTP requests onto the methods of the FileStore service.
So you will now have a fully functional (POST, PUT, GET, DELETE) REST-based file service at /files that will use your FileStore to retrieve (and store) files in /path/to/uploaded/files on your jboss server.
So:
curl --upload-file some-image.jpg /files/some-image.jpg
will upload some-image.jpg and store it in /path/to/uploaded/files on your server.
And:
curl /files/some-image.jpg
would retrieve it again.
HTH
The injected controller also supports video streaming too, in case that is useful.
With this you could also remove all of your controller and service code as it is no longer required. Plus, as Spring Content is an abstraction over storage, in future, you could also shift to any of the other storage mediums supported by Spring Content; S3 for example.

Related

Using aquillian to test jax-rs - do I need a servlet?

I'm testing my jax-rs services using aquillian and the wildfly embeded container. In this setup, I'm trying to understand how my web services are handled by the server. To set things up, I have the following deployment in my test:
#Deployment
public static WebArchive create() {
return ShrinkWrap.create(WebArchive.class, "rest-service.war")
.addClasses(ProfileService.class,
Profile.class); // classes and other resources into the war
}
So that war gets deployed and its running in an embedable container. However, my test can't find a service at any of the URLs mapped in ProfileService. Is it because my war is missing a servlet? Specifically, a javax.ws.rs.core.Application instance? Or am I misunderstanding how EJB containers expose jax-rs services.
It is because you're missing a class that extends Application, however you don't need to register it as a servlet. As long as its annotated #ApplicationPath it will be picked up by the container.

Cannot reach EJB exposed as REST service

I'm trying to expose some EJBs as REST web service using JAX-RS annotations. When I deploy war file containing EJB Jar in WEB-INF/lib to Wildfly 8, I can see in web admin panel EJB Jar as deployed, But I cannot reach REST endpoints and get 404.
This is content of web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/separated/*</url-pattern>
</servlet-mapping>
</web-app>
This is a sample session bean I'm trying to serve as web service and put in jar file:
#Stateless(name = "TestSessionEJB")
#LocalBean
public class TestSessionBean {
#PersistenceContext(unitName = "TestPU")
private EntityManager em;
public AuthenticationSessionBean() {
}
#GET
#Path("ep")
public String testEP() {
return "Hello from testEP()";
}
}
I cannot reach testEP through /<war_file_name>/separated/ep. Added ejb-jar.xml descriptor to WEB-INF/, still no success. I made another service with classes compiled and deployed directly in war file's WEB-INF/classes:
#ApplicationPath("/integrated")
public class TestRestApp extends Application {
}
#Path("/ep")
public class TestRestEp {
#GET
public String doGet() {
return "success";
}
}
Here I can reach doGet() through /<war_file_name>/integrated/ep.
Am I missing something? Can I deploy EJBs as separated jar files and expose them as REST web services with no wrapper?
UPDATE:
I annotated TestSessionBean with ApplicationPath("separated") and made it extending from javax.ws.rs.Application. Still getting 404 but this time It's different; 404 without "Not Found" body. If I make an endpoint path same as an endpoint in TestRestApp, e.g #Path("ep") It maps to endpoint in TestRestApp and I get "success" instead of "Hello from testEP()" by navigating to /<war_file_name>/separated/ep. If I annotate a method in TestSessionBean with a path not defined in TestRestApp result is 404. I cleared my web.xml out of servlet definitions and still same result.
First
Simply annotating an EJB class's method with JAX-RS annotations will not make the method a JAX-RS resource method. You need to make TestSessionBean a root resource class by annotating it with #Path, like you did with TestRestEp. Or you can make this class a Sub-Resource and have a Root resource pass the request to this class. I'd just stick to the former, if you have no idea what the latter means.
Second
Keeping in mind Wildfly (JBoss) modular architceture
Stated in the Resteasy (Wildfly's JAX-RS implementation) Reference Guide:
Resteasy and JAX-RS are automically loaded into your deployment's classpath, if and only if you are deploying a JAX-RS Application.
That being said, your web.xml doesn't create a JAX-RS application. You are basically depending on the (default JAX-RS specified) javax.ws.rs.Application servlet, which is only loaded if the JAX-RS module is loaded into the Server.
When you have an Application subclass, with the #ApplicationPath annotation, this creates a JAX-RS application and the JAX-RS module is loaded into the Server and the classpath will be scanned for resource classes.
Also stated in the JAX-RS spec:
The resources and providers that make up a JAX-RS application are configured via an application-supplied subclass of Application. An implementation MAY provide alternate mechanisms for locating resource classes and providers (e.g. runtime class scanning) but use of Application is the only portable means of configuration.
So I would stick to the Application subclass. No web.xml needed

Where to hook up authentication in Grizzly?

I'm using a Grizzly HttpServer which has two HttpHandler instances registered:
under /api/* there is an Jersey REST - style application offering the API of the product, and
under /* there is an StaticHttpHandler which serves static HTML / JavaScript content (which, among other things, talks to the API under /api/
For authentication I'm currently securing only the API using a Jersey ContainerRequestFilter implementing HTTP Basic Auth, which looks quite similar to what is presented in another SO question.
But as requirements changed, now I'd like to require authentication for all requests hitting the server. So I'd like to move the authentication one level up, from Jersey to Grizzly. Unfortunately, I'm completely lost figuring out where I can hook up a "request filter" (or whatever it is called) in Grizzly. Can someone point me to the relevant API to accomplish this?
The easiest solution would leverage the Grizzly embedded Servlet support.
This of course would mean you'd need to do a little work to migrate your current HttpHandler logic over to Servlets - but that really shouldn't be too difficult as the HttpHandler API is very similar.
I'll give some high level points on doing this.
HttpServer server = HttpServlet.createSimpleServer(<docroot>, <host>, <port>);
// use "" for <context path> if you want the context path to be /
WebappContext ctx = new WebappContext(<logical name>, <context path>);
// do some Jersey initialization here
// Register the Servlets that were converted from HttpHandlers
ServletRegistration s1 = ctx.addServlet(<servlet name>, <Servlet instance or class name>);
s1.addMapping(<url pattern for s1>);
// Repeat for other Servlets ...
// Now for the authentication Filter ...
FilterRegistration reg = ctx.addFilter(<filter name>, <filter instance or class name>);
// Apply this filter to all requests
reg.addMapping(null, "/*");
// do any other additional initialization work ...
// "Deploy" ctx to the server.
ctx.deploy(server);
// start the server and test ...
NOTE: The dynamic registration of Servlets and Filters is based off the Servlet 3.0 API, so if you want information on how to deal with Servlet listeners, init parameters, etc., I would recommend reviewing the Servlet 3.0 javadocs.
NOTE2: The Grizzly Servlet implementation is not 100% compatible with the Servlet specification. It doesn't support standard Servlet annotations, or deployment of traditional Servlet web application archive deployment.
Lastly, there are examples of using the embedded Servlet API here
The "hookup" part can be done using a HttpServerProbe (tested with Grizzly 2.3.5):
srv.getServerConfiguration().getMonitoringConfig().getWebServerConfig()
.addProbes(new HttpServerProbe.Adapter() {
#Override
public void onRequestReceiveEvent(HttpServerFilter filter,
Connection connection, Request request) {
...
}
#Override
public void onRequestCompleteEvent(HttpServerFilter filter,
Connection connection, Response response) {
}
});
For the "linking" to the ContainerRequestFilter you might want to have a look at my question:
UnsupportedOperationException getUserPrincipal

Using Blazeds To Connect to a EJB on Glassfish

The task is to try to connect directly to a stateless EJB deployed on Glassfish. I have already done this via Web Service and I can also connect to the EJB by calling a remote java object which uses JNDI to find and load the bean. What I cannot do is directly connect to the EJB with Blazeds. I am using EBJ3Factory BY Ryan Norris (downloaded from adobe site) as follows;
My WEB-INF/flex/services-config.xml has;
<factories>
<factory id="ejb3" class="com.adobe.ac.ejb.EJB3Factory" />
</factories>
My WEB-INF/flex/remoting-config.xml has;
<destination id="MyEJB">
<properties>
<factory>ejb3</factory>
<source>java:global/Together/PSearch!ejb.PSearch</source>
</properties>
</destination>
I have a simple java class that can access the bean so I can use Blazeds to call the class which then calls the bean;
public void getBean() {
PSearch search;
InitialContext ctx;
try {
ctx = new InitialContext();
search = (PSearch) ctx.lookup("java:global/Together/PSearch!ejb.PSearch");
System.out.println("jndi okay");
} catch (NamingException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
}
The asadmin command for the context in glassfish shows me;
./asadmin list-jndi-entries --context java:global/Together
PSearch__3_x_Internal_RemoteBusinessHome__: javax.naming.Reference
PSearch!ejb.PSearchRemote: javax.naming.Reference
PSearch!ejb.PSearch: com.sun.ejb.containers.JavaGlobalJndiNamingObjectProxy
PSearch!ejb.PSearchLocal: com.sun.ejb.containers.JavaGlobalJndiNamingObjectProxy
Yet when I use Eclipse / Flash Builder to try to Import a BlazeDS service I get an introspection error;
java:global/Together/PSearch/!ejb.PSearch is not available in the specified location
I have also tried changing the remoting-config.xml to point to local and remote interfaces but no joy!
Any pointers would be greatly appreciated.
One workaround you could do would be to remove the factory XML element, replace the source JNDI name with the EJB fully qualified class name and create the service with Flash Builder using the BlazeDS RTS service as you tried to do.
<destination id="MyEJB">
<properties>
<source>packagename.EJBClassName</source>
</properties>
</destination>
When you are done making the service client, service and the value objects(return type etc) in your Flex project then put everything back as they were:
<destination id="MyEJB">
<properties>
<factory>ejb3</factory>
<source>java:global/Together/PSearch!ejb.PSearch</source>
</properties>
</destination>
What u r going to do actually is to treat the EJB 3.x as a normal POJO for the introspection in order to create the AS3 classes and when u r done change the destination to an EJB3 destination by using the factory.
I am working on a way to make this steps unnecessary. If I have time to finish it I will let you know.

How to obtain OSGi service references from a Servlet that is registered in OSGi HttpService?

It seems natural that a HttpServlet running in OSGi environment (i.e. registered in OSGi HttpService) would want to call some OSGi services to accomplish it's tasks. The question is how to obtain references to these OSGi service inside the servlet.
One way would be to inject dependencies into the HttpServlet instance that is being registered to the OSGi HttpService like this:
MyServlet servlet = new MyServlet();
servlet.setFooService(fooService);
httpService.registerServlet("/myservlet", servlet, initparams, context);
I'm not sure if this is a valid approach since in non-OSGi environment the servlet life-cycle is managed by the Web Container and hence the service reference would not be injected for the servlet instances created later on.
There is another way to solve this when using PAX Web as an implementation of the OSGi HttpService. PAX Web exports the OSGi BundleContext into the ServletContext as a special attribute "osgi-bundlecontext". The BundleContext can then be used to obtain necessary service references:
public void init(ServletConfig servletConfig) throws ServletException {
ServletContext context = servletConfig.getServletContext()
BundleContext bundleContext =
(BundleContext) context.getAttribute("osgi-bundlecontext");
ServiceReference serviceRef =
bundleContext.getServiceReference("com.foo.FooService")
}
However this approach is rather ugly and ties you to a concrete implementation of the OSGi HttpService. Do you know any other (and possibly better) solution to this problem?
If you use a setter for the dependency on the service, as you have shown, it can work outside of OSGi as well. You just need to use some other dependency injection mechanism. If there is none, you could provide a subclass that initializes the servlet using JNDI lookups or from the servlet context.
public class MyServlet_AdapterForMissingDI extends MyServlet{
public void init(ServletConfig config){
setFooService(getItFromSomewhere());
}
}
The point being that if you have DI capabilities that can inject setFooService, you can just use the same servlet in OSGi and elsewhere, if you do not (and still want to support this case), you provide an adapter.
On a related note, check out Felix SCR to configure your object's dependencies, and Pax Web Extender Whiteboard, which takes care of hooking your servlet up with the HttpService.
Specifically, without SCR and Whiteboard, you need to think about the case when the fooService becomes unavailable later, or the HttpService gets started after your servlet.
In these cases your servlet would have a reference to a dead service that prevents the bundle from being garbage-collected, or your servlet would not be registered with the HttpService.
Update: Here is the SCR descriptor I use for one of my servlets. SCR handles servlet instantiation, life-cycle, registration (via Whiteboard), and dependencies. There is no OSGi-specific code in the servlet. There is not even the need for a BundleActivator anymore (SCR registers all services):
<component name="oracle.statusServlet" >
<implementation class="mypackage.DataSourceStatusServlet"/>
<property name="service.description" value="Oracle DataSource status servlet" />
<property name="alias" value="/OracleDataSourceStatus" />
<property name="servlet-name" value="Oracle DataSource status servlet" />
<service>
<provide interface="javax.servlet.Servlet" />
</service>
<reference name="DATASOURCES"
interface="javax.sql.DataSource"
cardinality="0..n" policy="dynamic"
bind="bindDataSource" unbind="unbindDataSource"/>
</component>
The dependencies for the servlet are specified in the reference tag. SCR will do the service lookup and binding.
May be an old post and you already might have got the answer..
Are you launching felix or whatever OSGi container yourself. If that is the case you can set the bundle context as an attribute to the servlet context.
Whats wrong in using an http service by PAX. ultimately the thread management and other aspects are taken care of by the servlet container in which you run this http service.
You could inject the services into some object, which is then queried by the servlets.

Resources