It is not possible to optimize the SOAP packet, the data is transmitted. What am I doing wrong?
Generated client classes using JBDS. I looked through a lot of examples it is not possible to implement the ability to transfer files outside the package:
</ SOAP-ENV: Envelope>
---- boundary388.5294117647058824932.470588235294118--
Content-Id: <1.B1150656.EC8A.4B5A.8835.A932E318190B>
Content-Transfer-Encoding: binary
CONTENT-TYPE: application / octet-stream
..........
I change the parameters, but it always turns out like this:
<ns2:AttachmentContentList>
<ns2:AttachmentContent>
<ns2:Id>request.zip</ns2:Id>
<ns2:Content>UEsDBBQACAg......
////
Client:
SMEVMessageExchangeService service1 = null;
SMEVMessageExchangePortType port1 = null;
try {
service1 = new SMEVMessageExchangeService(wsdlLocation, SERVICE);
boolean enabled = true;
int threshold = 10240;
port1 = service1.getSMEVMessageExchangeEndpoint(new MTOMFeature(enabled, threshold));//!!!!
.......
AttachmentContentList acList = new AttachmentContentList();
AttachmentContentType aContentType = new AttachmentContentType();
aContentType.setId("request.zip");
BindingProvider bp = (BindingProvider) port1;
javax.xml.ws.soap.SOAPBinding binding2 = (javax.xml.ws.soap.SOAPBinding) bp.getBinding();
binding2.setMTOMEnabled(true);
System.out.println("_____binding2.isMTOMEnabled() - "+binding2.isMTOMEnabled());
DataSource source = new FileDataSource(reqPthFile);
//DataHandler dh =new DataHandler(source,"application/octet-stream");
DataHandler dh =new DataHandler(source);
aContentType.setContent(dh);
//////
#MTOM(enabled=true)
#BindingType(value = javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_MTOM_BINDING)
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "AttachmentContentType", propOrder = {
"id",
"content"
})
public class AttachmentContentType {
#XmlElement(name = "Id", required = true)
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
#XmlID
#XmlSchemaType(name = "ID")
protected String id;
#MTOM(enabled=true)
#XmlElement(name = "Content", required = true)
#XmlMimeType("application/octet-stream")
protected DataHandler content;
public DataHandler getContent() {
return content;
}
public void setContent(DataHandler value) {
this.content = value;
}
///////
#MTOM(enabled=true)
#BindingType(value = javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_MTOM_BINDING)
#WebService(targetNamespace = "urn://x-artefacts-smev-gov-ru/services/message-exchange/1.2", name = "SMEVMessageExchangePortType")
#XmlSeeAlso({ru.it.smev.message_exchange.autogenerated.types.v1_2.ObjectFactory.class, ru.it.smev.message_exchange.autogenerated.types.fault.v1_2.ObjectFactory.class, ru.it.smev.message_exchange.autogenerated.types.basic.v1_2.ObjectFactory.class})
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface SMEVMessageExchangePortType {
///////
#MTOM(enabled=true)
#BindingType(value = javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_MTOM_BINDING)
#WebServiceClient(name = "SMEVMessageExchangeService",
targetNamespace = "urn://x-artefacts-smev-gov-ru/services/message-exchange/1.2")
public class SMEVMessageExchangeService extends Service {
Problem found.
MTOM stops working if handlerList is added.
Please tell me how you can use both handlerList and MTOM at the same time?
List<Handler> handlerList = binding.getHandlerChain();
// handlerList.add(new Handler1());
// handlerList.add(new Handler2());
handlerList.add(handler1);
handlerList.add(handler2);
binding.setHandlerChain(handlerList);
Related
I need to read content of message from the request body in WCF REST service like -
SERVICE SIDE CODE
string request = Encoding.UTF8.GetString(OperationContext.Current.RequestContext.RequestMessage.GetBody<byte[]>());
But I am getting an error on the service side, no matter what I try:
Expecting element 'base64Binary' from namespace 'http://schemas.microsoft.com/2003/10/Serialization/'.. Encountered 'Element' with name 'Human', namespace 'http://numans.hr-xml.org/2007-04-15'.
and the service contract is defined as:
//[OperationContract(Name = "LoadMessages", IsOneWay = true)]
[WebInvoke(Method = "POST",
UriTemplate = "/LoadMessages",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare)]
[Description("Inbound Message")]
void LoadMessages();
and the implementation is as:
public void LoadMessages()
{
string content = string.Empty;
//var request = OperationContext.Current.RequestContext.RequestMessage.GetBody<FileState>();
string request = Encoding.UTF8.GetString(OperationContext.Current.RequestContext.RequestMessage.GetBody<byte[]>());
}
CLIENT SIDE CODE
Content that I'm sending is:
string jsonData = "{ \"categoryid\":\"" + file.CategoryId + "\",\"fileId\":\"" + file.FileId + "\" }";
I tried many options to send data from the client like:
var buffer = System.Text.Encoding.UTF8.GetBytes(jsonData);
var content = new ByteArrayContent(buffer);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
and also tried this:
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
Posting request:
HttpResponseMessage executionResult = httpClient.PostAsync($"{url}/LoadMessages", content).Result;
I also tried serializing/de-serializing at client/server end, but that also is not working.
Can someone please suggest code samples what I can try that might work? Or point out what am I doing wrong.
A few more examples of what I tried with the JSON data :
var jsonData = JsonConvert.SerializeObject(data, Formatting.Indented);
var details = JObject.Parse(data);
Pasting my client side function for clarity:
HttpClient httpClient = new HttpClient(new HttpClientHandler());
HttpStatusCode statusCode = HttpStatusCode.OK;
string auditMessage = string.Empty;
using (httpClient)
{
var url = ConfigurationManager.AppSettings["APIURL"];
try
{
string jsonData = "{ \"categoryid\":\"" + file.CategoryId + "\",\"fileId\":\"" + file.FileId + "\" }";
//var jsonData = JsonConvert.SerializeObject(data, Formatting.Indented);
//var details = JObject.Parse(data);
//var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
var buffer = System.Text.Encoding.UTF8.GetBytes(jsonData);
var content = new ByteArrayContent(buffer);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage executionResult = httpClient.PostAsync($"{url}/LoadMessages", content).Result;
statusCode = executionResult.StatusCode;
if (statusCode == HttpStatusCode.Accepted)
{
file.Status = "Success";
}
}
catch (Exception ex)
{
}
}
Here is my demo:
This is the interface document of the service:
This is the request:
class Program
{
static void Main(string[] args)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:8012/ServiceModelSamples/service/user");
request.Method = "POST";
request.ContentType = "application/json;charset=UTF-16";
string Json = "{\"Email\":\"123\",\"Name\":\"sdd\",\"Password\":\"sad\"}";
request.ContentLength = Encoding.UTF8.GetByteCount(Json);
Stream myRequestStream = request.GetRequestStream();
StreamWriter myStreamWriter = new StreamWriter(myRequestStream, Encoding.GetEncoding("gb2312"));
myStreamWriter.Write(Json);
myStreamWriter.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
//myResponseStream.ResponseSoapContext
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
myResponseStream.Close();
Console.WriteLine(retString);
Console.ReadKey();
}
}
Feel free to let me know if the problem persists.
UPDATE
Define the Test class:
[DataContract]
public class Test {
[DataMember]
public string categoryid { get; set; }
[DataMember]
public string fileId { get; set; }
}
the implementation is as:
public void LoadMessages(Test test)
{
Test dataObject = OperationContext.Current.RequestContext.RequestMessage.GetBody<Test>(new DataContractJsonSerializer(typeof(Test)));
Console.WriteLine(dataObject.categoryid);
}
I have created an AEM servlet. Now I have created OSGi configuration (MULTI_FIELD as shown below of type array) with-in servlet itself because its defined as service also. Now, my requirement is how to access this osgi config inside doGet method. here is the code of servlet.
#Component(label = "Sample Servlet", description = "Sample Servlet", immediate = true, metatype = true)
#Service
#Properties(value = {
#Property(name = "sling.servlet.resourceTypes", value = {
GlobalConstants.RES_TYPE,
GlobalConstants.PAGE_RES_TYPE }, propertyPrivate =
true),
#Property(name = "sling.servlet.selectors", value = {
GlobalConstants.PAGES,
GlobalConstants.ASSETS }, propertyPrivate = true),
#Property(name = "sling.servlet.extensions", value = "xml",
propertyPrivate = true),
#Property(name = "sling.servlet.methods", value = { "GET" }) })
public class SampleServlet extends SlingAllMethodsServlet {
#Property(value={"English", "Hindi"}, unbounded =
PropertyUnbounded.ARRAY, label = "Subjects", cardinality = 50,
description = "Example for Multi field config")
private static final String MULTI_FIELD = "multifield";
#Override
protected void doGet(final SlingHttpServletRequest request, final
SlingHttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
You need to set the value of property to a member field within activate method:
#Activate
protected void activate(final BundleContext bundleContext,
final Map<String, Object> componentConfig) {
this.multiField = (String[]) componentConfig.get(MULTI_FIELD);
}
I didn't try the code myself but it can give some idea. You can check Sling Main Servlet here to see how it works: http://svn.apache.org/repos/asf/sling/tags/org.apache.sling.engine-2.2.6/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
I agree with Emin that this should be handled inside the activation method. But on 6.2 the overwritten method has only one parameter and I would use PropertiesUtil instead of the cast.
The method would look like:
#Activate
public void activate(final ComponentContext componentContext) {
final Dictionary<?, ?> props = componentContext.getProperties();
this.multiField = Arrays.asList(PropertiesUtil.toStringArray(props.get(MULTI_FIELD), new String[0]));
}
We are facing our REST API versioning and after having read a lot about the different options (URI versioning, mime type versioning) have decided to use the latter approach.
I was expecting that Springfox generates the following doc:
v1:
get /api/architecture/mails - application/vnd.arch.mails.v1+json
get /api/architecture/services - application/vnd.arch.service.v1+json
v2:
get /api/architecture/services - application/vnd.arch.service.v2+json
However, in the v2 I also get this:
get /api/architecture/services - application/vnd.arch.service.v1+json
It shouldn't be there since I configured the v2 Docklet with
.produces(new HashSet<String>(Arrays.asList(new String[]{"application/vnd.arch.service.v2+json"}))) so that it filters the services according to the versioned mime type. Why isn't is working?
Here is our springfox config:
#Bean
public Docket arqV1Api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.regex("/api/architecture/.*"))
.build()
.apiInfo(new ApiInfo("Architecture Rest Api","Architecture REST Services","v1","","","",""))
.produces(new HashSet<String>(Arrays.asList(new String[]{"application/vnd.arch.service.v1+json","application/vnd.arch.mail.v1+json"})))
.securitySchemes(newArrayList(apiKey()))
.securityContexts(newArrayList(securityContext()))
.groupName("Arq v1 group");
}
#Bean
public Docket arqV2Api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.regex("/api/architecture/.*"))
.build()
.apiInfo(new ApiInfo("Architecture Rest Api","Architecture REST Services","v2","","","",""))
.produces(new HashSet<String>(Arrays.asList(new String[]{"application/vnd.arch.service.v2+json"})))
.securitySchemes(newArrayList(apiKey()))
.securityContexts(newArrayList(securityContext()))
.groupName("Arq v2 group");
}
And these is the REST Controller:
private static final String serviceArqV1MediaType = "application/vnd.arch.service.v1+json";
private static final String serviceArqV2MediaType = "application/vnd.arch.service.v2+json";
private static final String mailsArqV1MediaType = "application/vnd.arch.mail.v1+json";
#ApiOperation(value = "Gets architecture services",
notes = "",
produces = serviceArqV1MediaType)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Request OK"),
#ApiResponse(code = 400, message = "Bad Request")})
#RequestMapping(value = {"/services"}, method = RequestMethod.GET,
produces = serviceArqV1MediaType)
public List<ServicioArquitectura> getServices() {
return Arrays.asList(new ServiceArch[]{new ServicioArquitectura("Support"), new ServicioArquitectura("Kickoff")});
}
#ApiOperation(value = "Gets architecture services",
notes = "",
produces = serviceArqV2MediaType)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Request OK"),
#ApiResponse(code = 400, message = "Bad Request")})
#RequestMapping(value = {"/services"}, method = RequestMethod.GET,
produces = {serviceArqV2MediaType})
public List<ServicioArquitecturaV2> getServicesV2() {
return Arrays.asList(new ServiceArchV2[]{new ServiceArchV2("Support", Boolean.TRUE), new ServiceArchV2("Kickoff", Boolean.FALSE)});
}
#ApiOperation(value = "Gets mails",
produces = mailsArqV1MediaType)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Request OK"),
#ApiResponse(code = 400, message = "Bad Request")})
#RequestMapping(value = {"/mails"}, method = RequestMethod.GET,
produces = {mailsArqV1MediaType})
public List<String> getMails() {
return Arrays.asList(new String[]{"xxxcompany.com"});
}
I opened an issue in Springfox's github and they pointed out how to correctly configure it. Here's the solution:
Helper static methods:
public static Predicate<RequestHandler> withMediaType(final MediaType[] mediaTypes){
return new Predicate<RequestHandler>() {
#Override
public boolean apply(RequestHandler input) {
if(mediaTypes!=null){
ProducesRequestCondition producesCondition = input.getRequestMapping().getProducesCondition();
Set<MediaType> producibleMediaTypes = producesCondition.getProducibleMediaTypes();
for (MediaType mt : producibleMediaTypes) {
for (int i = 0; i < mediaTypes.length; i++) {
if(mt.equals(mediaTypes[i])){
return true;
}
}
}
}
return false;
}
};
}
public static Set<String> mediaTypesToStringSet(MediaType[] mediaTypes){
Set<String> mediaTypesSet = new HashSet<String>();
if(mediaTypes!=null){
for (int i = 0; i < mediaTypes.length; i++) {
mediaTypesSet.add(mediaTypes[i].toString());
}
}
return mediaTypesSet;
}
Docket definitions:
#Bean
public Docket arqV1Api() {
MediaType[] validMediaTypes = new MediaType[]{new MediaType("application","vnd.arch.service.v1+json"),
new MediaType("application","vnd.arch.mails.v1+json")};
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(withMediaType(validMediaTypes))
.paths(PathSelectors.regex("/api/architecture/.*"))
.build()
.apiInfo(new ApiInfo("Architecture Rest Api","Architecture REST Services","v1","","","",""))
.produces(mediaTypesToStringSet(validMediaTypes))
.securitySchemes(newArrayList(apiKey()))
.securityContexts(newArrayList(securityContext()))
.groupName("Arq v1 group");
}
#Bean
public Docket arqV2Api() {
MediaType[] validMediaTypes = new MediaType[]{new MediaType("application","vnd.arch.service.v2+json")};
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(withMediaType(validMediaTypes))
.paths(PathSelectors.regex("/api/architecture/.*"))
.build()
.apiInfo(new ApiInfo("Architecture Rest Api","Architecture REST Services","v2","","","",""))
.produces(mediaTypesToStringSet(validMediaTypes))
.securitySchemes(newArrayList(apiKey()))
.securityContexts(newArrayList(securityContext()))
.groupName("Arq v2 group");
}
I am able to insert record and able index them but i am facing an exception while searching
org.hibernate.search.bridge.BridgeException: Exception while calling bridge#objectToString
class: com.edoors.formBean.Hib_cons_Cv
path: cons_cv
I am able search on all coulmn of table except blob column
Field Bridge
public class ByteArrayBridge implements TwoWayStringBridge {
public String objectToString(Object object) {
byte[] data = (byte[]) object;
StringWriter writer = new StringWriter();
InputStream is = null;
try {
is = new ByteArrayInputStream(data);
new AutoDetectParser().parse(is,new WriteOutContentHandler(writer),new Metadata(),new
ParseContext());
return is.toString();
} catch (Exception e) {
System.out.println("Exception "+e);
}
return writer.toString();
}
public Object stringToObject(String string) {
byte[] data=string.getBytes();
Object obj=data;
return obj;
}
}
DAO Class ::
public List searchConsultantByTitle(String jobtitle)
{
List list=null;
Session session = hiberUtil.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
FullTextSession fullTextSession = Search.getFullTextSession(session);
QueryBuilder queryBuilder =
fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Hib_cons_Cv.class).get();
org.apache.lucene.search.Query luceneQuery = null;
luceneQuery =
queryBuilder.keyword().fuzzy().withThreshold(0.7f).onField("cons_cv").matching(jobtitle).createQuery();
FullTextQuery hibernateQuery = fullTextSession.createFullTextQuery(luceneQuery, Hib_cons_Cv.class);
int resultSize = hibernateQuery.getResultSize();
System.out.println(".....resultSize..............................."+resultSize);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
POJO Class
#Entity
#AnalyzerDef(name = "customanalyzer", tokenizer = #TokenizerDef(factory =
KeywordTokenizerFactory.class), filters = {
#TokenFilterDef(factory = LowerCaseFilterFactory.class),
#TokenFilterDef(factory = SnowballPorterFilterFactory.class, params = {
#Parameter(name = "language", value = "English") }) })
#Indexed
public class Hib_cons_Cv {
#Column(name = "cons_cv", unique = false, nullable = false, length = 59296)
#Lob
#Field(analyze = Analyze.NO, store = Store.YES)
#FieldBridge(impl = ByteArrayBridge.class)
private Blob cons_cv;
//setters and getters
}
I also got this error (with no stack trace). Turned out i put in the wrong field name. It was actually using a field with no bridging.
I use org.apache.commons.fileupload to upload file
class StorageService is a service that use cloud storage APIs to store file
This is my code
public class UploadFileAction extends org.apache.struts.action.Action {
private static final String SUCCESS = "success";
private StorageService storage = new StorageService();
private static final int BUFFER_SIZE = 1024 * 1024;
#Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = iter.next();
String fileName = item.getName();
String mime = item.getContentType();
storage.init(fileName, mime);
InputStream is = item.openStream();
byte[] b = new byte[BUFFER_SIZE];
int readBytes = is.read(b, 0, BUFFER_SIZE);
while (readBytes != -1) {
storage.storeFile(b, BUFFER_SIZE);
readBytes = is.read(b, 0, readBytes);
}
is.close();
storage.destroy();
}
return mapping.findForward(SUCCESS);
}
}
package storageservice;
import com.google.appengine.api.files.*;
import com.google.appengine.api.files.GSFileOptions.GSFileOptionsBuilder;
import java.io.*;
import java.nio.channels.Channels;
public class StorageService {
private static final String BUCKET_NAME = "thoitbk";
private FileWriteChannel writeChannel = null;
private OutputStream os = null;
public void init(String fileName, String mime) throws Exception {
FileService fileService = FileServiceFactory.getFileService();
GSFileOptionsBuilder builder = new GSFileOptionsBuilder()
.setAcl("public_read")
.setBucket(BUCKET_NAME)
.setKey(fileName)
.setMimeType(mime);
AppEngineFile writableFile = fileService.createNewGSFile(builder.build());
boolean lock = true;
writeChannel = fileService.openWriteChannel(writableFile, lock);
os = Channels.newOutputStream(writeChannel);
}
public void storeFile(byte[] b, int readSize) throws Exception {
os.write(b, 0, readSize);
os.flush();
}
public void destroy() throws Exception {
os.close();
writeChannel.closeFinally();
}
}
In local this works fine but error when I deploy my app
Please help me!
Make sure your app's service account has WRITE access to the bucket in question, either by adding the service account to the team with can edit rights or else update the bucket acl to explicitly grant the service account WRITE access. See this question for more details.