I want to send a byte array from a web service to a client that requests an operation exposed via the service. In my method, I read an image into a byte array. I think place this byte array into a wrapper POJO. This is the return type for the operation.
#Override
public ImageWrapper getImage() {
File imageFile = new File("C:\\images\\car.jpg");
ImageWrapper wrapper = null;
try {
BufferedImage img = ImageIO.read(imageFile);
ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
ImageIO.write(img, "jpg", baos);
baos.flush();
byte[] result = baos.toByteArray();
baos.close();
wrapper = new ImageWrapper();
wrapper.setContent(result);
System.out.println("Service image wrapper: " + wrapper);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return wrapper;
}
I can receive the ImageWrapper object in the client ok. It has a different id to the ImageWrapper instance that is created by the web service on the server, as I would expect. But, the problem is that when I try to get the byte[] array from the ImageWrapper, it is null... Any ideas why? The wrapper class looks like:
package soap.service.model;
public class ImageWrapper {
private byte[] content;
public void setContent(byte[] content) {
this.content = content;
}
public byte[] getImg() {
return this.content;
}
}
and the client looks like:
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import soap.service.model.ImageWrapper;
import soap.service.sei.ImageSei;
public class ImageClient {
public static void main(String... args) throws MalformedURLException {
URL url = new URL("http://localhost:8080/image?wsdl");
QName qname = new QName("http://impl.service.soap/", "ImageImplService");
Service service = Service.create(url, qname);
ImageSei sei = service.getPort(ImageSei.class);
ImageWrapper iw = sei.getImage();// This is ok
System.out.println(iw.getImg()); // * This is null
}
}
========================================================================
Update Even if I change the byte array in ImageWrapper to a String, it
still comes back as 'null' in the client. I have my web service set to use
'Document' style also.
Your interface object (the one getting serialized and being transfered) does not contain public data (only a method to get private data). Your byte[] should be a public field or property to be included in the serialized data
Related
I have written a code in java that reads the ontology and print the triplets. the code is working fine. i want to hide the URI's in output and also print the output in the tree hierarchy form. Currently it gives me output in lines. Any idea how can i do this.
Tree Form Like:
Thing
Class
SubClass
Individual
so on ...
this is the ReadOntology class, this class i use in servlet.
public class ReadOntology {
public static OntModel model;
public static void run(String ontologyInFile) {
model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
InputStream ontologyIn = FileManager.get().open(ontologyInFile);
loadModel(model, ontologyIn);
}
protected static void loadModel(OntModel m, InputStream ontologyIn) {
try {
m.read(ontologyIn, "RDF/XML");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
this is the servlet
public class Ontology extends HttpServlet{
OntClass ontClass = null;
public void service(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException
{
PrintWriter out = res.getWriter();
ServletContext context = this.getServletContext();
String fullPath = context.getRealPath("/WEB-INF/Data/taxi.owl");
ReadOntology.run(fullPath);
SimpleSelector selector = new SimpleSelector(null, null, (RDFNode)null);
StmtIterator iter = ReadOntology.model.listStatements(selector);
while(iter.hasNext()) {
Statement stmt = iter.nextStatement();
out.print(stmt.getSubject().toString());
out.print(stmt.getPredicate().toString());
out.println(stmt.getObject().toString());
}
}
}
As one step towards your goal, this groups the statements by subject, and for the predicates only shows the local name:
ResIterator resIt = ReadOntology.model.listSubjects()
while (resIt.hasNext()) {
Resource r = resIt.nextResource();
out.println(r);
StmtIterator iter = r.listProperties();
while (iter.hasNext()) {
Statement stmt = iter.nextStatement();
out.print(" ");
out.print(stmt.getPredicate().getLocalName());
out.println(stmt.getObject());
}
}
There are lots of useful methods in the API for Resource and Model.
To render a full class tree, use the methods on OntModel and OntClass. Perhaps:
private void printClass(Writer out, OntClass clazz, int indentation) {
String space = ' '.repeat(indentation);
// print space + clazz.getLocalName()
...
// iterate over clazz.listSubClasses(true)
// and call printClass for each with indentation increased by 1
...
// iterator over clazz.listInstances()
// and print all their properties as in the
// snippet above but with space added
}
Then in the service method, iterate over the OntModel's classes, and for any where hasSuperClass() is false, call printClass(out, clazz, 0).
I have written code for accessing GCS bucket to store files thru API in java which takes JSON credential file. I have created that JSON file from google console. I need to automate the JSON file or key rotation for every 90 days. How to regenerate/rotate that JSON file? I am a newbie to GCS.
import java.io.IOException;
import java.security.GeneralSecurityException;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpMethods;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.iam.v1.Iam;
import com.google.api.services.iam.v1.IamRequest;
import com.google.api.services.iam.v1.IamRequestInitializer;
import com.google.api.services.iam.v1.model.CreateServiceAccountKeyRequest;
public class TestServiceAccount {
public static void main(String[] args) {
// TODO Auto-generated method stub
//ServiceAccountKey key = new ServiceAccountKey();
try {
System.out.println("created");
String KEY = "AIzaSyDjHg2u4bwfvncb_YwdjJC_vUPRYLW5Sh8";
IamRequestInitializer req = new IamRequestInitializer(KEY);
HttpTransport transport;
transport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = new JacksonFactory();
Iam iam = new Iam(transport,jsonFactory,new HttpRequestInitializer() {
public void initialize(HttpRequest httpRequest) {
httpRequest.setConnectTimeout(0);
httpRequest.setReadTimeout(0);
}
});
//https://iam.googleapis.com/v1/projects/newsampleproject/serviceAccounts/NewServiceAccount/keys
MyIamRequest<String> request = new MyIamRequest<String>(
iam, HttpMethods.POST, "/v1/projects/newsampleproject/serviceAccounts/NewServiceAccount/keys", String.class, String.class);
req.initialize(request);
System.out.println(req.getKey());
req.initializeJsonRequest(request);
System.out.println(req.getUserIp());
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
//req.initializeJsonRequest(request);
}
public static HttpRequestFactory createRequestFactory(HttpTransport transport) {
return transport.createRequestFactory(new HttpRequestInitializer() {
public void initialize(HttpRequest request) throws IOException {
}
});
}
}
This what I have written to call the API But i am not sure if this is the way to call it.
try this solution, it worked for me
private static void createNewKey(IamRequestInitializer req) throws IOException, GeneralSecurityException {
Iam iam = jsonAuthentication();
CreateServiceAccountKeyRequest keyRequest = new CreateServiceAccountKeyRequest();
keyRequest.setKeyAlgorithm(KEY_ALGO);
String account = SERVICE_ACCOUNT_URL + SERVICE_ACCOUNT_EMAIL;
iam.projects().serviceAccounts().keys().create(account, keyRequest);
String requestString = BASE_URL + SERVICE_ACCOUNT_EMAIL + KEY;
ServiceAccountKey result = getServiceAccountKey(req, iam, requestString);
String jsonKey = new String(result.decodePrivateKeyData());
System.out.println(jsonKey);
JsonFileUtil.createFile(JSON_KEY_FILE_NAME, jsonKey);
}
private static <T> T getServiceAccountKey(IamRequestInitializer req, Iam iam, String requestString)
throws IOException {
MyIamRequest<String> request = new MyIamRequest<String>(iam, HttpMethods.POST, requestString, String.class,
ServiceAccountKey.class);
request.setKey(API_KEY);
request.setFields(
"keyAlgorithm,name,privateKeyData,privateKeyType,publicKeyData,validAfterTime,validBeforeTime");
req.initializeJsonRequest(request);
System.out.println(request.getRequestHeaders());
return (T) request.execute();
}
If you're using a JSON credential file, you are acting as some particular service account which is a member of your project and has access to the files.
Service accounts can be programmatically controlled for exactly this sort of use case. The IAM Service Account API controls service accounts, and the two methods you want for key rotation are serviceAccount.keys.create() and serviceAccount.keys.delete().
The result of the create() call (if you pass in the private key type TYPE_GOOGLE_CREDENTIALS_FILE), will be a new, valid JSON credential file for your service account.
#user7049946
ServiceAccountKey response = getServiceAccountKey(req, iam, requestString);
CreateNewJson.createFile("NEW_JSON_KEY_FILE_NAME", new String(response.decodePrivateKeyData()));
create new class to convert that conent into new file.
public class CreateNewJson {
public static void createFile(String filename, String content) throws IOException {
FileOutputStream fileOutputStream = null;
File file;
file = new File(filename);
fileOutputStream = new FileOutputStream(file);
if (!file.exists()) {
file.createNewFile();
}else{
file.delete();
file.createNewFile();
}
byte[] contentInBytes = content.getBytes();
fileOutputStream.write(contentInBytes);
fileOutputStream.flush();
fileOutputStream.close();
System.out.println("File Created");
}
}
I am using Apache HttpClient to put/get customized object using REST APIs. Below is the sample code. My putObject() method works fine and I could serialize Person object and put properly. However, while getting the object, I got below error:
Exception in thread "main" java.lang.ClassCastException: [B cannot be cast to Person at MyTest.demoGetRESTAPI(MyTest.java:88) at MyTest.main(MyTest.java:21)
Seems the code to build Person object out of response entity is not correct
HttpEntity httpEntity = response.getEntity();
byte[] resultByteArray = EntityUtils.toByteArray(httpEntity);
Person person = (Person)SerializationUtils.deserialize(resultByteArray);
Am I doing somthing wrong while getting byte[] array and converting to Person object. Please help me out to solve this issue.
Complete Example Program:
import java.io.Serializable;
import org.apache.commons.lang.SerializationUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.SerializableEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
public class MyTest {
public static void main(String[] args) throws Exception {
putObject();
getObject();
}
public static void putObject() throws Exception
{
HttpClient httpClient = new DefaultHttpClient();
Person person = new Person();
person.setName("Narendra");
person.setId("1");
try
{
//Define a postRequest request
HttpPut putRequest = new HttpPut("http://localhost:9084/ehcache-server/rest/screeningInstance/2221");
//Set the API media type in http content-type header
putRequest.addHeader("content-type", "application/x-java-serialized-object");
//Set the request put body
SerializableEntity personSEntity = new SerializableEntity(SerializationUtils.serialize(person));
putRequest.setEntity(personSEntity);
//Send the request; It will immediately return the response in HttpResponse object if any
HttpResponse response = httpClient.execute(putRequest);
//verify the valid error code first
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 201)
{
throw new RuntimeException("Failed with HTTP error code : " + statusCode);
}
}
finally
{
//Important: Close the connect
httpClient.getConnectionManager().shutdown();
}
}
public static void getObject() throws Exception
{
DefaultHttpClient httpClient = new DefaultHttpClient();
try
{
//Define a HttpGet request; You can choose between HttpPost, HttpDelete or HttpPut also.
//Choice depends on type of method you will be invoking.
HttpGet getRequest = new HttpGet("http://localhost:9084/ehcache-server/rest/screeningInstance/2221");
//Set the API media type in http accept header
getRequest.addHeader("accept", "application/x-java-serialized-object");
//Send the request; It will immediately return the response in HttpResponse object
HttpResponse response = httpClient.execute(getRequest);
//verify the valid error code first
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200)
{
throw new RuntimeException("Failed with HTTP error code : " + statusCode);
}
//Now pull back the response object
HttpEntity httpEntity = response.getEntity();
byte[] resultByteArray = EntityUtils.toByteArray(httpEntity);
Person person = (Person)SerializationUtils.deserialize(resultByteArray);
}
finally
{
//Important: Close the connect
httpClient.getConnectionManager().shutdown();
}
}
}
class Person implements Serializable{
String name;
String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Override
public String toString() {
return "Person [name=" + name + ", id=" + id + "]";
}
}
I got the solution. It was mistake in my code:
While putting object, I have written below code. That was doing two time serialization. First from Person object to byte[] and second from byte[] to byte[].
SerializableEntity personSEntity = new SerializableEntity(SerializationUtils.serialize(person));
putRequest.setEntity(personSEntity);
This is the right approach:
SerializableEntity personSEntity = new SerializableEntity(person);
putRequest.setEntity(personSEntity);
After getting binary from REST, code should be like below to get Object:
HttpEntity httpEntity = response.getEntity();
InputStream inputStream = null;
try {
inputStream = httpEntity.getContent();
Person p = (Person) SerializationUtils.deserialize(inputStream);
System.out.println("Person:" + p.getName());
}
finally {
inputStream.close();
}
This worked like CHARM !!
I'm trying to send serialize class object on the server side. First I serialize object in byte array, then I take array length and send lenght as integer and send array on the srever side. But programm fold with NullPointerException in stacktrace. All class-fields is static. What a problem?
public class Main {
public static int port = 8085;
public static String address = "127.0.0.1";
public static Socket clientSocket;
public static InputStream in;
public static OutputStream out;
public static DataInputStream din;
public static DataOutputStream dout;
public static boolean stop = false;
public static int l;
public Main(){
try {
InetAddress ipAddress = InetAddress.getByName(address);
clientSocket = new Socket(ipAddress, port);
in = clientSocket.getInputStream();
out = clientSocket.getOutputStream();
din = new DataInputStream(in);
dout = new DataOutputStream(out);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
int number = 5;
String str = "Hello world!";
byte[] bt = str.getBytes();
ArrayList<Byte> array = new ArrayList<Byte>();
for(int i=0; i<bt.length; i++){
array.add(bt[i]);
}
while(!stop){
Template protocol = new Template(number, str, array);
byte[] serializeObject = SerializationUtils.serialize(protocol);
l = serializeObject.length;
try {
dout.writeInt(l); //NPE
dout.write(serializeObject); //NPE
dout.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
You're invoking the static field dout without it being initialized. By default, Java object references are initialized to null. The code that initializes those fields is in the constructor, which is not being called since you're inside the static main() method, which is not tied to an instance. So your reference is still null, hence the NullPointerException when you invoke your dout.writeInt(l);.
Unless you explicitly create a Main() instance, as in Main myMain = new Main();, your main method needs to initialize your dout reference, since it's null.
Since this seems more like a simple communication test, just move the initialization code in the constructor to your main method.
I am making a Silverlight app using WCF. I want to get the status of the hard-disks from remote servers and I am able to do that on the server side using a Management object. I have defined a wrapper class to hold the data of the hard-disks and store the objects in a list which I return.
Earlier, when the wrapper class was in the server project, it worked fine. However, when I transferred the class to a class library project in the same solution, the asynchronous call-completed event handler on the client side now gives me an event argument that is empty, i.e. an empty list
I tried debugging both the server and client code, and I see that the server creates the list properly and accesses the disk objects nicely. But the client code simply shows the list to be of size 0.
My client code is:
private void getDiskStatus()
{
diskSpaceStatus.Text = "Running...";
if (server == string.Empty)
{
server = "localhost";
}
diskServer.Text = server;
LogReaderClient proxy = new LogReaderClient();
proxy.getDiskSpaceCompleted += new EventHandler<getDiskSpaceCompletedEventArgs>(proxy_getDiskSpaceCompleted);
proxy.getDiskSpaceAsync(server);
}
void proxy_getDiskSpaceCompleted(object sender, getDiskSpaceCompletedEventArgs e)
{
diskSpaceStatus.Text = "Completed";
try
{
List<uDisk> udisks = new List<uDisk>();
foreach (Disk d in e.Result)
{
uDisk ud = new uDisk(d);
udisks.Add(ud);
}
diskTable.ItemsSource = udisks;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Where uDisk is another wrapper class for the client side.
My server code is:
[OperationContract]
public List<Disk> getDiskSpace(string server)
{
ConnectionOptions conn = new ConnectionOptions();
ManagementScope scope = new ManagementScope("\\\\" + server + "\\root\\cimv2", conn);
try
{
scope.Connect();
}
catch (Exception ex)
{
error = ex.Message;
}
ObjectQuery oq = new ObjectQuery("select FreeSpace, Size, Name from Win32_LogicalDisk where DriveType=3");
ManagementObjectSearcher search = new ManagementObjectSearcher(scope, oq);
ManagementObjectCollection moc = search.Get();
List<Disk> disks = new List<Disk>();
Disk d;
foreach (ManagementObject mo in moc)
{
d = new Disk(mo);
disks.Add(d);
}
return disks;
}
And the server wrapper class is:
namespace LogFilter.DataObjects
{
[DataContract]
public class Disk
{
[DataMember]
public string name;
[DataMember]
public double freeSpace;
[DataMember]
public double size;
[DataMember]
public double percentFree;
public Disk()
{}
public Disk(ManagementObject mo)
{
this.name = Convert.ToString(mo["Name"]);
this.freeSpace = Convert.ToDouble(mo["FreeSpace"]);
this.size = Convert.ToDouble(mo["Size"]);
this.percentFree = freeSpace * 100 / size;
}
}
}
The wrapper class is in the namespace LogFilter.DataObjects and the Server code is in the namespace LogFilter.Web.
Can anyone provide a solution to this?
Also can someone please give me a resource as to how to set the transfermode in a Silverlight application to Buffered?