Expand my Community achievements bar.

Guidelines for the Responsible Use of Generative AI in the Experience Cloud Community.
SOLVED

External Jar not getting installed in Felix | Akamai Flush

Avatar

Level 2

Hi All

 

I am trying to flush the Akamai Cache through java code by invoking there open APIs.

Followed the link from the Akamai Forum for the steps.(https://community.akamai.com/customers/s/article/OPEN-API-Fast-Purge-and-Java)

But it has below imports for packages which are not available in public repositories and hence could not find any dependency to download the same. 

 

import com.akamai.edgegrid.auth.ClientCredential;

import com.akamai.edgegrid.auth.DefaultCredential;

import com.akamai.edgegrid.auth.EdgeGridV1Signer;

import com.akamai.edgegrid.auth.RequestSigner;

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;

 

Now I have found a jar and downloaded from the below url.

 http://www.java2s.com/Code/Jar/g/Downloadgoogleapiclient141betajar.htm

 

I have converted the above jar to bundle and placed it in the install folder of our code base and added an embedded dependency as below in our ui.apps/pom. Still the bundle is not getting deployed to felix.

 

Could you please help me in this case either any simple solution to invoke their open apis or issue of jar getting deployed to felix. Or please suggest any other pom file to be updated or the corrected embedded/dependency tags if needed.

 

Any quick help is much appreciated. Please let me know if any other details needed for this.

 

 

Regards

Bishnu

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

can you check the below example

 

https://www.linkedin.com/pulse/akamai-cache-purge-aem-through-java-code-shubham-saxena/

 

=====================

 

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;


import javax.jcr.Session;


import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.jcr.resource.JcrResourceConstants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import com.day.cq.commons.Externalizer;
import com.day.cq.replication.ContentBuilder;
import com.day.cq.replication.ReplicationAction;
import com.day.cq.replication.ReplicationContent;
import com.day.cq.replication.ReplicationContentFactory;
import com.day.cq.replication.ReplicationException;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import com.myproject.bundle.core.constants.FsbpConstants;
import com.myproject.bundle.core.search.services.MyProjectConfigurationService;


/**
 * Akamai content builder to create replication content containing a JSON array
 * of URLs for Akamai to purge through the Akamai Transport Handler. This class
 * takes the internal resource path and converts it to external URLs as well as
 * adding vanity URLs and pages that may Sling include the activated resource.
 */
@Component(service = ContentBuilder.class,
		   property = {"name=myProjectAkamai", "value=akamai"},
		   immediate = true)
public class AkamaiContentBuilder implements ContentBuilder {


    @Reference
    private ResourceResolverFactory resolverFactory;


    /** The name of the replication agent */
    public static final String NAME = "myProjectAkamai";


    /**
     * The serialization type as it will display in the replication
     * agent edit dialog selection field.
     */
    public static final String TITLE = "My Project Akamai Purge Content Builder";
    
    @Reference
	MyProjectConfigurationService myProjectConfigurationService;
    
    private static final Logger LOG = LoggerFactory.getLogger(AkamaiContentBuilder.class);


    /**
     * {@inheritDoc}
     */
    @Override
    public ReplicationContent create(Session session, ReplicationAction action,
            ReplicationContentFactory factory) throws ReplicationException {
        return create(session, action, factory, null);
    }


    /**
     * Create the replication content containing the public facing URLs for
     * Akamai to purge.
     */
    @Override
    public ReplicationContent create(Session session, ReplicationAction action,
            ReplicationContentFactory factory, Map<String, Object> parameters)
            throws ReplicationException {


        final String path = action.getPath();


        ResourceResolver resolver = null;
        JSONArray jsonArray = new JSONArray();


        if (StringUtils.isNotBlank(path)) {
        	HashMap<String, Object> sessionMap = new HashMap<>();
            sessionMap.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, session);
            try {
            	resolver = resolverFactory.getResourceResolver(sessionMap);
            
        	if (StringUtils.contains(path, myProjectConfigurationService.getContentpath())) { // my project's specific page root path - /content/myproject
        		jsonArray = createPageContent(resolver, jsonArray, path);
        	} else if (StringUtils.contains(path, myProjectConfigurationService.getAssetpath())) { // my project's specific dam root path - /content/dam/myproject
        		jsonArray = createAssetContent(resolver, jsonArray, path);
        	}
            } catch (LoginException e) {
            	LOG.error("Could not retrieve Page Manager", e);
            }
            return createContent(factory, jsonArray);
        }


        return ReplicationContent.VOID;
    }


    private JSONArray createPageContent(ResourceResolver resolver, JSONArray jsonArray, String path) {
    	PageManager pageManager = resolver.adaptTo(PageManager.class);
		if (null != pageManager) {
		    Page purgedPage = pageManager.getContainingPage(path);
		    Externalizer externalizer = resolver.adaptTo(Externalizer.class);
			if (null != purgedPage && null != externalizer) {
				final String link = externalizer.externalLink(resolver, "firestonebpco", path);
				jsonArray.put(link);
				LOG.info("Page link added: {}", link);
			    final String vanityUrl = purgedPage.getVanityUrl();
			
			    if (StringUtils.isNotBlank(vanityUrl)) {
			        jsonArray.put(vanityUrl);
			        LOG.info("Vanity URL added: {}", vanityUrl);
			    }
			} else {
			    jsonArray.put(path);
			    LOG.info("Page Resource path added: {}", path);
			}
		}
		return jsonArray;
    }
    
    private JSONArray createAssetContent(ResourceResolver resolver, JSONArray jsonArray, String path) {
    	Resource purgedAssetResource = resolver.getResource(path);
    	Externalizer externalizer = resolver.adaptTo(Externalizer.class);
		if (null != purgedAssetResource && null != externalizer) {
			final String assetLink = externalizer.externalLink(resolver, "firestonebpco", path);
			jsonArray.put(assetLink);
			LOG.info("Asset link added: {}", assetLink);
		} else {
		    jsonArray.put(path);
		    LOG.info("Asset Resource path added: {}", path);
		}
		return jsonArray;
    }
    
    /**
     * Create the replication content containing 
     *
     * @param factory Factory to create replication content
     * @param jsonArray JSON array of URLS to include in replication content
     * @return replication content
     *
     * @throws ReplicationException if an error occurs
     */
    private ReplicationContent createContent(final ReplicationContentFactory factory,
            final JSONArray jsonArray) throws ReplicationException {


        Path tempFile;


        try {
            tempFile = Files.createTempFile("akamai_purge_agent", ".tmp");
        } catch (IOException e) {
            throw new ReplicationException("Could not create temporary file", e);
        }


        try (BufferedWriter writer = Files.newBufferedWriter(tempFile, Charset.forName("UTF-8"))) {
            writer.write(jsonArray.toString());
            writer.flush();


            return factory.create("text/plain", tempFile.toFile(), true);
        } catch (IOException e) {
            throw new ReplicationException("Could not write to temporary file", e);
        }
    }


    /**
     * {@inheritDoc}
     *
     * @return {@value #NAME}
     */
    @Override
    public String getName() {
        return NAME;
    }


    /**
     * {@inheritDoc}
     *
     * @return {@value #TITLE}
     */
    @Override
    public String getTitle() {
        return TITLE;
    }
}
=============================

 

https://github.com/AvionosLLC/purge-surgeon/tree/develop

 

View solution in original post

3 Replies

Avatar

Community Advisor

Did you check the latest REST API calls

 

https://techdocs.akamai.com/developer/docs/postman-make-api-calls

 

Create API Client in Akamai - Create an Akamai API client - This client need to have a PURGE functionality or purge method

Then Generate API Access Credentials (like your site id, secret key etc)

Then Write a Service AEM - Create service in AEM to making a request to Purge

- write a scheduler or CTA - when to trigger this service.

 

 

public class AkamaiPurgeService {
   
public void clearCache(String url) {
httpclient --- Akamai connection
Header for authentication
trigger purge method
get response
}
}

Thanks @SureshDhulipudi for your response.

 

If you can paste any sample reference code for this would be of real help.

 

Actually the following method execute the request.

 

private HttpResponse sendRequest(HttpPost request, String baseurl, String purgeurlpath, String token, String accesstoken, String secret, String protocol) throws ReplicationException {
if (baseurl != null &&
purgeurlpath != null &&
token != null &&
accesstoken != null &&
secret != null &&
protocol != null &&
request != null) {
String body = null;

try {
body = read(request.getEntity().getContent());
} catch (IOException e) {
logReplicationEventInfoStatement("IOException occurred while reading the tmp file created bu Akamai Content builder " + e);
}

String clientToken = "";
try {
clientToken = cryptoSupport.isProtected(token) ? cryptoSupport.unprotect(token) : token;
} catch (CryptoException e) {
e.printStackTrace();
throw new ReplicationException("Could not unprotect token.", e);
}
String clientAccessToken = "";
try {
clientAccessToken = cryptoSupport.isProtected(accesstoken) ? cryptoSupport.unprotect(accesstoken) : accesstoken;
} catch (CryptoException e) {
throw new ReplicationException("Could not unprotect accesstoken.", e);
}
String clientSecret = "";
try {
clientSecret = cryptoSupport.isProtected(secret) ? cryptoSupport.unprotect(secret) : secret;
} catch (CryptoException e) {
throw new ReplicationException("Could not unprotect secret.", e);
}

String authHeader = generateAuthHeader(clientToken, clientAccessToken);
String bodyHash = crypto(body, clientSecret);

String data = StringUtils.join(getDataToSign(request, authHeader, bodyHash, baseurl, purgeurlpath, protocol), "\t");
String authorizationHeader = authHeader + "signature=" + crypto(data, clientSecret);

request.setHeader(HttpHeaders.AUTHORIZATION, authorizationHeader);
request.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType());

HttpResponse response;

HttpClient client = HttpClientBuilder.create()
.addInterceptorFirst(new ApacheHttpClientEdgeGridInterceptor(getClientCredential(clientAccessToken, clientToken, clientSecret, baseurl)))
.setRoutePlanner(new ApacheHttpClientEdgeGridRoutePlanner(getClientCredential(clientAccessToken, clientToken, clientSecret, baseurl)))
.setConnectionTimeToLive(1000, TimeUnit.MILLISECONDS)
.build();

try {
response = client.execute(request);
} catch (IOException e) {
throw new ReplicationException("Could not send replication request.", e);
}

return response;
}
return null;
}

 

However the request object used above needs ReplicationTransaction object. How we would be able to pass this object is a concern. (request.setEntity(createPostBody(tx, domain, protocol, additionalTrimPath, excludepaths));)

Hence we were thinking of the open api approach.

If we could help me with that, it would be of great help.

 

Regards

Bishnu

Avatar

Correct answer by
Community Advisor

can you check the below example

 

https://www.linkedin.com/pulse/akamai-cache-purge-aem-through-java-code-shubham-saxena/

 

=====================

 

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;


import javax.jcr.Session;


import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.jcr.resource.JcrResourceConstants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import com.day.cq.commons.Externalizer;
import com.day.cq.replication.ContentBuilder;
import com.day.cq.replication.ReplicationAction;
import com.day.cq.replication.ReplicationContent;
import com.day.cq.replication.ReplicationContentFactory;
import com.day.cq.replication.ReplicationException;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import com.myproject.bundle.core.constants.FsbpConstants;
import com.myproject.bundle.core.search.services.MyProjectConfigurationService;


/**
 * Akamai content builder to create replication content containing a JSON array
 * of URLs for Akamai to purge through the Akamai Transport Handler. This class
 * takes the internal resource path and converts it to external URLs as well as
 * adding vanity URLs and pages that may Sling include the activated resource.
 */
@Component(service = ContentBuilder.class,
		   property = {"name=myProjectAkamai", "value=akamai"},
		   immediate = true)
public class AkamaiContentBuilder implements ContentBuilder {


    @Reference
    private ResourceResolverFactory resolverFactory;


    /** The name of the replication agent */
    public static final String NAME = "myProjectAkamai";


    /**
     * The serialization type as it will display in the replication
     * agent edit dialog selection field.
     */
    public static final String TITLE = "My Project Akamai Purge Content Builder";
    
    @Reference
	MyProjectConfigurationService myProjectConfigurationService;
    
    private static final Logger LOG = LoggerFactory.getLogger(AkamaiContentBuilder.class);


    /**
     * {@inheritDoc}
     */
    @Override
    public ReplicationContent create(Session session, ReplicationAction action,
            ReplicationContentFactory factory) throws ReplicationException {
        return create(session, action, factory, null);
    }


    /**
     * Create the replication content containing the public facing URLs for
     * Akamai to purge.
     */
    @Override
    public ReplicationContent create(Session session, ReplicationAction action,
            ReplicationContentFactory factory, Map<String, Object> parameters)
            throws ReplicationException {


        final String path = action.getPath();


        ResourceResolver resolver = null;
        JSONArray jsonArray = new JSONArray();


        if (StringUtils.isNotBlank(path)) {
        	HashMap<String, Object> sessionMap = new HashMap<>();
            sessionMap.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, session);
            try {
            	resolver = resolverFactory.getResourceResolver(sessionMap);
            
        	if (StringUtils.contains(path, myProjectConfigurationService.getContentpath())) { // my project's specific page root path - /content/myproject
        		jsonArray = createPageContent(resolver, jsonArray, path);
        	} else if (StringUtils.contains(path, myProjectConfigurationService.getAssetpath())) { // my project's specific dam root path - /content/dam/myproject
        		jsonArray = createAssetContent(resolver, jsonArray, path);
        	}
            } catch (LoginException e) {
            	LOG.error("Could not retrieve Page Manager", e);
            }
            return createContent(factory, jsonArray);
        }


        return ReplicationContent.VOID;
    }


    private JSONArray createPageContent(ResourceResolver resolver, JSONArray jsonArray, String path) {
    	PageManager pageManager = resolver.adaptTo(PageManager.class);
		if (null != pageManager) {
		    Page purgedPage = pageManager.getContainingPage(path);
		    Externalizer externalizer = resolver.adaptTo(Externalizer.class);
			if (null != purgedPage && null != externalizer) {
				final String link = externalizer.externalLink(resolver, "firestonebpco", path);
				jsonArray.put(link);
				LOG.info("Page link added: {}", link);
			    final String vanityUrl = purgedPage.getVanityUrl();
			
			    if (StringUtils.isNotBlank(vanityUrl)) {
			        jsonArray.put(vanityUrl);
			        LOG.info("Vanity URL added: {}", vanityUrl);
			    }
			} else {
			    jsonArray.put(path);
			    LOG.info("Page Resource path added: {}", path);
			}
		}
		return jsonArray;
    }
    
    private JSONArray createAssetContent(ResourceResolver resolver, JSONArray jsonArray, String path) {
    	Resource purgedAssetResource = resolver.getResource(path);
    	Externalizer externalizer = resolver.adaptTo(Externalizer.class);
		if (null != purgedAssetResource && null != externalizer) {
			final String assetLink = externalizer.externalLink(resolver, "firestonebpco", path);
			jsonArray.put(assetLink);
			LOG.info("Asset link added: {}", assetLink);
		} else {
		    jsonArray.put(path);
		    LOG.info("Asset Resource path added: {}", path);
		}
		return jsonArray;
    }
    
    /**
     * Create the replication content containing 
     *
     * @param factory Factory to create replication content
     * @param jsonArray JSON array of URLS to include in replication content
     * @return replication content
     *
     * @throws ReplicationException if an error occurs
     */
    private ReplicationContent createContent(final ReplicationContentFactory factory,
            final JSONArray jsonArray) throws ReplicationException {


        Path tempFile;


        try {
            tempFile = Files.createTempFile("akamai_purge_agent", ".tmp");
        } catch (IOException e) {
            throw new ReplicationException("Could not create temporary file", e);
        }


        try (BufferedWriter writer = Files.newBufferedWriter(tempFile, Charset.forName("UTF-8"))) {
            writer.write(jsonArray.toString());
            writer.flush();


            return factory.create("text/plain", tempFile.toFile(), true);
        } catch (IOException e) {
            throw new ReplicationException("Could not write to temporary file", e);
        }
    }


    /**
     * {@inheritDoc}
     *
     * @return {@value #NAME}
     */
    @Override
    public String getName() {
        return NAME;
    }


    /**
     * {@inheritDoc}
     *
     * @return {@value #TITLE}
     */
    @Override
    public String getTitle() {
        return TITLE;
    }
}
=============================

 

https://github.com/AvionosLLC/purge-surgeon/tree/develop