i created an app, that should receive data from my thingspeak channel.
First i just used the webview widget, but i want to go further and use the thingspeak java api to handle the data by myself.
In MainActivity i just put in the code :
Channel channel = new Channel(1234,"writeKey");
try {
Entry entry = channel.getLastChannelEntry();
} catch (UnirestException e) {
e.printStackTrace();
} catch (ThingSpeakException e) {
e.printStackTrace();
}
out.println("entry");
but i get the following error:
java.lang.RuntimeException: Unable to start activity ComponentInfo{de.babytemp.babytempapp2/de.babytemp.babytempapp2.MainActivity}: java.lang.IllegalArgumentException: Unknown pattern character 'X'
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.IllegalArgumentException: Unknown pattern character 'X'
at java.text.SimpleDateFormat.validatePatternCharacter(SimpleDateFormat.java:314)
at java.text.SimpleDateFormat.validatePattern(SimpleDateFormat.java:303)
at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:356)
at com.google.gson.DefaultDateTypeAdapter.<init>(DefaultDateTypeAdapter.java:49)
at com.google.gson.GsonBuilder.addTypeAdaptersForDate(GsonBuilder.java:555)
at com.google.gson.GsonBuilder.create(GsonBuilder.java:543)
at de.babytemp.babytempapp2.Channel.<init>(Channel.java:46)
at de.babytemp.babytempapp2.MainActivity.onCreate(MainActivity.java:41)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Thanks!
package de.babytemp.babytempapp2;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.mashape.unirest.request.GetRequest;
import java.util.HashMap;
public class Channel {
private String APIURL = "http://api.thingspeak.com";
private static final String APIHEADER = "XXXXXXXXX";
private final Integer channelId;
private String readAPIKey;
private String writeAPIKey;
private final Boolean isPublic;
private final HashMap<String, Object> fields = new HashMap<>();
private final Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create();
/**
* Constructor for a public, read-only, Thingspeak channel. This type of
* channel cannot be updated.
*
* #param channelId Channel Id.
*/
public Channel(Integer channelId) {
this.isPublic = true;
this.channelId = channelId;
}
/**
* Constructor for a public, writeable, Thingspeak channel.
*
* #param channelId Channel Id.
* #param writeKey API Key for the channel. See
* https://thingspeak.com/channels/<channelId>#apikeys
*/
public Channel(Integer channelId, String writeKey) {
this.isPublic = true;
this.channelId = channelId;
this.writeAPIKey = writeKey;
}
/**
* Constructor for a private, writeable, Thingspeak channel.
*
* #param channelId Channel Id.
* #param writeKey Write API Key. See
* https://thingspeak.com/channels/<channelId>#apikeys.
* #param readKey Read API Key. See
* https://thingspeak.com/channels/<channelId>#apikeys.
*/
public Channel(Integer channelId, String writeKey, String readKey) {
this.channelId = channelId;
this.readAPIKey = readKey;
this.writeAPIKey = writeKey;
this.isPublic = false;
}
/**
* Make GET requests to the Thingspeak API without additional feed
* parameters.
*
* #param url The API url.
* #return JSON string.
* #throws UnirestException The request cannot be made.
* #throws ThingSpeakException The request is invalid.
*/
private String thingRequest(String url) throws UnirestException, ThingSpeakException {
GetRequest request = Unirest.get(url);
if (!this.isPublic) {
request.field("key", this.readAPIKey);
}
HttpResponse<JsonNode> response = request.asJson();
if (response.getCode() != 200) {
throw new ThingSpeakException("Request failed with code " + response.getCode());
}
return response.getBody().toString();
}
/**
* Make GET requests to the Thingspeak API with additional feed parameters.
*
* #param url The API url.
* #param options Optional feed parameters.
* #return JSON string.
* #throws UnirestException The request cannot be made.
* #throws ThingSpeakException The request is invalid.
*/
private String thingRequest(String url, FeedParameters options) throws UnirestException, ThingSpeakException {
GetRequest request = Unirest.get(url);
if (!this.isPublic) {
request.field("key", this.readAPIKey);
}
request.fields(options.fields);
HttpResponse<JsonNode> response = request.asJson();
if (response.getCode() != 200) {
throw new ThingSpeakException("Request failed with code " + response.getCode());
}
return response.getBody().toString();
}
/**
* Use a server other than thingspeak.com. If you are hosting your own
* Thingspeak server, set the url of the server here. The url of the public
* Thingspeak server is http://api.thingspeak.com
*
* #param url eg. http://localhost, http://thingspeak.local:3000, etc.
*/
public void setUrl(String url) {
this.APIURL = url;
}
/**
* Update channel with new data.
*
* #param entry The new data to be posted.
* #return The id of the new entry.
* #throws UnirestException The request cannot be made.
* #throws ThingSpeakException The request is invalid.
*/
public Integer update(Entry entry) throws UnirestException, ThingSpeakException {
HttpResponse<String> response = Unirest.post(APIURL + "/update")
.header(APIHEADER, this.writeAPIKey)
.header("Connection", "close")
.fields(entry.getUpdateMap())
.asString();
if (response.getCode() != 200) {
throw new ThingSpeakException("Request failed with code " + response.getCode());
} else if (response.getBody().equals("0")) {
throw new ThingSpeakException("Update failed.");
}
return Integer.parseInt(response.getBody());
}
/**
* Get a channel feed with default feed options. Does not include location or status info. Only fields that
* have been named in the channel's settings (via the web) will be returned.
*
* #return Feed for this channel.
* #throws UnirestException The request cannot be made.
* #throws ThingSpeakException The request is invalid.
*/
public Feed getChannelFeed() throws UnirestException, ThingSpeakException {
String url = APIURL + "/channels/" + this.channelId + "/feed.json";
return gson.fromJson(thingRequest(url), Feed.class);
}
/**
* Get a channel feed with additional feed options. Only fields that have been named in
* the channel's settings (via the web) will be returned.
*
* #param options Additional feed parameters.
* #return Feed for this channel.
* #throws UnirestException The request cannot be made.
* #throws ThingSpeakException The request is invalid.
*/
public Feed getChannelFeed(FeedParameters options) throws UnirestException, ThingSpeakException {
String url = APIURL + "/channels/" + this.channelId + "/feed.json";
return gson.fromJson(thingRequest(url, options), Feed.class);
}
/**
* Get last entry in this channel with default feed options. This is a
* faster alternative to getting a Channel Feed and then calling
* {#link Feed#getChannelLastEntry()}.
*
* #return Entry.
* #throws UnirestException The request cannot be made.
* #throws ThingSpeakException The request is invalid.
*/
public Entry getLastChannelEntry() throws UnirestException, ThingSpeakException {
String url = APIURL + "/channels/" + this.channelId + "/feed/last.json";
return gson.fromJson(thingRequest(url), Entry.class);
}
/**
* Get last entry in this channel with additional feed options. This is a
* faster alternative to getting a Channel Feed and then calling
* {#link Feed#getChannelLastEntry()}
*
* #param options
* #return Entry.
* #throws UnirestException The request cannot be made.
* #throws ThingSpeakException The request is invalid.
*/
public Entry getLastChannelEntry(FeedParameters options) throws UnirestException, ThingSpeakException {
String url = APIURL + "/channels/" + this.channelId + "/feed/last.json";
return gson.fromJson(thingRequest(url, options), Entry.class);
}
/**
* Get a field feed with default feed options.
*
* #param fieldId The field to include in the field (1-8).
* #return Feed.
* #throws UnirestException The request cannot be made.
* #throws ThingSpeakException The request is invalid.
*/
public Feed getFieldFeed(Integer fieldId) throws UnirestException, ThingSpeakException {
String url = APIURL + "/channels/" + this.channelId + "/field/" + fieldId + ".json";
return gson.fromJson(thingRequest(url), Feed.class);
}
/**
* Get a field feed with additional feed options.
*
* #param fieldId The field to include in the field (1-8).
* #param options Optional parameters that control the format of the feed.
* #return Feed.
* #throws UnirestException The request cannot be made.
* #throws ThingSpeakException The request is invalid.
*/
public Feed getFieldFeed(Integer fieldId, FeedParameters options) throws UnirestException, ThingSpeakException {
String url = APIURL + "/channels/" + this.channelId + "/field/" + fieldId + ".json";
return gson.fromJson(thingRequest(url, options), Feed.class);
}
/**
* Get the last entry in a field feed with default feed options.
*
* #param fieldId The field to return (0-8).
* #return Last entry for the specified field.
* #throws UnirestException The request cannot be made.
* #throws ThingSpeakException The request is invalid.
*/
public Entry getLastFieldEntry(Integer fieldId) throws UnirestException, ThingSpeakException {
String url = APIURL + "/channels/" + this.channelId + "/field/" + fieldId + "/last.json";
return gson.fromJson(thingRequest(url), Entry.class);
}
/**
* Get the last entry in a field feed with additional feed options.
*
* #param fieldId The field to return (0-8).
* #param options Supported options: offset, status, and location.
* #return Last entry for the specified field.
* #throws UnirestException The request cannot be made.
* #throws ThingSpeakException The request is invalid.
*/
public Entry getLastFieldEntry(Integer fieldId, FeedParameters options) throws UnirestException, ThingSpeakException {
String url = APIURL + "/channels/" + this.channelId + "/field/" + fieldId + "/last.json";
return gson.fromJson(thingRequest(url, options), Entry.class);
}
/**
* Get channel status updates. Uses the default feed options.
*
* #return Status feed.
* #throws UnirestException The request cannot be made.
* #throws ThingSpeakException The request is invalid.
*/
public Feed getStatusFeed() throws UnirestException, ThingSpeakException {
String url = APIURL + "/channels/" + this.channelId + "/status.json";
return gson.fromJson(thingRequest(url), Feed.class);
}
/**
* Get channel status updates.
*
* #param options Only {#link FeedParameters#offset(java.lang.Integer)} is
* supported.
* #return Status feed.
* #throws UnirestException The request cannot be made.
* #throws ThingSpeakException The request is invalid.
*/
public Feed getStatusFeed(FeedParameters options) throws UnirestException, ThingSpeakException {
String url = APIURL + "/channels/" + this.channelId + "/status.json";
return gson.fromJson(thingRequest(url, options), Feed.class);
}
}
Please try
private final Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create();
to
private final Gson gson = new GsonBuilder().setDateFormat(java.text.DateFormat.LONG).create()
FATAL EXCEPTION: main
Process: de.babytemp.babytempapp2, PID: 8731
java.lang.NoSuchFieldError: No static field INSTANCE of type Lorg/apache/http/message/BasicLineFormatter; in class Lorg/apache/http/message/BasicLineFormatter; or its superclasses (declaration of 'org.apache.http.message.BasicLineFormatter' appears in /system/framework/ext.jar)
at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:52)
at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:56)
at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<clinit>(DefaultHttpRequestWriterFactory.java:46)
at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:72)
at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:84)
at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<clinit>(ManagedHttpClientConnectionFactory.java:59)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager$InternalConnectionFactory.<init>(PoolingHttpClientConnectionManager.java:487)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:147)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:136)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:112)
at org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:727)
at com.mashape.unirest.http.options.Options.refresh(Options.java:41)
at com.mashape.unirest.http.options.Options.<clinit>(Options.java:27)
at com.mashape.unirest.http.HttpClientHelper.prepareRequest(HttpClientHelper.java:142)
at com.mashape.unirest.http.HttpClientHelper.request(HttpClientHelper.java:119)
at com.mashape.unirest.request.BaseRequest.asString(BaseRequest.java:52)
at de.babytemp.babytempapp2.Channel.update(Channel.java:149)
at de.babytemp.babytempapp2.MainActivity.onCreate(MainActivity.java:47)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Related
Whenevr i m trying to do it in plain sql command then it is working but when i try it throgh java it notworking.only a blank table is created with no data?
DELIMITER $$
CREATE PROCEDURE `create_tb_tw`(IN tableName varchar(255),IN x varchar(255),IN y varchar(255))
BEGIN
SET #sql = CONCAT('CREATE TABLE ',tableName,' SELECT * FROM emp
WHERE hiredate >= ',x,'
AND hiredate <= ',y);
PREPARE s FROM #sql;
EXECUTE s;
DEALLOCATE PREPARE s;
END $$
DELIMITER;
call create_tb_tw("x","'1980-12-17'","'1981-02-22'");//working
public class emdetails extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
//db connection
Connection con = DbConnection.getcon();
String Sdate = request.getParameter("Sdate");
String Edate = request.getParameter("Edate");
String TName = request.getParameter("TName");
try {
CallableStatement cStmt = con.prepareCall("{call create_tb_tw(?, ?,?)}");
cStmt.setString(1, TName);
cStmt.setString(2, Sdate);
cStmt.setString(3, Edate);
cStmt.executeQuery();
}
} catch (SQLException ex) {
// System.out.println(emdetails.class.getName()).log(Level.SEVERE, null, ex);
Logger.getLogger(emdetails.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
#Override
protected void doGet(HttpServletReq`enter code heenter code herere`uest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* #return a String containing servlet description
*/
#Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
Whenevr i m trying to do it in plain sql command then it is working but when i try it throgh java it notworking.only a blank table is created with no data?
You need to quote the dates
call create_tb_tw("t","'2014-01-01'","'2017-12-31'");
Has anyone tried integrating there java code from CCU V2 to CCU V3 with fast purge. I read the documentation but unable to understand what needs to be done in case of a java based project. After we have configured the client in Akamai console how do we write the code to access and clear.
Any help is highly appreciated.
Thanks,
Tushar
The general approach is to write some code that makes an HTTP request to the fast purge endpoint.
Here is some an example:
import com.akamai.edgegrid.auth.*;
//other imports
public void callAkamaiFastPurgeForUrls(Set<String> urlsToPurge) throws URISyntaxException, IOException, RequestSigningException {
if(!urlsToPurge.isEmpty()) {
int status;
String json = getPurgeJson(urlsToPurge);
HttpRequest signedRequest = getHttpRequest(json, compProperty);
HttpResponse response = signedRequest.execute();
status = response.getStatusCode();
if (status == 201) {
//handle success responses as you see fit
} else {
//handle non-success responses as you see fit
}
}
}
private static String getPurgeJson(Set<String> pathsToPurge) {
//your code to turn the list of urls into JSON in this format:
//{"objects":["https://www.yourdomain.com/page1.html","https://www.yourdomain.com/page2.html"]}
return //JSON string such as the example above
}
private HttpRequest getHttpRequest(String json, Dictionary<String, Object> dispatcherAndAkamaiServletProperties) throws URISyntaxException, IOException, RequestSigningException {
String hostName = yourCodeToFetchConfigValues("hostname");
String accessToken = yourCodeToFetchConfigValues("accesstoken");
String clientToken = yourCodeToFetchConfigValues("clienttoken");
String clientSecret = yourCodeToFetchConfigValues("clientsecret");
String apiUrl = yourCodeToFetchConfigValues("apiurl");
String proxyServer = yourCodeToFetchConfigValues("proxyhostakamai");
int proxyPort = yourCodeToFetchConfigValues("proxyport");
HttpTransport httpTransport = new NetHttpTransport.Builder()
.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyServer, proxyPort))).build();
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
URI uri = new URI(HTTPS, hostName, apiUrl, null, null);
HttpContent body = new ByteArrayContent("application/json", json.getBytes());
HttpRequest request = requestFactory.buildPostRequest(new GenericUrl(uri), body);
HttpHeaders headers = request.getHeaders();
headers.set("Host", hostName);
ClientCredential credential = new DefaultCredential(clientToken, accessToken, clientSecret);
RequestSigner signer = new EdgeGridV1Signer(Collections.emptyList(), 1024 * 2);
return signer.sign(request, credential);
}
In addition you will likely need to update your truststore to include the certificates of the Akamai endpoints you are calling so that the SSL communication can happen.
What #Shawn has answered is mostly correct. Though you would like to have more things in plate like your custom replication agent, a custom content builder and a transport handler if you are integrating it with AEM. Also, there can be few dependency issues as well.
If you need help with all these, you can refer to below article:
https://www.linkedin.com/pulse/akamai-cache-purge-aem-through-java-code-shubham-saxena/
For a transport handler you can use below snippet:
package com.myproject.bundle.core.services.impl;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.http.entity.ContentType;
import org.apache.jackrabbit.util.Base64;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.akamai.edgegrid.signer.ClientCredential;
import com.akamai.edgegrid.signer.exceptions.RequestSigningException;
import com.akamai.edgegrid.signer.googlehttpclient.GoogleHttpClientEdgeGridRequestSigner;
import com.day.cq.replication.AgentConfig;
import com.day.cq.replication.ReplicationActionType;
import com.day.cq.replication.ReplicationException;
import com.day.cq.replication.ReplicationResult;
import com.day.cq.replication.ReplicationTransaction;
import com.day.cq.replication.TransportContext;
import com.day.cq.replication.TransportHandler;
import com.myproject.bundle.core.configuration.BaseConfigurationService;
import com.myproject.bundle.core.constants.MyConstants;
import com.myproject.bundle.core.search.services.MyProjectConfigurationService;
import com.google.api.client.http.ByteArrayContent;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.apache.ApacheHttpTransport;
/**
* Transport handler to send test and purge requests to Akamai and handle
* responses. The handler sets up basic authentication with the user/pass from
* the replication agent's transport config and sends a GET request as a test
* and POST as purge request. A valid test response is 200 while a valid purge
* response is 201.
*
* The transport handler is triggered by setting your replication agent's
* transport URL's protocol to "akamai://".
*
* The transport handler builds the POST request body in accordance with
* Akamai's Fast Purge REST API {#link https://developer.akamai.com/api/core_features/fast_purge/v3.html}
* using the replication agent properties.
*/
#Component(service = TransportHandler.class, immediate = true)
public class AkamaiTransportHandler implements TransportHandler {
/**The Solr Server Configuration Service.*/
#Reference
MyProjectConfigurationService myProjectConfigurationService;
#Reference
BaseConfigurationService baseConfigurationService;
/**Logger Instantiation for Akamai Transport Handler*/
private static final Logger LOGGER = LoggerFactory.getLogger(AkamaiTransportHandler.class);
/** Protocol for replication agent transport URI that triggers this transport handler. */
private static final String AKAMAI_PROTOCOL = "akamai://";
/**Config Pid for Akamai Flush*/
private static final String AKAMAI_FLUSH_CONFIG_PID = "com.myproject.bundle.core.configuration.AkamaiFlushConfiguration";
/** Replication agent type property name. Valid values are "arl" and "cpcode". */
private static final String PROPERTY_AKAMAI_TYPE = "type";
/** Replication agent multifield CP Code property name.*/
private static final String PROPERTY_AKAMAI_CP_CODES = "4321xxx";
/** Replication agent domain property name. Valid values are "staging" and "production". */
private static final String PROPERTY_AKAMAI_DOMAIN = "domain";
/** Replication agent action property name. Valid values are "remove" and "invalidate". */
private static final String PROPERTY_AKAMAI_ACTION = "action";
/** Replication agent default type value */
private static final String PROPERTY_AKAMAI_TYPE_DEFAULT = "url";
/** Replication agent default domain value */
private static final String PROPERTY_AKAMAI_DOMAIN_DEFAULT = "production";
/** Replication agent default action value */
private static final String PROPERTY_AKAMAI_ACTION_DEFAULT = "invalidate";
/**Transport URI*/
private static final String TRANSPORT_URI = "transportUri";
/**
* {#inheritDoc}
*/
#Override
public boolean canHandle(AgentConfig config) {
final String transportURI = config.getTransportURI();
return (transportURI != null) && (transportURI.toLowerCase().startsWith(AKAMAI_PROTOCOL));
}
/**
* {#inheritDoc}
*/
#Override
public ReplicationResult deliver(TransportContext ctx, ReplicationTransaction tx)
throws ReplicationException {
final ReplicationActionType replicationType = tx.getAction().getType();
if (replicationType == ReplicationActionType.TEST) {
return ReplicationResult.OK;
} else if (replicationType == ReplicationActionType.ACTIVATE ||
replicationType == ReplicationActionType.DEACTIVATE ||
replicationType == ReplicationActionType.DELETE) {
LOGGER.info("Replication Type in Akamai Handler: {}", replicationType);
String resourcePath = tx.getAction().getPath();
if (StringUtils.startsWith(resourcePath, myProjectConfigurationService.getContentpath())
|| StringUtils.startsWith(resourcePath, myProjectConfigurationService.getAssetpath())) {
// checking for my project specific root page and root dam path.
LOGGER.info("Calling activate in Akamai for path: {}", resourcePath);
try {
return doActivate(ctx, tx);
} catch (RequestSigningException e) {
LOGGER.error("Signing ceremony unsuccessful....");
throw new ReplicationException("Signing ceremony unsuccessful: {}", e);
} catch (IOException e) {
LOGGER.error("IO Exception in deliver \n");
throw new ReplicationException("IO Exception in deliver: {}", e);
}
}
return ReplicationResult.OK;
} else {
throw new ReplicationException("Replication action type " + replicationType + " not supported.");
}
}
private String getTransportURI(TransportContext ctx) throws IOException {
LOGGER.info("Entering getTransportURI method.");
final ValueMap properties = ctx.getConfig().getProperties();
final String AKAMAI_HOST = baseConfigurationService.getPropValueFromConfiguration(AKAMAI_FLUSH_CONFIG_PID, "akamaiHost");
final String domain = PropertiesUtil.toString(properties.get(PROPERTY_AKAMAI_DOMAIN), PROPERTY_AKAMAI_DOMAIN_DEFAULT);
final String action = PropertiesUtil.toString(properties.get(PROPERTY_AKAMAI_ACTION), PROPERTY_AKAMAI_ACTION_DEFAULT);
final String type = PropertiesUtil.toString(properties.get(PROPERTY_AKAMAI_TYPE), PROPERTY_AKAMAI_TYPE_DEFAULT);
String defaultTransportUri = MyConstants.HTTPS + AKAMAI_HOST + "/ccu/v3/"
+ action + MyConstants.BACK_SLASH + type + MyConstants.BACK_SLASH + domain;
String transporturi = PropertiesUtil.toString(properties.get(TRANSPORT_URI), defaultTransportUri);
if(StringUtils.isEmpty(transporturi)) {
return defaultTransportUri;
}
if (transporturi.startsWith(AKAMAI_PROTOCOL)) {
transporturi = transporturi.replace(AKAMAI_PROTOCOL, MyConstants.HTTPS);
}
transporturi = transporturi + "/ccu/v3/"
+ action + MyConstants.BACK_SLASH + type + MyConstants.BACK_SLASH + domain;
LOGGER.info("Exiting getTransportURI method of Akamai Transport Handler : {}", transporturi);
return transporturi;
}
/**
* Send purge request to Akamai via a POST request
*
* Akamai will respond with a 201 HTTP status code if the purge request was
* successfully submitted.
*
* #param ctx Transport Context
* #param tx Replication Transaction
* #return ReplicationResult OK if 201 response from Akamai
* #throws ReplicationException
* #throws RequestSigningException
* #throws IOException
* #throws JSONException
*/
private ReplicationResult doActivate(TransportContext ctx, ReplicationTransaction tx)
throws ReplicationException, RequestSigningException, IOException {
LOGGER.info("Inside doActivate of Akamai");
final String AKAMAI_ACCESS_TOKEN = baseConfigurationService.getPropValueFromConfiguration(AKAMAI_FLUSH_CONFIG_PID, "akamaiAccessToken");
final String AKAMAI_CLIENT_TOKEN = baseConfigurationService.getPropValueFromConfiguration(AKAMAI_FLUSH_CONFIG_PID, "akamaiClientToken");
final String AKAMAI_CLIENT_SECRET = baseConfigurationService.getPropValueFromConfiguration(AKAMAI_FLUSH_CONFIG_PID, "akamaiClientSecret");
final String AKAMAI_HOST = baseConfigurationService.getPropValueFromConfiguration(AKAMAI_FLUSH_CONFIG_PID, "akamaiHost");
ClientCredential clientCredential = ClientCredential.builder().accessToken(AKAMAI_ACCESS_TOKEN).
clientToken(AKAMAI_CLIENT_TOKEN).clientSecret(AKAMAI_CLIENT_SECRET).host(AKAMAI_HOST).build();
HttpTransport httpTransport = new ApacheHttpTransport();
HttpRequestFactory httpRequestFactory = httpTransport.createRequestFactory();
JSONObject jsonObject = createPostBody(ctx, tx);
URI uri = URI.create(getTransportURI(ctx));
HttpRequest request = httpRequestFactory.buildPostRequest(new GenericUrl(uri), ByteArrayContent.fromString("application/json", jsonObject.toString()));
final HttpResponse response = sendRequest(request, ctx, clientCredential);
if (response != null) {
final int statusCode = response.getStatusCode();
LOGGER.info("Response code recieved: {}", statusCode);
if (statusCode == HttpStatus.SC_CREATED) {
return ReplicationResult.OK;
}
}
return new ReplicationResult(false, 0, "Replication failed");
}
/**
* Build preemptive basic authentication headers and send request.
*
* #param request The request to send to Akamai
* #param ctx The TransportContext containing the username and password
* #return JSONObject The HTTP response from Akamai
* #throws ReplicationException if a request could not be sent
* #throws RequestSigningException
*/
private HttpResponse sendRequest(final HttpRequest request, final TransportContext ctx,
ClientCredential clientCredential)
throws ReplicationException, RequestSigningException {
LOGGER.info("Inside Send Request method of Akamai");
final String auth = ctx.getConfig().getTransportUser() + ":" + ctx.getConfig().getTransportPassword();
final String encodedAuth = Base64.encode(auth);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setAuthorization("Basic " + encodedAuth);
httpHeaders.setContentType(ContentType.APPLICATION_JSON.getMimeType());
request.setHeaders(httpHeaders);
GoogleHttpClientEdgeGridRequestSigner requestSigner = new GoogleHttpClientEdgeGridRequestSigner(clientCredential);
requestSigner.sign(request);
HttpResponse response;
try {
response = request.execute();
} catch (IOException e) {
LOGGER.error("IO Exception in sendRequest");
throw new ReplicationException("Could not send replication request.", e);
}
LOGGER.info("Sucessfully executed Send Request for Akamai");
return response;
}
/**
* Build the Akamai purge request body based on the replication agent
* settings and append it to the POST request.
*
* #param request The HTTP POST request to append the request body
* #param ctx TransportContext
* #param tx ReplicationTransaction
* #throws ReplicationException if errors building the request body
*/
private JSONObject createPostBody(final TransportContext ctx,
final ReplicationTransaction tx) throws ReplicationException {
final ValueMap properties = ctx.getConfig().getProperties();
final String type = PropertiesUtil.toString(properties.get(PROPERTY_AKAMAI_TYPE), PROPERTY_AKAMAI_TYPE_DEFAULT);
JSONObject json = new JSONObject();
JSONArray purgeObjects = null;
if (type.equals(PROPERTY_AKAMAI_TYPE_DEFAULT)) {
try {
String content = IOUtils.toString(tx.getContent().getInputStream(), Charset.defaultCharset());
if (StringUtils.isNotBlank(content)) {
LOGGER.info("Content of Akamai is:\n {}", content);
purgeObjects = new JSONArray(content);
}
} catch (JSONException | IOException e) {
throw new ReplicationException("Could not retrieve content from content builder", e);
}
}
if (null != purgeObjects && purgeObjects.length() > 0) {
try {
json.put("objects", purgeObjects);
} catch (JSONException e) {
throw new ReplicationException("Could not build purge request content", e);
}
} else {
throw new ReplicationException("No CP codes or pages to purge");
}
return json;
}
}
Also you would need following dependencies:
<dependency>
<groupId>com.akamai.edgegrid</groupId>
<artifactId>edgegrid-signer-google-http-client</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>com.akamai.edgegrid</groupId>
<artifactId>edgegrid-signer-core</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client</artifactId>
<version>1.22.0</version>
</dependency>
For my case, the bundle did not resolve and I had to add below dependencies to resolve it. It might differ in your case though:
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-api</artifactId>
<version>0.24.0</version>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-contrib-http-util</artifactId>
<version>0.24.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-context</artifactId>
<version>1.24.0</version>
</dependency>
<Import-Package>
javax.annotation;version=0.0.0,
</Import-Package>
For the line : "IOUtils.toString(tx.getContent().getInputStream(), Charset.defaultCharset());", it internally calls your custom content builder (you can refer the article link I provided earlier). However, you can directly make you content objects in transport handler itself as the transport handler is creating it's own request anyways. However, if you need the session you need to implement the ContentBuilder since TransportHandler implementations do not provide that leverage.
Thanks,
Shubham
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
So, i'm getting slightly familiar with html, css and frameworks in general and i have a fair understanding of Java. However, i can only see how you can make inbuilt functions and computations with Javascript that you add to your html file. But i don't understand how it works with say a Java program on your computer that the website would fetch data and information from. Can anyone explain that? I couldn't find any good answers on the internet.
Say i want to compute the value 2+3 with Java on a server and then fetch that value and display it on the website. How would i do that?
I achieve this functionality by sending an ajax request via javascript to a java servlet on the server here is an example that I use:
Say you have a link:
<a href="#" onclick = 'shipProduct(1)'>Test</a>
When this link is clicked it will look for the corresponding javscript function, which in my case is:
/**
*
* #param {type} action
* #param {type} bundleId
* #returns {undefined}
*/
function shipProduct(bundleId)
{
$.ajax
({
url: "/FlcErp-war/ShipmentServlet", //this is the name of the serverlet in your project
type: "GET", // the type of your request
data: _action + "=addToShipped&bundleId=" + bundleId,
success: function (content)
{
if (content.substring(0, 1) == '_')
{
alert(content);
}
else
{
//rebuild shipment tables to show updated
//information about the item
buildShipmentQueue();
}
},
error: function (xhr, status, error) {
alert(xhr.responseText);
alert(status);
alert(error);
}
});
}
What I did was have have an annotated java servlet to serve my request:
your doPost and doGet will handle your post and get requests
/**
*
* #author samo
*/
#WebServlet("/ShipmentServlet")
public class ShipmentServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String _addToShipped = "addToShipped";
private static final String _bundleId = "bundleId";
private static final String _shipmentId = "shipmentId";
private static final String _productId = "productId";
private static final String _updateQueue = "updateQueue";
private static final String _unship = "unship";
private static final String _setInSession = "setInSession";
private static final String _externalBundleId = "externalBundleId";
private static final String _plywood = "P";
private static final String _veneer = "V";
private static final String _lumber = "L";
private static final String _bundle = "Bundle";
private static final String _list = "List";
private boolean multipleActions;
private String[] actions;
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
protected void processBundleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException, NamingException, CloneNotSupportedException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
this.actions = null;
//this is where we will get the actions to process
//if there is more than one action the string will contain
// a comma as a delimiter
String action = request.getParameter("_action");
InitialContext ctx = new InitialContext();
LoadShipmentController lsc = (LoadShipmentController) ctx.lookup("loadShipmentController");
switch (action) {
case _addToShipped:
shipProduct(request, out);
break;
case _updateQueue:
Shipment shipment = lsc.getCurrent();
String type = shipment.getShipmentType();
String shipmentQueue = "";
switch (type) {
case _veneer:
shipmentQueue = lsc.getVeneerShipmentQueue();
break;
case _plywood:
shipmentQueue = lsc.getShipmentQueue();
break;
case _lumber:
shipmentQueue = lsc.getShipmentQueue();
break;
}
out.println(shipmentQueue);
break;
case _unship:
unshipProduct(request, out);
break;
case _setInSession:
String bundleId = request.getParameter(_bundleId);
lsc.setBundleId(bundleId);
break;
case _list:
out.println(lsc.getBundleAndProductListString());
break;
// setSessionVariable(_externalBundleId, bundleId);
}
}
}
public void shipProduct(HttpServletRequest request, PrintWriter out) throws NamingException, CloneNotSupportedException {
Integer bundleId = Integer.valueOf(request.getParameter(_bundleId));
InitialContext ctx = new InitialContext();
ShipmentController shipmentController = (ShipmentController) ctx.lookup("shipmentController");
LoadShipmentController loadShipmentController = (LoadShipmentController) ctx.lookup("loadShipmentController");
// getting the product from the bundle, because that's all we care about
Product product = shipmentController.loadBundle(bundleId).getProduct();
String type = product.getProductType();
//because the way we ships differs depending on the product type I need to
//check first mainly for veneer shipments because their bundle count is not
//predetermined
boolean loaded = false;
switch (type) {
case _veneer:
loaded = loadShipmentController.loadVeneerProduct(product, bundleId);
break;
case _plywood:
loaded = loadShipmentController.loadPlywoodProduct(product, bundleId);
break;
case _lumber:
loaded = loadShipmentController.loadLumberProduct(product, bundleId);
break;
}
if(!loaded)
{
out.println("_" + loadShipmentController.getErrors());
}
}
public void unshipProduct(HttpServletRequest request, PrintWriter out) throws NamingException {
Integer bundleId = Integer.valueOf(request.getParameter(_bundle));
InitialContext ctx = new InitialContext();
LoadShipmentController loadShipmentController = (LoadShipmentController) ctx.lookup("loadShipmentController");
boolean unship = loadShipmentController.unshipByBundleId(bundleId);
if (!unship) {
String error = loadShipmentController.getErrors();
out.println("Error:" + error);
}
}
private void setSessionVariable(String name, String value) {
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext externalContext = context.getExternalContext();
HttpSession session = (HttpSession) externalContext.getSession(false);
session.setAttribute(name, value);
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
processBundleRequest(request, response);
} catch (NamingException ex) {
Logger.getLogger(ShipmentServlet.class.getName()).log(Level.SEVERE, null, ex);
} catch (CloneNotSupportedException ex) {
Logger.getLogger(ShipmentServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Handles the HTTP <code>POST</code> method.
*
* #param request servlet request
* #param response servlet response
* #throws ServletException if a servlet-specific error occurs
* #throws IOException if an I/O error occurs
*/
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
I am trying to use the Glide Android library to load images from urls such as
String urlString = "https://images.example.com/is/image/example/EXMPL1234_021347_1?$cdp_thumb$";
When I enter the above url string into Glide,
Glide.with(mContext).load(urlString).into(view);
the address it actually hits is:
https://images.example.com/is/image/example/EXMPL1234_021347_1?%24cdp_thumb%24
which is for me incorrect. The $ must be preserved.
I tried then to pass in java.net.URL object in, but I again seem unable to construct one that preserves the $ character inside the query.
Here is an example of something I tried:
URL url = null;
try
{
url = new URL(urlStr);
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath()+"?$hp_wn_thumb_app$", "", url
.getRef()
+"?$hp_wn_thumb_app$");
url = uri.toURL();
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
catch (URISyntaxException e)
{
e.printStackTrace();
}
I would be very grateful if someone could suggest a solution. to making non-urlencoded java URL objects.
This solves this original problem.
package com.techventus;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.load.model.Headers;
import java.net.MalformedURLException;
import java.net.URL;
/*
// Necessary to help make correct calls to the API which does not apply and //URL special Character correction.
*/
public class CorrectGlideUrl extends GlideUrl
{
String urlString;
public CorrectGlideUrl(URL url)
{
super(url);
}
public CorrectGlideUrl(String url)
{
super(url);
urlString = url;
}
public CorrectGlideUrl(URL url, Headers headers)
{
super(url, headers);
}
public CorrectGlideUrl(String url, Headers headers)
{
super(url, headers);
}
/**
*
* Returns a properly escaped {#link String} url that can be used to make http/https requests.
*
* #see #toURL()
* #see #getCacheKey()
*/
#Override
public String toStringUrl() {
return urlString.replace("%24","$");
// return getSafeStringUrl();
}
/**
* Returns a properly escaped {#link java.net.URL} that can be used to make http/https requests.
*
* #see #toStringUrl()
* #see #getCacheKey()
* #throws MalformedURLException
*/
#Override
public URL toURL() throws MalformedURLException {
return getSafeUrl();
}
// See http://stackoverflow.com/questions/3286067/url-encoding-in-android. Although the answer using URI would work,
// using it would require both decoding and encoding each string which is more complicated, slower and generates
// more objects than the solution below. See also issue #133.
private URL getSafeUrl() throws MalformedURLException {
return null;
}
}
My first implementation using the Jersey client code with cookies does not successfully maintain session to next call. What is suspicious to me is that the method
Builder javax.ws.rs.client.Invocation.Builder.cookie(String s, String s1)
does not return a different instance of the builder. Shouldn't it? Either way, my login request is denied with message "Your session expired due to inactivity.", which seems to imply to me that the request isn't arriving with the same session id as previous.
See anything wrong with this code? The culprit in question is method #applyCookies(Builder) which does not return anything different after the cookies have been set.
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import org.apache.log4j.Logger;
import org.glassfish.jersey.client.filter.HttpBasicAuthFilter;
/**
* A JAX-RS <a href="https://jax-rs-spec.java.net/" /> connector that uses
* Jersey <a href="https://jersey.java.net"/> as the API to create a client that
* will connect to a remote REST service.
*/
public class JerseyConnector extends WebServiceConnector
{
/** Debug logger. */
protected static final Logger logger = Logger.getLogger(JerseyConnector.class);
/**
* Simple test execution method.
*
* #param args
* #throws MessageException
*/
public static void main(String[] args) throws MessageException
{
JerseyConnector conn = new JerseyConnector();
conn.setProviderURL("http://somehost.somewhere.com:7203/rest");
conn.open();
String sessConf = (String)conn.send("initiateSession");
HashMap<String,String> content = new HashMap<String,String>(3);
content.put("sessionConfirmation", sessConf);
content.put("password", "password");
content.put("login", "joe");
String body = JSONMapFormatter.toJSON(content);
String loginResponse = (String)conn.send(new RESTRequest("login", body, HttpMethod.POST));
System.out.println(loginResponse);
}
protected WebTarget webTarget;
protected Map<String,Cookie> cookies;
/**
* Calls the {#link #webTarget} and provides the {#link String} response.
* The request method defaults to {#link HttpMethod#GET}.
* <p>
* If the <code>message</code> is a {#link String}, it is assumed to be the
* suffix URI to append to the provider URL of the {#link #webTarget},
* unless the string begins with a "{", in which case it is assumed to be
* the JSON request body to send.
* <p>
* If the <code>message</code> is a {#link RESTRequest}, the path, body and
* HTTP method will be determined from that.
* <p>
* Otherwise, the <code>toString()</code> version of the message will be
* sent as the body of the message.
*
* #see WebTarget#path(String)
* #see WebTarget#request()
* #see #getProviderURL()
* #see oracle.retail.stores.commext.connector.webservice.WebServiceConnector#send(java.io.Serializable)
*/
#Override
protected Serializable send(Serializable message) throws MessageException
{
RESTRequest request = null;
// determine path and body content if any
if (message instanceof RESTRequest)
{
request = (RESTRequest)message;
}
else
{
request = new RESTRequest();
String messageString = message.toString();
if (messageString.startsWith("{"))
{
request.body = (String)message;
}
else
{
request.path = (String)message;
}
}
// send request, get response
Response response = sendRequest(webTarget, request);
logger.debug("Response received.");
// remember cookies that came in the response
rememberCookies(response);
// return response as a string
return response.readEntity(String.class);
}
/* (non-Javadoc)
* #see oracle.retail.stores.commext.connector.webservice.WebServiceConnector#openConnector()
*/
#Override
protected void openConnector() throws MessageException
{
super.openConnector();
// create a client
logger.debug("Creating new client.");
Client client = ClientBuilder.newClient();
// register the auth creds
if (!Util.isEmpty(getUserName()))
{
logger.debug("Registering user credentials with client.");
client.register(new HttpBasicAuthFilter(getUserName(), getPassword()));
}
else
{
logger.info("No credentials specified for \"" + getName() + "\".");
}
// open the target url
if (logger.isDebugEnabled())
{
logger.debug("Creating webTarget with \"" + getProviderURL() + "\".");
}
webTarget = client.target(getProviderURL());
// construct a new cookie map
cookies = new HashMap<String,Cookie>(3);
}
/**
* Returns the response after invoking the specified request on the specified
* target.
*
* #param target
* #param request
* #return
*/
protected Response sendRequest(WebTarget target, RESTRequest request)
{
// retarget destination
if (request.path != null)
{
target = target.path(request.path);
}
if (logger.isDebugEnabled())
{
logger.debug("Making service request " + request);
}
// build request
Builder builder = target.request(MediaType.APPLICATION_JSON_TYPE);
// apply cookies
builder = applyCookies(builder);
// call webservice and return response as a string
if (HttpMethod.POST.equals(request.httpMethod))
{
return builder.post(Entity.entity(request.body, MediaType.APPLICATION_JSON));
}
else if (HttpMethod.PUT.equals(request.httpMethod))
{
return builder.put(Entity.entity(request.body, MediaType.APPLICATION_JSON));
}
else if (HttpMethod.DELETE.equals(request.httpMethod))
{
return target.request(request.body).delete();
}
// default to HttpMethod.GET
return target.request(request.body).get();
}
/**
* Apply all the cookies in the cookies map onto the request builder.
*
* #param builder
* #return the cookied builder
*/
private Builder applyCookies(Builder builder)
{
if (logger.isDebugEnabled())
{
logger.debug("Applying " + cookies.size() + " cookies: " + cookies);
}
for (Cookie cookie : cookies.values())
{
builder = builder.cookie(cookie.getName(), cookie.getValue());
}
return builder;
}
/**
* Put all the cookies from the response into the map of cookies being
* remembered.
*
* #param response
*/
private void rememberCookies(Response response)
{
Map<String,NewCookie> newCookies = response.getCookies();
if (logger.isDebugEnabled())
{
logger.debug("Remembering " + newCookies.size() + " cookies: " + newCookies);
}
cookies.putAll(newCookies);
}
// -------------------------------------------------------------------------
/**
* Request parameters that can be sent to this connector in order to specify
* the path (URL sub-sequence) and body (contents) of the request message to
* send.
*/
public static class RESTRequest implements Serializable
{
private static final long serialVersionUID = 5675990073393175886L;
private String path;
private String body;
private String httpMethod;
/**
* Internal constructor
*/
private RESTRequest()
{
}
/**
* #param path
* #param body
*/
public RESTRequest(String path, String body)
{
this.path = path;
this.body = body;
}
/**
* #param path
* #param body
* #param httpMethod see values at {#link javax.ws.rs.HttpMethod}
*/
public RESTRequest(String path, String body, String httpMethod)
{
this.path = path;
this.body = body;
this.httpMethod = httpMethod;
}
/**
* #return the path
*/
public String getPath()
{
return path;
}
/**
* #return the body
*/
public String getBody()
{
return body;
}
/**
* #return the httpMethod
* #see javax.ws.rs.HttpMethod
*/
public String getHttpMethod()
{
return httpMethod;
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString()
{
return "RESTRequest[" + httpMethod + ", " + path + ", with body=" + body + "]";
}
}
}
The defect was in the bottom of the #sendRequest() method. It was ignoring the Builder object returned and re-using the WebTarget to create a new request (which creates a new builder. The last three lines of code in that method should have been:
return builder.buildDelete().invoke();
}
// default to HttpMethod.GET
return builder.buildGet().invoke();