opentrace activeSpan is null - opentracing

I have an old application where I am trying to introduce opentrace. Instead of changing individual methods, I have added AOP/aspectJ to add span.But when i try to do
Span currentSpan = GlobalTracer.get().activeSpan()
in my original code, currentSpan is null.
I wonder Why ?
Here is my Code Aspect/AOP.
package com.visenti.LogAspectJ;
import io.jaegertracing.Configuration;
import io.jaegertracing.internal.JaegerTracer;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.Tracer;
import io.opentracing.util.GlobalTracer;
import org.aspectj.lang.Signature;
public aspect LogAspectJ {
pointcut methodExecution(): execution(* com.visenti.globaliams..*.*(..));
private Tracer tracer = initTracer("AspectJ");
public static JaegerTracer initTracer(String service) {
System.setProperty("JAEGER_AGENT_HOST", "*.*.*.*");
Configuration.SamplerConfiguration samplerConfig = Configuration.SamplerConfiguration.fromEnv().withType("const").withParam(1);
Configuration.ReporterConfiguration reporterConfig = Configuration.ReporterConfiguration.fromEnv().withLogSpans(true);
Configuration config = new Configuration(service).withSampler(samplerConfig).withReporter(reporterConfig);
JaegerTracer tracer = config.getTracer();
GlobalTracer.registerIfAbsent(tracer);
return tracer;
}
Object around(): methodExecution() {
Signature signature = thisJoinPoint.getSignature();
String operationName = signature.getName();
String declaringTypeName = signature.getDeclaringType().getSimpleName()+"::"+operationName;
Tracer.SpanBuilder spanBuilder = tracer.buildSpan(declaringTypeName);
Span spanStart = spanBuilder.start();
Scope scope = tracer.activateSpan(spanStart);
Object response = proceed();
scope.close();
spanStart.finish();
return response;
}
}
This is my old code where I am trying to get parent span. This below method is covered by AOP, I can see in debugger.
What I am trying to understand is why it is null ? I expected the span to be propagated the method call chain.

I've had a similar problem in a jax-rs application. What solved the issue for me was adding jaeger and opentracing-jaxrs2 dependencies.
<dependency>
<groupId>io.jaegertracing</groupId>
<artifactId>jaeger-client</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-jaxrs2</artifactId>
<version>1.0.0</version>
</dependency>
And the web.xml file I added filter and filter-mapping tags as follows:
<filter>
<filter-name>TracingFilter</filter-name>
<filter-class>io.opentracing.contrib.web.servlet.filter.TracingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TracingFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
I think the problem was that java CDI was not injecting those filters.
Cheers!

Related

Declarative services in OSGI

I have created a (very) simple test to determine how to send and receive events using Apache Felix.
This is my sender:
package be.pxl;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import java.util.HashMap;
#Component(name = "be.pxl.Publisher", immediate = true)
public class Publisher {
EventAdmin admin;
#Activate
public void run(Object object) {
System.out.println("IN PUBLISHER");
Event event = new Event("event", new HashMap<String, Object>());
System.out.println("\tEVENT: " + event);
admin.postEvent(event);
System.out.println("\tADMIN: " + admin);
}
#Reference(name="be.pxl.admin", service = EventAdmin.class)
protected void setEventAdmin(EventAdmin admin) {
this.admin = admin;
}
}
This is my receiver:
package be.pxl;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
import java.util.Dictionary;
import java.util.Hashtable;
#Component(name = "be.pxl.Subscriber", immediate = true)
public class Subscriber implements EventHandler {
private BundleContext context;
#Activate
public void run(Object object) {
System.out.println("IN SUBSCRIBER");
System.out.println("\tIN RUN METHOD");
String[] topics = new String[]{"event"};
Dictionary props = new Hashtable();
props.put(EventConstants.EVENT_TOPIC, topics);
System.out.println("\t\tCONTEXT: " + context);
context.registerService(EventHandler.class.getName(), this, props);
System.out.println("\t\tCONTEXT AFTER REGISTERSERVICE: " + context);
}
public void handleEvent(Event event) {
System.out.println("IN SUBSCRIBER");
String text = event.getProperty("text").toString();
System.out.println("\tEVENT CALLED: " + text);
}
#Reference(name="be.pxl.context", service=BundleContext.class)
protected void setBundleContex(BundleContext context) {
this.context = context;
}
}
This is the pom of my sender:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>be.pxl</groupId>
<artifactId>EventSender</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.service.event</artifactId>
<version>1.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.service.component.annotations</artifactId>
<version>1.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
<version>3.2.100.v20100503</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.4.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Vendor>SmartCampus</Bundle-Vendor>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>
be.pxl.*;version="1.0.0"
</Export-Package>
<Import-Package>
org.osgi.service.component.annotations
org.eclipse.osgi.service
org.osgi.core
org.osgi.service.event
</Import-Package>
<_dsannotations>*</_dsannotations>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
Everything compiles fine. I create it using mvn clean package, then I install this jar file in my apache felix container and start it. However, nothing happens. Nothing get pritns out.
Thanks in advance!
You appear to be most of the way there! As you've identified, Event Admin uses a whiteboard model to receive events. The important thing is that you need to tell the whiteboard which topics you want to listen to, which you do.
%%% Update %%%
Event admin topic names use a hierarchy of tokens separated by / characters. When publishing an event you do so to a specific topic, for example foo/bar/baz. When receiving events the EventHandler will be called for topics that match its registered interest(s). These interests can either be for a specific topic, or they can end with a * to indicate a wildcard match. For example foo/bar/* would receive events sent to foo/bar/baz and events sent to foo/bar/fizzbuzz.
%%% Back to the original %%%
There are, however a couple of issues with your code:
Firstly:
#Reference(name="be.pxl.context", service=BundleContext.class)
protected void setBundleContex(BundleContext context) {
this.context = context;
}
This is not how you access the BundleContext for your bundle. If you do need a BundleContext then it should be injected as a parameter into your #Activate annotated method. A BundleContext should never be registered as a service (it represents your bundle's private access to the OSGi framework), and it would not surprise me to find that this reference is unsatisfied in your example. You don't actually need the BundleContext however because...
Secondly:
#Activate
public void run(Object object) {
System.out.println("IN SUBSCRIBER");
System.out.println("\tIN RUN METHOD");
String[] topics = new String[]{"event"};
Dictionary props = new Hashtable();
props.put(EventConstants.EVENT_TOPIC, topics);
System.out.println("\t\tCONTEXT: " + context);
context.registerService(EventHandler.class.getName(), this, props);
System.out.println("\t\tCONTEXT AFTER REGISTERSERVICE: " + context);
}
This is not the right way to write an activate method (and as a result it may not be being called), nor should you be registering your component as a service here. When you make your class an #Component it will automatically be registered as a service using each directly implemented interface. This means that:
#Component(name = "be.pxl.Subscriber", immediate = true)
public class Subscriber implements EventHandler {
...
}
is already an OSGi EventHandler service!
You can add service properties to your component using the #Component annotation, or from the OSGi R7 release (due in a couple of months) using Component Property annotations. In this case you want to set your event.topics property like this:
#Component(property="event.topics=event")
You can then get rid of the activate method completely if you like.
Finally:
Event Admin is not a message queue, and your publisher is a one-shot send. Therefore if your publisher sends the event before the handler is fully registered then it will never receive the event. Consider making the publisher send periodic events, or be certain that the receiver starts before the publisher so that you see the message.
P.S.
It's not technically a problem, but I see that you're using version 2.4 of the maven-bundle-plugin. This is very old and the current released version of bnd is 3.5.0. The Bnd team have also started providing their own Maven plugins (such as the bnd-maven-plugin) that you might want to look at.

How to remove the entire cache, and then pre-populate the cache?

Can someone tell me what is the problem with below implementation. I'm trying to delete the entire cache, secondly, I then want to pre-populate/prime the cache. However, what I've below is only deleting both caches, but not pre-populating/priming the cache, when the two methods are executed. Any idea?
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
#Cacheable(cacheNames = "cacheOne")
List<User> cacheOne() throws Exception {...}
#Cacheable(cacheNames = "cacheOne")
List<Book> cacheTwo() throws Exception {...}
#Caching (
evict = {
#CacheEvict(cacheNames = "cacheOne", allEntries = true),
#CacheEvict(cacheNames = "CacheTwo", allEntries = true)
}
)
void clearAndReloadEntireCache() throws Exception
{
// Trying to reload cacheOne and cacheTwo inside this method
// Is this even possible? if not what is the correct approach?
cacheOne();
cacheTwo();
}
I've spring boot application (v1.4.0), more importantly, utilizing the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
<version>1.0.0</version>
</dependency>
If you call the clearAndReloadEntireCache() method, only this method will be processed by the caching interceptor. Calling other methods of the same object: cacheOne() and cacheTwo() will not cause cache interception at runtime, although both of them are annotated with #Cacheable.
You could achieve desired functionality by reloading cacheOne and cacheTwo with two method calls shown below:
#Caching(evict = {#CacheEvict(cacheNames = "cacheOne", allEntries = true, beforeInvocation = true)},
cacheable = {#Cacheable(cacheNames = "cacheOne")})
public List<User> cleanAndReloadCacheOne() {
return cacheOne();
}
#Caching(evict = {#CacheEvict(cacheNames = "cacheTwo", allEntries = true, beforeInvocation = true)},
cacheable = {#Cacheable(cacheNames = "cacheTwo")})
public List<Book> cleanAndReloadCacheTwo() {
return cacheTwo();
}

Unable to create file upload service - Receiving ModelValidationException (No injection source ) during startup [duplicate]

I am using Jersey based restful Service implementation strategy to build a service which will be used to upload files.
My service class name is : UploadFileService.java (See Code below)
package com.jerser.service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;
#Path("/fileUpload")
public class UploadFileService {
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail) {
String uploadedFileLocation = "d://uploaded/" + fileDetail.getFileName();
// save it
writeToFile(uploadedInputStream, uploadedFileLocation);
String output = "File uploaded to : " + uploadedFileLocation;
return Response.status(200).entity(output).build();
}
// save uploaded file to new location
private void writeToFile(InputStream uploadedInputStream,
String uploadedFileLocation) {
try {
OutputStream out = new FileOutputStream(new File(
uploadedFileLocation));
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(uploadedFileLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
These are the JAR files I have inside my lib:
aopalliance-repackaged-2.4.0-b10.jar
asm-debug-all-5.0.2.jar
hk2-api-2.4.0-b10.jar
hk2-locator-2.4.0-b10.jar
hk2-utils-2.4.0-b10.jar
javassist-3.18.1-GA.jar
javax.annotation-api-1.2.jar
javax.inject-2.4.0-b10.jar
javax.servlet-api-3.0.1.jar
javax.ws.rs-api-2.0.1.jar
jaxb-api-2.2.7.jar
jersey-client.jar
jersey-common.jar
jersey-container-servlet-core.jar
jersey-container-servlet.jar
jersey-core-1.11.jar
jersey-guava-2.17.jar
jersey-media-jaxb.jar
jersey-multipart-1.18.jar
jersey-server.jar
org.osgi.core-4.2.0.jar
osgi-resource-locator-1.0.1.jar
persistence-api-1.0.jar
validation-api-1.1.0.Final.jar
I am getting the following error when I am trying to up my tomcat server :
org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization.
[[FATAL] No injection source found for a parameter of type public javax.ws.rs.core.Response com.jerser.service.UploadFileService.uploadFile(java.io.InputStream,com.sun.jersey.core.header.FormDataContentDisposition) at index 0.; source='ResourceMethod{httpMethod=POST, consumedTypes=[multipart/form-data], producedTypes=[], suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class com.jerser.service.UploadFileService, handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor#d3e2d4]}, definitionMethod=public javax.ws.rs.core.Response com.jerser.service.UploadFileService.uploadFile(java.io.InputStream,com.sun.jersey.core.header.FormDataContentDisposition), parameters=[Parameter [type=class java.io.InputStream, source=file, defaultValue=null], Parameter [type=class com.sun.jersey.core.header.FormDataContentDisposition, source=file, defaultValue=null]], responseType=class javax.ws.rs.core.Response}, nameBindings=[]}']
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:528)
at org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:166)
at org.glassfish.jersey.server.ApplicationHandler$3.run(ApplicationHandler.java:327)
at org.glassfish.jersey.internal.Errors$2.call(Errors.java:289)
at org.glassfish.jersey.internal.Errors$2.call(Errors.java:286)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:286)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:324)
at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:338)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:171)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:363)
at javax.servlet.GenericServlet.init(GenericServlet.java:160)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1176)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1102)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1009)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4885)
at org.apache.catalina.core.StandardContext$3.call(StandardContext.java:5212)
at org.apache.catalina.core.StandardContext$3.call(StandardContext.java:5207)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Over the internet I found there are plenty of example which shows How to upload MULTIPART file using RESTFul API. But with same solution. I am not able to run those code as well.
I think I am doing something wrong with the JAR files. Could anyone please help me on this?
Get rid of jersey-multipart-1.18.jar. That is for Jersey 1.x. Add these two
jersey-media-multipart-2.17
mimepull-1.9.3
For Maven you would use the following dependency (you don't need to explicitly add the mimepull dependency, as this one will pull it in).
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.17</version> <!-- Make sure the Jersey version matches
the one you are currently using -->
</dependency>
Then you need to register the MultiPartFeature. If you are using a ResourceConfig for configuration, you can simply do
register(MultiPartFeature.class);
If you are using web.xml, then you can add the class as an <init-param> to the Jersey servlet
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
Note that if you have multiple providers that you want to register, then you can delimit each provider class with a comma, semicolon, or space/newline. You cannot use this same param-name twice. See Suarabh's answer
UPDATE
Also, once you get rid of jersey-multipart-1.18.jar you will have compile errors for the missing imported classes. For the most part, the class names are still the same, just the packages have changed, i.e.
org.glassfish.jersey.media.multipart.FormDataParam
org.glassfish.jersey.media.multipart.FormDataContentDisposition
For Dropwizard
If you're using Dropwizard, instead of adding the jersey-media-multipart, they document for your to add dropwizard-forms instead. And instead of registering the MultiPartFeature, you should register the MultiPartBundle
#Override
public void initialize(Bootstrap<ExampleConfiguration> bootstrap) {
bootstrap.addBundle(new MultiPartBundle());
}
Really doesn't make much difference though as all the Dropwizard bundle does is register the MultiPartFeature with the ResourceConfig.
Aside
If you are here for a different ModelValidationException, here are some links for information on other causes of the exception.
1
2
3
Yet another possible cause for this very generic error is that Jersey only searches for factories associated with the last annotation when multiple ones are declared on a param. (See bug report)
Until this is fixed, if you are using any other annotations besides #FormDataParam, it has to come last.
This works:
#NotEmpty #FormDataParam("myParam") String myParam
This does not:
#FormDataParam("myParam") #NotEmpty String myParam
I too got the same exception.I did the following changes in web.xml
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.filter.LoggingFilter;org.glassfish.jersey.moxy.json.MoxyFeature;org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
and changed jersey 2.7 to 2.9 .I do not know what change of this 2 has solved the issue.
Register MultiPartFeature.
In web.xml add to the Jersey servlet:
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
Below code worked for me:
Class ->>> add it
Class Property --->> add it
Public Class userREST () {
#POST
#Path("upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_JSON)
public Response uploadImageFile(#FormDataParam("uploadFile") InputStream fileInputStream,
#FormDataParam("uploadFile") FormDataContentDisposition fileFormDataContentDisposition,
#FormDataParam("FIR_REG_NUM") String FIR_REG_NUM, #FormDataParam("LOGIN_ID") String LOGIN_ID) {
final_json_result = WriteFileInFolder.fileAnalysis(fileInputStream, fileFormDataContentDisposition, FIR_REG_NUM,
LOGIN_ID);
return Response.ok(final_json_result).build();
}// uploadImageFile
Public Class FileJAXRSConfig () {
package ####.jaxrs.jwt;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import ####.helper.Common###;
import ####.jaxrs.jwt.filters.JWTRequestFilter;
import ####.jaxrs.jwt.filters.JWTResponseFilter;
import ####.service.FileServicesREST;
#ApplicationPath("fileservice")
public class FileJAXRSConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Common###.logging("#ApplicationPath#FileServicesREST...");
Set<Class<?>> clazzes = new HashSet<Class<?>>();
clazzes.add(JWTRequestFilter.class);
clazzes.add(FileServicesREST.class);
clazzes.add(JWTResponseFilter.class);
return clazzes;
}
#Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("jersey.config.server.provider.packages", "####.service");
properties.put("jersey.config.server.provider.classnames", "org.glassfish.jersey.media.multipart.MultiPartFeature");
return properties;
}
}
Don't need to add following in web.xml
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>mha.###.service</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
If someone is using #FormDataParam with #ApiOperation swagger annotation, it won't work(as per swagger latest version at this time) as mentioned here:
https://github.com/swagger-api/swagger-ui/issues/169
I had this same problem with Scala and this helped me solve it. Just want to add some Scala specific details to help anyone using Dropwizard with Scala. Here is an example of how to "register" the MultiPartFeature in a Scala and Dropwizard project.
package org.research.s3.service
import io.dropwizard.Application
import io.dropwizard.setup.Environment
import org.research.s3.service.resource._
import org.research.service.s3.resource.UploadResource
import org.glassfish.jersey.media.multipart.{FormDataParam,MultiPartFeature}
class CmdaaApp() extends Application[CmdaaAppConfig] {
override def run(t: CmdaaAppConfig, env: Environment): Unit = {
env.jersey().register(new RootResource)
//Need this to make the file upload code work in
env.jersey().register(new MultiPartFeature)
env.jersey().register(new UploadResource(curBucket))
}
}
object CmdaaApp {
def main(args: Array[String]): Unit = new CmdaaApp().run(args: _*)
}
and here is the code for the UploadResource that does the upload:
package org.research.service.s3.resource
import java.io.{FileInputStream, InputStream}
import com.google.gson.{Gson, GsonBuilder}
import javax.ws.rs.core.MediaType.APPLICATION_JSON
import javax.ws.rs._
import javax.ws.rs.core.Response
import javax.ws.rs.core.MediaType
import org.research.util.OptionSerializer
import org.research.s3.service.resource.s3Bucket
import org.glassfish.jersey.media.multipart.{FormDataParam,MultiPartFeature}
#Path("/file")
class UploadResource(currentBucket: s3Bucket) {
val gsonb = new GsonBuilder()
gsonb.registerTypeAdapter(classOf[Option[Any]], new OptionSerializer)
val gson = gsonb.create
#POST
#Path("upload")
#Produces(Array(APPLICATION_JSON))
#Consumes(Array(MediaType.MULTIPART_FORM_DATA))
// def uploadFile(): Response = {
def uploadFile(#FormDataParam("file") uploadedInputStream: InputStream): Response = {
/* Need code here to get a uuid for the file name
Then return the uuid if we have success and of course 200
*/
Response.ok.entity(currentBucket.upload("testName",uploadedInputStream,false)).build()
//Response.ok().build()
}
}
This code refers to an s3 bucket but you don't need that. You can just replace that call with code do download your incoming file data to a regular file.
scala
I had the same problem when I tried to upload the file.
I spent a lot of time until I found a solution to the problem.
1.If you changed version of your JARs files you may have a version conflicts!
Clean up your artifacts/libs and rebuild project.
2.You need to register your UploadFileService class too:
register(MultiPartFeature.class);
register(UploadFileService.class);
Hope it will help someone and save your time.
in case you are getting this error while writing Dropwizard tests for the upload Resource this is the solution:
add dependency on dropwizard-forms
2.add this in the application file:
#Override
public void initialize(Bootstrap<ExampleConfiguration> bootstrap) {
bootstrap.addBundle(new MultiPartBundle());
}
in the test file add:
ResourceExtension.builder()
.addResource(new FileResource())
.addProvider(new MultiPartFeature())
.build();
I had a very similar problem and the answer that helped me was this https://stackoverflow.com/a/30407999/6801721
I was trying to use a user defined object as a query parameter and from the answer that's usually not allowed unless it meets some conditions.
In case someone comes across this in the future and is running into the same problem I was running into. Make sure that the annotations you are importing are from the correct packages. In my case I was importing javax.websocket.server.PathParam instead of javax.ws.rs.PathParam.

How to make webjars version agnostic in spring mvc

I have followed the documentation on their website as described here
First of all I added the required path
<mvc:resources mapping="/webjars/**" location="/webjars/"/>
then I created a controller with the following
#ResponseBody
#RequestMapping("/webjarslocator/{webjar}/**")
public ResponseEntity locateWebjarAsset(#PathVariable String webjar, HttpServletRequest request) {
try {
String mvcPrefix = "/webjarslocator/" + webjar + "/"; // This prefix must match the mapping path!
String mvcPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
String fullPath = assetLocator.getFullPath(webjar, mvcPath.substring(mvcPrefix.length()));
return new ResponseEntity(new ClassPathResource(fullPath), HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
Few dependencies were missing so I added in maven the following pom
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.28</version>
</dependency>
The above will import the following
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.core.io.ClassPathResource;
None of these has been imported from the external jar.
The error is: assetLocator cannot be resolved
EDIT: It could be that I need to create a filter rather than put it in a controller. Any thoughts on this?
The documentation is quite sparse, but you can create an instance of an asset locator with new WebJarAssetLocator().
Here's another solution, considering more recent versions of WebJar, in a similar vein for anyone else who stumbles upon this question. Using org.webjars.play.WebJarsUtil#locate(java.lang.String, java.lang.String) (which, in-turn, uses org.webjars.WebJarAssetLocator#getFullPath(java.lang.String, java.lang.String)) accepts the WebJar name (which acts as a scope) and the file without needing to provide a full path that necessitates including the version.

Invoke Struts Action Test from within a web app (JSF managed bean): TestCase.fname cannot be null

I have a Junit 3.8 test of a Struts 2 action that runs with no problems from my workspace (from eclipse: right click > run as > junit test).
For this, I use two plugins:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-junit-plugin</artifactId>
<version>2.1.8</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.1.8</version>
</dependency>
Here is the test class:
package com.myapp.user.my;
import org.apache.struts2.StrutsSpringTestCase;
import com.myapp.user.action.UserAction;
import com.opensymphony.xwork2.ActionProxy;
public class TestAccountActionUsingStrutsTestCase extends StrutsSpringTestCase {
public void testUserNameErrorMessage() throws Exception {
request.setParameter("userBean.userName", "Bruc");
request.setParameter("userBean.password", "test");
ActionProxy proxy = getActionProxy("/userAction");
UserAction userAction = (UserAction) proxy.getAction();
proxy.execute();
assertTrue("Problem There were no errors present in fieldErrors but there should have been one error present", userAction.getFieldErrors().size() == 1);
assertTrue("Problem field user.userName not present in fieldErrors but it should have been",
userAction.getFieldErrors().containsKey("userBean.userName") );
System.out.println("Finish 1 test.");
}
}
Next, I try to invoke this test, this time from within a web application (a JSF managed bean).
Here is my code for trying to do that (I'm calling the following runTest() method from a managed bean):
import java.util.List;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import com.myapp.user.my.TestAccountActionUsingStrutsTestCase;
public class CallStrutsActionExecuteThruTest {
public void runTest(){
System.out.println("CallStrutsActionExecuteThruTest.runTest() is executed.");
TestAccountActionUsingStrutsTestCase test = new TestAccountActionUsingStrutsTestCase();
JUnitCore jUnitCore = new JUnitCore();
Result result = jUnitCore.run(test);
List<Failure> list = result.getFailures();
for (Failure failure : list) {
System.out.println(failure.getMessage());
}
System.out.println("Test done!");
}
}
When I access the managed bean, I can see that runTest() is called. The first output CallStrutsActionExecuteThruTest.runTest() is executed. is printed to console. Strangely, the next outputs are not printed to console, although the debugger shows me they are executed.
Also, result.getFailures() returns a list with one element. As I said, its failure.getMessage() for some reason is not printed to console, but when I watch it in the debugger its value is TestCase.fname cannot be null.
* Even when I have only one method in my test class:
public void testTrue() throws Exception {
System.out.println("inside testTrue().");
assertTrue(true);
}
I still get the same results.
My questions are,
If I want to run the Struts action test from a JSF managed bean, am I using the Junit API correctly?
Why weren't the outputs that followed the first one printed to console?
How do I set TestCase.fname with a value? First I don't see a method in my test class to set this value. Second, from my understanding, fanme is the name of the test method in the test class that I want to call; and jUnitCore.run(test) should call all the test methods in the test class test, so how can I specify all these methods with only one fname parameter?
Download - you can download my project here. I use Maven, Eclipse, and deploy on Jboss 7.
I access the JSF managed bean by: http://localhost:8080/Struts2WithSpringDIIntegrationExampleJunitFromUI-1.0-SNAPSHOT/xhtml/hello.jsf
Struts2 tests don't work with raw parameters for some reason. Use parameterMap instead.
Map<String, String[]> parameterMap = new HashMap<String, String[]>();
parameterMap.put("userBean.userName", new String[]{"Bruc"});
parameterMap.put("userBean.password", new String[]{"test"});
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
request.setupGetServletPath("/userAction");
request.setParameterMap(parameterMap);

Resources